@buoy-gg/license 7.0.44 → 7.0.46

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 (69) hide show
  1. package/lib/commonjs/LicenseManager.js +2 -2
  2. package/lib/commonjs/config.js +2 -2
  3. package/lib/commonjs/devToken.js +6 -0
  4. package/lib/commonjs/headless.js +1 -1
  5. package/lib/commonjs/hooks.js +2 -2
  6. package/lib/commonjs/index.js +2 -2
  7. package/lib/commonjs/index.web.js +2 -2
  8. package/lib/commonjs/nodeSession.js +6 -0
  9. package/lib/commonjs/serviceKey.js +6 -0
  10. package/lib/commonjs/sessionManager.js +6 -0
  11. package/lib/commonjs/sessionToken.js +6 -0
  12. package/lib/commonjs/syncCredential.js +6 -0
  13. package/lib/module/LicenseManager.js +1 -1
  14. package/lib/module/config.js +1 -1
  15. package/lib/module/devToken.js +6 -0
  16. package/lib/module/headless.js +1 -1
  17. package/lib/module/hooks.js +1 -1
  18. package/lib/module/index.js +1 -1
  19. package/lib/module/index.web.js +1 -1
  20. package/lib/module/nodeSession.js +6 -0
  21. package/lib/module/serviceKey.js +6 -0
  22. package/lib/module/sessionManager.js +6 -0
  23. package/lib/module/sessionToken.js +6 -0
  24. package/lib/module/syncCredential.js +6 -0
  25. package/lib/typescript/commonjs/LicenseManager.d.ts +26 -2
  26. package/lib/typescript/commonjs/config.d.ts +7 -0
  27. package/lib/typescript/commonjs/devToken.d.ts +27 -0
  28. package/lib/typescript/commonjs/headless.d.ts +9 -0
  29. package/lib/typescript/commonjs/hooks.d.ts +11 -0
  30. package/lib/typescript/commonjs/index.d.ts +7 -0
  31. package/lib/typescript/commonjs/index.web.d.ts +7 -0
  32. package/lib/typescript/commonjs/nodeSession.d.ts +86 -0
  33. package/lib/typescript/commonjs/serviceKey.d.ts +55 -0
  34. package/lib/typescript/commonjs/sessionManager.d.ts +170 -0
  35. package/lib/typescript/commonjs/sessionToken.d.ts +64 -0
  36. package/lib/typescript/commonjs/syncCredential.d.ts +11 -0
  37. package/lib/typescript/module/LicenseManager.d.ts +26 -2
  38. package/lib/typescript/module/config.d.ts +7 -0
  39. package/lib/typescript/module/devToken.d.ts +27 -0
  40. package/lib/typescript/module/headless.d.ts +9 -0
  41. package/lib/typescript/module/hooks.d.ts +11 -0
  42. package/lib/typescript/module/index.d.ts +7 -0
  43. package/lib/typescript/module/index.web.d.ts +7 -0
  44. package/lib/typescript/module/nodeSession.d.ts +86 -0
  45. package/lib/typescript/module/serviceKey.d.ts +55 -0
  46. package/lib/typescript/module/sessionManager.d.ts +170 -0
  47. package/lib/typescript/module/sessionToken.d.ts +64 -0
  48. package/lib/typescript/module/syncCredential.d.ts +11 -0
  49. package/lib/web/chunks/LicenseManager-HPGEBROD.mjs +1 -0
  50. package/lib/web/chunks/LicenseManager-IDGPK6OM.mjs +1 -0
  51. package/lib/web/chunks/LicenseManager-KDM6XEPI.mjs +1 -0
  52. package/lib/web/chunks/LicenseManager-Q3JTVOGK.mjs +1 -0
  53. package/lib/web/chunks/LicenseManager-RXOJAIDG.mjs +1 -0
  54. package/lib/web/chunks/LicenseManager-UHFOJRQ6.mjs +1 -0
  55. package/lib/web/chunks/LicenseManager-XSLQCKDC.mjs +1 -0
  56. package/lib/web/chunks/LicenseManager-YI5LR3AY.mjs +1 -0
  57. package/lib/web/chunks/LicenseManager-YKUYIOKJ.mjs +1 -0
  58. package/lib/web/chunks/chunk-AC36O63C.mjs +73 -0
  59. package/lib/web/chunks/chunk-CMYC3OJ3.mjs +73 -0
  60. package/lib/web/chunks/chunk-CVVUFZAQ.mjs +73 -0
  61. package/lib/web/chunks/chunk-JPTOVVON.mjs +73 -0
  62. package/lib/web/chunks/chunk-JVWYYKXV.mjs +73 -0
  63. package/lib/web/chunks/chunk-KQ3HUCUX.mjs +73 -0
  64. package/lib/web/chunks/chunk-LHMH746X.mjs +73 -0
  65. package/lib/web/chunks/chunk-XOY6D2WL.mjs +73 -0
  66. package/lib/web/chunks/chunk-YEGY5MDO.mjs +73 -0
  67. package/lib/web/chunks/chunk-ZSTLYSNF.mjs +68 -68
  68. package/lib/web/index.mjs +6 -1
  69. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.LicenseManager=void 0;var _storage=require("./storage");var _config=require("./config.js");var _api=require("./api.js");var _fingerprint=require("./fingerprint");var _cacheSignature=require("./cacheSignature.js");var _freeToken=require("./freeToken.js");var _tier=require("./tier.js");var _accountAccess=require("./accountAccess.js");var _foreground=require("./foreground");var _realNow=require("./realNow.js");/*!
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.LicenseManager=void 0;var _storage=require("./storage");var _config=require("./config.js");var _api=require("./api.js");var _fingerprint=require("./fingerprint");var _cacheSignature=require("./cacheSignature.js");var _freeToken=require("./freeToken.js");var _tier=require("./tier.js");var _accountAccess=require("./accountAccess.js");var _foreground=require("./foreground");var _realNow=require("./realNow.js");var _sessionManager=require("./sessionManager.js");var _serviceKey=require("./serviceKey.js");var _devToken=require("./devToken.js");/*!
2
2
  * PROPRIETARY — Buoy Pro license enforcement. NOT open source.
3
3
  *
4
4
  * Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
@@ -13,4 +13,4 @@
13
13
  * Pro is $9/mo, and is free every weekend for anyone holding a key —
14
14
  * including a free one (`npx buoy login`). Buy a key at
15
15
  * https://buoy.gg or use it free on Saturday and Sunday.
16
- */async function boundedStorage(o,e){let t;try{return await Promise.race([o,new Promise(i=>{t=setTimeout(()=>i(e),15e3)})])}finally{if(t)clearTimeout(t)}}function tierOfCache(o){if(o.tier==="pro"||o.tier==="free")return o.tier;return o.isPro?"pro":"free"}class LicenseManagerImpl{state={isInitialized:false,isValidating:false,isPro:false,tier:"free",tierSource:"none",licenseKey:null,error:null,errorKind:null,expiresAt:null};listeners=new Set;revalidationTimer=null;cachedLicense=null;fingerprintPromise=null;initPromise=null;generation=0;persistence=Promise.resolve();verifiedAt=null;expiryTimer=null;removeForegroundListener=null;retryTimer=null;retryAttempt=0;deviceRegistrationCallback=null;pendingRegistration=null;async initialize(){if(this.initPromise)return this.initPromise;if(this.state.isInitialized)return;this.initPromise=this._doInitialize();return this.initPromise}async _doInitialize(){if(this.state.isInitialized)return;const e=this.generation;try{const t=await boundedStorage(this.loadCachedLicense(),null);if(e!==this.generation){this.state.isInitialized=true;this.emit({type:"initialized",isPro:this.state.isPro});this.startRevalidationTimer();return}if(t&&(this.configuredKey===void 0||t.licenseKey===this.configuredKey)){const i=(0,_cacheSignature.verifyCacheSignature)(t);this.cachedLicense=t;this.state.licenseKey=t.licenseKey;if(i&&this.isCacheValid(t))this.applyTier(tierOfCache(t));else this.lock();this.state.expiresAt=t.expiresAt?new Date(t.expiresAt):null;if(i&&this.isCacheValid(t))this.setVerifiedAt(t.cachedAt);if(this.configuredKey===void 0&&t.licenseKey&&!(i&&this.isCacheValid(t)&&this.isCacheFresh(t))){this.validateInBackground(t.licenseKey)}}this.state.isInitialized=true;this.emit({type:"initialized",isPro:this.state.isPro});this.startRevalidationTimer()}catch(t){console.warn("[React Buoy] License initialization failed:",t);this.state.isInitialized=true;this.emit({type:"initialized",isPro:false})}}async configure(e){if(e===void 0){await this.initialize();return this.hasAccountAccess()}const t=e.trim().toUpperCase();const i=++this.generation;this.cancelRetry();this.configuredKey=t||null;if(this.state.licenseKey!==this.configuredKey)this.lock();this.state.licenseKey=this.configuredKey;this.state.isValidating=!!t;this.emit({type:"validating",isPro:this.isPro()});await this.initialize();if(i!==this.generation)return false;if(!t){await this.clearLicense();return false}return this.setLicenseKey(t)}async setLicenseKey(e,t){if(!e||e.trim().length===0){this.state.error="License key is required";this.state.errorKind="verdict";return false}const i=e.trim().toUpperCase();const s=++this.generation;this.cancelRetry();if(!t?.isRetry)this.retryAttempt=0;if(this.state.licenseKey!==i)this.lock();this.state.licenseKey=i;this.state.isValidating=true;this.state.error=null;this.state.errorKind=null;this.emit({type:"validating",isPro:this.isPro()});if((0,_freeToken.isBuoyToken)(i))return this.admitToken(i,s);if(!this.cachedLicense){const a=await boundedStorage(this.loadCachedLicense(),null);if(s!==this.generation)return false;if(a?.licenseKey===i){this.cachedLicense=a;if((0,_cacheSignature.verifyCacheSignature)(a)&&this.isCacheValid(a)){this.applyTier(tierOfCache(a));this.state.expiresAt=a.expiresAt?new Date(a.expiresAt):null;this.setVerifiedAt(a.cachedAt);this.emit({type:"validating",isPro:this.isPro()})}}}const r=this.cachedLicense;if(!t?.force&&r&&r.valid&&r.licenseKey===i&&r.fingerprint&&(0,_cacheSignature.verifyCacheSignature)(r)&&this.isCacheValid(r)&&this.isCacheFresh(r)){this.applyTier(tierOfCache(r));this.state.licenseKey=i;this.state.isValidating=false;this.state.error=null;this.state.errorKind=null;this.state.expiresAt=r.expiresAt?new Date(r.expiresAt):null;this.setVerifiedAt(r.cachedAt);this.emit({type:"validated",isPro:this.state.isPro});return true}const c=await boundedStorage(this.loadHold(),null);if(s!==this.generation)return false;const u=(c?.backoffUntil??0)-(0,_realNow.realNow)();if(u>0){return this.standDown(i,s,"License server is rate limited; retrying later.",u)}if(!t?.force&&c?.key===i&&c.verdictAt!==void 0&&(0,_realNow.realNow)()-c.verdictAt>=0&&(0,_realNow.realNow)()-c.verdictAt<_config.LICENSE_VERDICT_CACHE_DURATION){this.lock();this.state.isValidating=false;this.state.error=c.detail||"License could not be verified";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});return false}let n;try{n=await(0,_api.validateLicense)(i)}catch(a){const h=a instanceof Error?a.message:"Validation failed";if(s!==this.generation)return false;if((0,_api.isTransientLicenseError)(a)){if((0,_api.isRateLimited)(a)){const l=Math.min((0,_api.backoffAfter)(a,_config.LICENSE_QUOTA_COOLDOWN,_config.LICENSE_RATE_LIMIT_DEFAULT_WAIT)*2**this.retryAttempt,_config.LICENSE_QUOTA_COOLDOWN);this.retryAttempt+=1;await this.saveHold({...this.hold,backoffUntil:(0,_realNow.realNow)()+l});if(s!==this.generation)return false;return this.standDown(i,s,h,l)}this.state.isValidating=false;if(this.cachedLicense&&this.cachedLicense.licenseKey===i&&(0,_cacheSignature.verifyCacheSignature)(this.cachedLicense)&&this.isCacheValid(this.cachedLicense)){this.applyTier(tierOfCache(this.cachedLicense));this.state.error=null;this.state.errorKind=null;this.state.expiresAt=this.cachedLicense.expiresAt?new Date(this.cachedLicense.expiresAt):null;this.setVerifiedAt(this.cachedLicense.cachedAt);if(!this.isPro())this.scheduleRetry(i);this.emit({type:"validated",isPro:this.state.isPro});return true}this.state.error=h;this.state.errorKind="transport";this.scheduleRetry(i);this.emit({type:"error",isPro:this.state.isPro,error:h});return false}this.state.isValidating=false;this.state.error=h;this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:h});return false}try{if(s!==this.generation)return false;const a=(0,_api.parseValidationResult)(n);const h=n.data?.relationships?.product?.data?.id;if((!h||h===_config.KEYGEN_CONFIG.productId)&&a.code==="EXPIRED"&&((0,_tier.isRecognizedAccount)(n.data)||this.cachedLicense?.licenseKey===i&&(0,_cacheSignature.verifyCacheSignature)(this.cachedLicense)&&this.isCacheValid(this.cachedLicense))){const p=(0,_realNow.realNow)();const T=await this.saveCache({licenseKey:i,licenseId:n.data?.id??"",valid:true,isPro:false,tier:"free",expiresAt:null,cachedAt:p,lastValidatedAt:p,fingerprint:this.cachedLicense?.licenseKey===i?this.cachedLicense.fingerprint:void 0},s);if(s!==this.generation||!T)return false;this.cachedLicense=T;this.applyTier("free");this.state.isValidating=false;this.state.expiresAt=null;this.setVerifiedAt(p);this.emit({type:"validated",isPro:false});return true}if((0,_api.isFatalLicenseError)(a.code)||!(0,_api.isAcceptedValidation)(n)){this.lock();this.state.isValidating=false;this.state.error=a.detail||"License could not be verified";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});await this.clearCachedLicense();await this.saveHold({key:i,code:a.code,detail:this.state.error,verdictAt:(0,_realNow.realNow)()});return false}if(!n.data){this.lock();this.state.isValidating=false;this.state.error=a.detail||"License not found";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});await this.clearCachedLicense();return false}const l=(0,_tier.resolveTier)(n.data);const _=n.data.id;const g=(0,_realNow.realNow)();const A=(0,_api.machineCount)(n)>=_config.LICENSE_FLEET_MACHINE_THRESHOLD;const v=(0,_fingerprint.isDevBundle)();const I=v&&!A;const R=l==="free"&&(A||!v);let d=this.cachedLicense?.fingerprint;let f=this.cachedLicense?.deviceName;let m=false;if(!d){d=await boundedStorage(this.getOrCreateDeviceFingerprint(),(0,_fingerprint.generateUUID)());if(s!==this.generation)return false;f=(0,_fingerprint.getDefaultDeviceName)();m=I}let y=false;if(m){if(this.deviceRegistrationCallback){this.pendingRegistration={licenseId:_,licenseKey:i,fingerprint:d};this.deviceRegistrationCallback({fingerprint:d,defaultName:f});y=true}else{this.registerDeviceAsync(_,i,d,f)}}const E={licenseKey:i,licenseId:_,valid:true,isPro:l==="pro",tier:l,expiresAt:n.data.attributes.expiry??null,cachedAt:g,lastValidatedAt:g,fingerprint:y?void 0:d,deviceName:y?void 0:f,quiet:R||void 0};const L=await this.saveCache(E,s);if(s!==this.generation||!L)return false;this.cachedLicense=L;this.applyTier(l);this.state.isValidating=false;this.state.expiresAt=E.expiresAt?new Date(E.expiresAt):null;this.setVerifiedAt(g);if(this.hold)await this.saveHold(null);if(s!==this.generation)return false;this.retryAttempt=0;this.emit({type:"validated",isPro:this.state.isPro});return true}catch(a){const h=a instanceof Error?a.message:"Validation failed";if(s!==this.generation)return false;this.state.isValidating=false;this.state.error=h;this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:h});return false}}scheduleRetry(e){this.cancelRetry();const t=_config.LICENSE_TRANSIENT_RETRY_DELAYS[this.retryAttempt];if(t===void 0)return;this.retryAttempt+=1;const i=this.generation;this.retryTimer=setTimeout(()=>{this.retryTimer=null;if(i!==this.generation)return;if(this.state.isValidating)return;void this.setLicenseKey(e,{force:true,isRetry:true})},t);if(typeof __DEV__!=="undefined"&&__DEV__){global.__LICENSE_MANAGER_RETRY_TIMER__=this.retryTimer}}async admitToken(e,t){const i=(0,_freeToken.verifyFreeToken)(e);if(t!==this.generation)return false;if(!i){this.lock();this.state.isValidating=false;this.state.error="This key is not valid. Check that it was copied completely.";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});await this.clearCachedLicense();return false}const s=(0,_realNow.realNow)();const r=this.cachedLicense?.fingerprint??await boundedStorage(this.getOrCreateDeviceFingerprint(),(0,_fingerprint.generateUUID)());if(t!==this.generation)return false;const c=await this.saveCache({licenseKey:e,licenseId:`token:${i.accountHash}`,valid:true,isPro:false,tier:"free",expiresAt:null,cachedAt:s,lastValidatedAt:s,fingerprint:r,deviceName:this.cachedLicense?.deviceName??(0,_fingerprint.getDefaultDeviceName)(),quiet:true},t);if(t!==this.generation||!c)return false;this.cachedLicense=c;this.applyTier("free");this.state.isValidating=false;this.state.expiresAt=null;this.setVerifiedAt(s);this.retryAttempt=0;this.emit({type:"validated",isPro:false});return true}standDown(e,t,i,s){if(t!==this.generation)return false;this.state.isValidating=false;const r=this.cachedLicense;if(r&&r.licenseKey===e&&(0,_cacheSignature.verifyCacheSignature)(r)&&this.isCacheValid(r)){this.applyTier(tierOfCache(r));this.state.error=null;this.state.errorKind=null;this.state.expiresAt=r.expiresAt?new Date(r.expiresAt):null;this.setVerifiedAt(r.cachedAt);if(!this.isPro())this.scheduleRetryIn(e,s);this.emit({type:"validated",isPro:this.state.isPro});return true}this.state.error=i;this.state.errorKind="transport";this.scheduleRetryIn(e,s);this.emit({type:"error",isPro:this.state.isPro,error:i});return false}scheduleRetryIn(e,t){this.cancelRetry();const i=this.generation;this.retryTimer=setTimeout(()=>{this.retryTimer=null;if(i!==this.generation)return;if(this.state.isValidating)return;void this.setLicenseKey(e,{force:true,isRetry:true})},Math.max(1,Math.min(t,2147483647)));if(typeof __DEV__!=="undefined"&&__DEV__)devTimers.__LICENSE_MANAGER_RETRY_TIMER__=this.retryTimer}cancelRetry(){if(this.retryTimer){clearTimeout(this.retryTimer);this.retryTimer=null}}async clearLicense(){this.generation+=1;this.cancelRetry();this.retryAttempt=0;this.configuredKey=null;this.state.licenseKey=null;this.lock();this.state.expiresAt=null;this.state.error=null;this.state.errorKind=null;this.cachedLicense=null;this.pendingRegistration=null;this.state.isValidating=false;this.emit({type:"deactivated",isPro:false});await this.clearCachedLicense();if(this.hold?.verdictAt!==void 0){await this.saveHold(this.hold.backoffUntil?{backoffUntil:this.hold.backoffUntil}:null)}}applyTier(e){this.state.tier=e;this.state.tierSource="key";this.state.isPro=e==="pro"}lock(){this.state.tier="free";this.state.tierSource="none";this.state.isPro=false;this.verifiedAt=null;if(this.expiryTimer)clearTimeout(this.expiryTimer);this.expiryTimer=null}getTier(){if(!this.hasAccountAccess())return"free";if(this.state.expiresAt&&(0,_realNow.realNow)()>=this.state.expiresAt.getTime())return"free";return this.state.tier}isPro(){return this.getTier()==="pro"}hasEntitlement(e){return this.isPro()}getState(){const e=this.getAccountAccess();const t=this.getTier();return{...this.state,tier:t,isPro:t==="pro",access:e}}getAccountAccess(){return(0,_accountAccess.resolveAccountAccess)({initialized:this.state.isInitialized,validating:this.state.isValidating,key:this.state.licenseKey,tierSource:this.state.tierSource,verifiedAt:this.verifiedAt})}hasAccountAccess(){return this.getAccountAccess().status==="admitted"}setVerifiedAt(e){this.verifiedAt=e;if(this.expiryTimer)clearTimeout(this.expiryTimer);const t=e+_config.LICENSE_CACHE_DURATION;const i=this.state.expiresAt?.getTime();const s=i&&i>(0,_realNow.realNow)()?Math.min(t,i):t;const r=s-(0,_realNow.realNow)();this.expiryTimer=setTimeout(()=>{this.expiryTimer=null;if(this.verifiedAt!==e)return;this.emit({type:"validated",isPro:this.isPro()});if((0,_realNow.realNow)()<t)this.setVerifiedAt(e)},Math.max(1,Math.min(r,2147483647)));if(typeof __DEV__!=="undefined"&&__DEV__)devTimers.__LICENSE_MANAGER_EXPIRY_TIMER__=this.expiryTimer}subscribe(e){this.listeners.add(e);return()=>this.listeners.delete(e)}onDeviceRegistrationNeeded(e){this.deviceRegistrationCallback=e;return()=>{this.deviceRegistrationCallback=null}}async completeDeviceRegistration(e){if(!this.pendingRegistration){console.warn("[Buoy] No pending device registration");return}const{licenseId:t,licenseKey:i,fingerprint:s}=this.pendingRegistration;const r=this.generation;const c=e.trim()||(0,_fingerprint.getDefaultDeviceName)();const u=(0,_fingerprint.getDeviceMetadata)();try{await(0,_api.activateMachine)(t,i,s,c,u)}catch(n){const a=n instanceof Error?n.message:String(n);if(a==="FINGERPRINT_TAKEN"||a==="MACHINE_LIMIT_EXCEEDED"){}else{console.warn("[Buoy] Device registration failed:",a);throw n}}if(r!==this.generation)return;if(this.cachedLicense?.licenseKey===i){const n=await this.saveCache({...this.cachedLicense,fingerprint:s,deviceName:c},r);if(r!==this.generation)return;if(n)this.cachedLicense=n}this.pendingRegistration=null}emit(e){const t=[...this.listeners];t.forEach(i=>{try{i(e)}catch(s){console.warn("[React Buoy] License listener error:",s)}})}isCacheValid(e){const t=(0,_realNow.realNow)();const i=t-e.cachedAt;if(!e.valid||!Number.isFinite(e.cachedAt)||i<0||i>=_config.LICENSE_CACHE_DURATION){return false}return true}isCacheFresh(e){const t=this.isQuiet(e)?_config.LICENSE_QUIET_VALIDATION_TTL:_config.LICENSE_LAUNCH_VALIDATION_TTL;return(0,_realNow.realNow)()-(e.lastValidatedAt??0)<t}isQuiet(e){if(e.quiet!==void 0)return e.quiet;return tierOfCache(e)==="free"&&!(0,_fingerprint.isDevBundle)()}async loadHold(){if(this.hold!==void 0)return this.hold;try{const e=await(0,_storage.getLicenseStorage)();const t=await e.getItem(_config.LICENSE_HOLD_STORAGE_KEY);const i=t?JSON.parse(t):null;this.hold=i&&typeof i==="object"?i:null}catch{this.hold=null}return this.hold}async saveHold(e){this.hold=e;try{const t=await(0,_storage.getLicenseStorage)();if(e)await t.setItem(_config.LICENSE_HOLD_STORAGE_KEY,JSON.stringify(e));else await t.removeItem(_config.LICENSE_HOLD_STORAGE_KEY)}catch{}}async persistCache(e){const t=(0,_cacheSignature.signCache)(e);const i=await(0,_storage.getLicenseStorage)();await i.setItem(_config.LICENSE_STORAGE_KEY,JSON.stringify(t));return t}saveCache(e,t){const i=this.persistence.catch(()=>{}).then(async()=>{if(t!==this.generation)return null;const s=await this.persistCache(e);return t===this.generation?s:null});this.persistence=i;return boundedStorage(i,(0,_cacheSignature.signCache)(e))}async loadCachedLicense(){try{await this.persistence.catch(()=>{});const e=await(0,_storage.getLicenseStorage)();const t=await e.getItem(_config.LICENSE_STORAGE_KEY);if(!t)return null;const i=JSON.parse(t);return i}catch(e){console.warn("[Buoy] Error loading cached license:",e);return null}}getOrCreateDeviceFingerprint(){if(!this.fingerprintPromise){this.fingerprintPromise=(async()=>{const e=await(0,_storage.getLicenseStorage)();const t=await e.getItem(_config.DEVICE_FINGERPRINT_STORAGE_KEY);if(t)return t;const i=this.cachedLicense?.fingerprint||(0,_fingerprint.generateUUID)();await e.setItem(_config.DEVICE_FINGERPRINT_STORAGE_KEY,i);return i})()}return this.fingerprintPromise}async clearCachedLicense(){this.cachedLicense=null;const e=this.persistence.catch(()=>{}).then(async()=>{const t=await(0,_storage.getLicenseStorage)();await t.removeItem(_config.LICENSE_STORAGE_KEY)});this.persistence=e;await boundedStorage(e.catch(()=>{}),void 0)}registerDeviceAsync(e,t,i,s){const r=(0,_fingerprint.getDeviceMetadata)();(0,_api.activateMachine)(e,t,i,s,r).catch(c=>{if(c.message!=="FINGERPRINT_TAKEN"&&c.message!=="MACHINE_LIMIT_EXCEEDED"){console.warn("[Buoy] Device registration failed (non-blocking):",c.message)}})}validateInBackground(e){void this.setLicenseKey(e,{force:true,isRetry:true})}refreshAccess(){this.emit({type:"validated",isPro:this.isPro()})}startRevalidationTimer(){if(!this.removeForegroundListener){this.removeForegroundListener=(0,_foreground.subscribeForeground)(()=>this.refreshAccess());if(typeof __DEV__!=="undefined"&&__DEV__)devTimers.__LICENSE_MANAGER_FOREGROUND_OFF__=this.removeForegroundListener}if(this.revalidationTimer){clearInterval(this.revalidationTimer)}this.revalidationTimer=setInterval(()=>{if(!this.state.licenseKey||this.state.isValidating)return;const e=this.cachedLicense;if(e&&e.licenseKey===this.state.licenseKey&&this.isCacheFresh(e))return;this.validateInBackground(this.state.licenseKey)},_config.LICENSE_REVALIDATION_INTERVAL);if(typeof __DEV__!=="undefined"&&__DEV__){global.__LICENSE_MANAGER_TIMER__=this.revalidationTimer}}stopRevalidationTimer(){this.removeForegroundListener?.();this.removeForegroundListener=null;if(this.expiryTimer)clearTimeout(this.expiryTimer);this.expiryTimer=null;if(this.revalidationTimer){clearInterval(this.revalidationTimer);this.revalidationTimer=null}this.cancelRetry()}async forceReregister(){if(this.cachedLicense){this.cachedLicense.fingerprint=void 0;this.cachedLicense.deviceName=void 0}this.fingerprintPromise=null;await this.clearCachedLicense();try{const e=await(0,_storage.getLicenseStorage)();await e.removeItem(_config.DEVICE_FINGERPRINT_STORAGE_KEY)}catch{}}}const LicenseManager=exports.LicenseManager=new LicenseManagerImpl;const devTimers=globalThis;if(typeof __DEV__!=="undefined"&&__DEV__){devTimers.__LICENSE_MANAGER_FOREGROUND_OFF__?.();devTimers.__LICENSE_MANAGER_FOREGROUND_OFF__=void 0;if(devTimers.__LICENSE_MANAGER_EXPIRY_TIMER__)clearTimeout(devTimers.__LICENSE_MANAGER_EXPIRY_TIMER__);if(devTimers.__LICENSE_MANAGER_TIMER__){clearInterval(devTimers.__LICENSE_MANAGER_TIMER__)}if(devTimers.__LICENSE_MANAGER_RETRY_TIMER__){clearTimeout(devTimers.__LICENSE_MANAGER_RETRY_TIMER__);devTimers.__LICENSE_MANAGER_RETRY_TIMER__=void 0}}
16
+ */async function boundedStorage(h,e){let t;try{return await Promise.race([h,new Promise(i=>{t=setTimeout(()=>i(e),15e3)})])}finally{if(t)clearTimeout(t)}}function tierOfCache(h){if(h.tier==="pro"||h.tier==="free")return h.tier;return h.isPro?"pro":"free"}class LicenseManagerImpl{state={isInitialized:false,isValidating:false,isPro:false,tier:"free",tierSource:"none",licenseKey:null,error:null,errorKind:null,expiresAt:null};listeners=new Set;revalidationTimer=null;cachedLicense=null;fingerprintPromise=null;initPromise=null;generation=0;persistence=Promise.resolve();verifiedAt=null;expiryTimer=null;removeForegroundListener=null;sessionUnsubscribe=null;retryTimer=null;retryAttempt=0;deviceRegistrationCallback=null;pendingRegistration=null;async initialize(){if(this.initPromise)return this.initPromise;if(this.state.isInitialized)return;this.initPromise=this._doInitialize();return this.initPromise}async _doInitialize(){if(this.state.isInitialized)return;const e=this.generation;if(!this.sessionUnsubscribe){this.sessionUnsubscribe=_sessionManager.SessionManager.subscribe(()=>this.emit({type:"validated",isPro:this.isPro()}))}await boundedStorage(_sessionManager.SessionManager.load().catch(()=>void 0),void 0);try{const t=await boundedStorage(this.loadCachedLicense(),null);if(e!==this.generation){this.state.isInitialized=true;this.emit({type:"initialized",isPro:this.state.isPro});this.startRevalidationTimer();return}if(t&&(this.configuredKey===void 0||t.licenseKey===this.configuredKey)){const i=(0,_cacheSignature.verifyCacheSignature)(t);this.cachedLicense=t;this.state.licenseKey=t.licenseKey;if(i&&this.isCacheValid(t))this.applyTier(tierOfCache(t));else this.lock();this.state.expiresAt=t.expiresAt?new Date(t.expiresAt):null;if(i&&this.isCacheValid(t))this.setVerifiedAt(t.cachedAt);if(this.configuredKey===void 0&&t.licenseKey&&!(i&&this.isCacheValid(t)&&this.isCacheFresh(t))){this.validateInBackground(t.licenseKey)}}this.state.isInitialized=true;this.emit({type:"initialized",isPro:this.state.isPro});this.startRevalidationTimer()}catch(t){console.warn("[React Buoy] License initialization failed:",t);this.state.isInitialized=true;this.emit({type:"initialized",isPro:false})}}async configure(e){if(e===void 0){await this.initialize();return this.hasAccountAccess()}const t=(0,_serviceKey.normalizeLicenseKey)(e);const i=++this.generation;this.cancelRetry();this.configuredKey=t||null;if(this.state.licenseKey!==this.configuredKey)this.lock();this.state.licenseKey=this.configuredKey;this.state.isValidating=!!t;this.emit({type:"validating",isPro:this.isPro()});await this.initialize();if(i!==this.generation)return false;if(!t){await this.clearLicense();return false}return this.setLicenseKey(t)}async setLicenseKey(e,t){if(!e||e.trim().length===0){this.state.error="License key is required";this.state.errorKind="verdict";return false}const i=(0,_serviceKey.normalizeLicenseKey)(e);const s=++this.generation;this.cancelRetry();if(!t?.isRetry)this.retryAttempt=0;if(this.state.licenseKey!==i)this.lock();this.state.licenseKey=i;this.state.isValidating=true;this.state.error=null;this.state.errorKind=null;this.emit({type:"validating",isPro:this.isPro()});if((0,_freeToken.isBuoyToken)(i))return this.admitToken(i,s);if((0,_serviceKey.isServiceKey)(i))return this.admitServiceKey(i,s);if((0,_devToken.isDevToken)(i))return this.admitDevToken(i);if(!this.cachedLicense){const a=await boundedStorage(this.loadCachedLicense(),null);if(s!==this.generation)return false;if(a?.licenseKey===i){this.cachedLicense=a;if((0,_cacheSignature.verifyCacheSignature)(a)&&this.isCacheValid(a)){this.applyTier(tierOfCache(a));this.state.expiresAt=a.expiresAt?new Date(a.expiresAt):null;this.setVerifiedAt(a.cachedAt);this.emit({type:"validating",isPro:this.isPro()})}}}const r=this.cachedLicense;if(!t?.force&&r&&r.valid&&r.licenseKey===i&&r.fingerprint&&(0,_cacheSignature.verifyCacheSignature)(r)&&this.isCacheValid(r)&&this.isCacheFresh(r)){this.applyTier(tierOfCache(r));this.state.licenseKey=i;this.state.isValidating=false;this.state.error=null;this.state.errorKind=null;this.state.expiresAt=r.expiresAt?new Date(r.expiresAt):null;this.setVerifiedAt(r.cachedAt);this.emit({type:"validated",isPro:this.state.isPro});return true}const c=await boundedStorage(this.loadHold(),null);if(s!==this.generation)return false;const u=(c?.backoffUntil??0)-(0,_realNow.realNow)();if(u>0){return this.standDown(i,s,"License server is rate limited; retrying later.",u)}if(!t?.force&&c?.key===i&&c.verdictAt!==void 0&&(0,_realNow.realNow)()-c.verdictAt>=0&&(0,_realNow.realNow)()-c.verdictAt<_config.LICENSE_VERDICT_CACHE_DURATION){this.lock();this.state.isValidating=false;this.state.error=c.detail||"License could not be verified";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});return false}let n;try{n=await(0,_api.validateLicense)(i)}catch(a){const o=a instanceof Error?a.message:"Validation failed";if(s!==this.generation)return false;if((0,_api.isTransientLicenseError)(a)){if((0,_api.isRateLimited)(a)){const l=Math.min((0,_api.backoffAfter)(a,_config.LICENSE_QUOTA_COOLDOWN,_config.LICENSE_RATE_LIMIT_DEFAULT_WAIT)*2**this.retryAttempt,_config.LICENSE_QUOTA_COOLDOWN);this.retryAttempt+=1;await this.saveHold({...this.hold,backoffUntil:(0,_realNow.realNow)()+l});if(s!==this.generation)return false;return this.standDown(i,s,o,l)}this.state.isValidating=false;if(this.cachedLicense&&this.cachedLicense.licenseKey===i&&(0,_cacheSignature.verifyCacheSignature)(this.cachedLicense)&&this.isCacheValid(this.cachedLicense)){this.applyTier(tierOfCache(this.cachedLicense));this.state.error=null;this.state.errorKind=null;this.state.expiresAt=this.cachedLicense.expiresAt?new Date(this.cachedLicense.expiresAt):null;this.setVerifiedAt(this.cachedLicense.cachedAt);if(this.keyTier()!=="pro")this.scheduleRetry(i);this.emit({type:"validated",isPro:this.state.isPro});return true}this.state.error=o;this.state.errorKind="transport";this.scheduleRetry(i);this.emit({type:"error",isPro:this.state.isPro,error:o});return false}this.state.isValidating=false;this.state.error=o;this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:o});return false}try{if(s!==this.generation)return false;const a=(0,_api.parseValidationResult)(n);const o=n.data?.relationships?.product?.data?.id;if((!o||o===_config.KEYGEN_CONFIG.productId)&&a.code==="EXPIRED"&&((0,_tier.isRecognizedAccount)(n.data)||this.cachedLicense?.licenseKey===i&&(0,_cacheSignature.verifyCacheSignature)(this.cachedLicense)&&this.isCacheValid(this.cachedLicense))){const E=(0,_realNow.realNow)();const L=await this.saveCache({licenseKey:i,licenseId:n.data?.id??"",valid:true,isPro:false,tier:"free",expiresAt:null,cachedAt:E,lastValidatedAt:E,fingerprint:this.cachedLicense?.licenseKey===i?this.cachedLicense.fingerprint:void 0},s);if(s!==this.generation||!L)return false;this.cachedLicense=L;this.applyTier("free");this.state.isValidating=false;this.state.expiresAt=null;this.setVerifiedAt(E);this.emit({type:"validated",isPro:false});return true}if((0,_api.isFatalLicenseError)(a.code)||!(0,_api.isAcceptedValidation)(n)){this.lock();this.state.isValidating=false;this.state.error=a.detail||"License could not be verified";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});await this.clearCachedLicense();await this.saveHold({key:i,code:a.code,detail:this.state.error,verdictAt:(0,_realNow.realNow)()});return false}if(!n.data){this.lock();this.state.isValidating=false;this.state.error=a.detail||"License not found";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});await this.clearCachedLicense();return false}const l=(0,_tier.resolveTier)(n.data);const _=n.data.id;const g=(0,_realNow.realNow)();const v=(0,_api.machineCount)(n)>=_config.LICENSE_FLEET_MACHINE_THRESHOLD;const m=(0,_fingerprint.isDevBundle)();const I=m&&!v;const R=l==="free"&&(v||!m);let d=this.cachedLicense?.fingerprint;let f=this.cachedLicense?.deviceName;let A=false;if(!d){d=await boundedStorage(this.getOrCreateDeviceFingerprint(),(0,_fingerprint.generateUUID)());if(s!==this.generation)return false;f=(0,_fingerprint.getDefaultDeviceName)();A=I}let y=false;if(A){if(this.deviceRegistrationCallback){this.pendingRegistration={licenseId:_,licenseKey:i,fingerprint:d};this.deviceRegistrationCallback({fingerprint:d,defaultName:f});y=true}else{this.registerDeviceAsync(_,i,d,f)}}const p={licenseKey:i,licenseId:_,valid:true,isPro:l==="pro",tier:l,expiresAt:n.data.attributes.expiry??null,cachedAt:g,lastValidatedAt:g,fingerprint:y?void 0:d,deviceName:y?void 0:f,quiet:R||void 0};const T=await this.saveCache(p,s);if(s!==this.generation||!T)return false;this.cachedLicense=T;this.applyTier(l);this.state.isValidating=false;this.state.expiresAt=p.expiresAt?new Date(p.expiresAt):null;this.setVerifiedAt(g);if(this.hold)await this.saveHold(null);if(s!==this.generation)return false;this.retryAttempt=0;this.emit({type:"validated",isPro:this.state.isPro});return true}catch(a){const o=a instanceof Error?a.message:"Validation failed";if(s!==this.generation)return false;this.state.isValidating=false;this.state.error=o;this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:o});return false}}scheduleRetry(e){this.cancelRetry();const t=_config.LICENSE_TRANSIENT_RETRY_DELAYS[this.retryAttempt];if(t===void 0)return;this.retryAttempt+=1;const i=this.generation;this.retryTimer=setTimeout(()=>{this.retryTimer=null;if(i!==this.generation)return;if(this.state.isValidating)return;void this.setLicenseKey(e,{force:true,isRetry:true})},t);if(typeof __DEV__!=="undefined"&&__DEV__){global.__LICENSE_MANAGER_RETRY_TIMER__=this.retryTimer}}async admitServiceKey(e,t){const i=await(0,_serviceKey.exchangeServiceKey)(e,{origin:_sessionManager.SessionManager.origin});if(t!==this.generation)return false;if(!i.ok){this.lock();this.state.isValidating=false;this.state.error=i.detail;this.state.errorKind=i.reason==="network"?"transport":"verdict";this.emit({type:"error",isPro:false,error:i.detail});if(i.reason==="network")this.scheduleRetry(e);return false}const s=i.claims.exp*1e3;this.applyTier(i.claims.tier==="free"?"free":"pro");this.state.isValidating=false;this.state.expiresAt=new Date(s);this.setVerifiedAt((0,_realNow.realNow)());this.retryAttempt=0;this.scheduleRetryIn(e,Math.max(6e4,s-60*60*1e3-(0,_realNow.realNow)()));this.emit({type:"validated",isPro:this.isPro()});return true}admitDevToken(e){const t=(0,_devToken.checkDevToken)(e);if(!t.ok||!(0,_fingerprint.isDevBundle)()){const s=t.ok?_devToken.DEV_TOKEN_IN_RELEASE:t.message;this.lock();this.state.isValidating=false;this.state.error=s;this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:s});return false}const i=(0,_realNow.realNow)();this.applyTier(t.claims.tier==="free"?"free":"pro");this.state.isValidating=false;this.state.expiresAt=new Date(t.claims.exp*1e3);this.setVerifiedAt(Math.min(i,t.claims.iat*1e3));this.retryAttempt=0;this.emit({type:"validated",isPro:this.isPro()});return true}async admitToken(e,t){const i=(0,_freeToken.verifyFreeToken)(e);if(t!==this.generation)return false;if(!i){this.lock();this.state.isValidating=false;this.state.error="This key is not valid. Check that it was copied completely.";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});await this.clearCachedLicense();return false}const s=(0,_realNow.realNow)();const r=this.cachedLicense?.fingerprint??await boundedStorage(this.getOrCreateDeviceFingerprint(),(0,_fingerprint.generateUUID)());if(t!==this.generation)return false;const c=await this.saveCache({licenseKey:e,licenseId:`token:${i.accountHash}`,valid:true,isPro:false,tier:"free",expiresAt:null,cachedAt:s,lastValidatedAt:s,fingerprint:r,deviceName:this.cachedLicense?.deviceName??(0,_fingerprint.getDefaultDeviceName)(),quiet:true},t);if(t!==this.generation||!c)return false;this.cachedLicense=c;this.applyTier("free");this.state.isValidating=false;this.state.expiresAt=null;this.setVerifiedAt(s);this.retryAttempt=0;this.emit({type:"validated",isPro:false});return true}standDown(e,t,i,s){if(t!==this.generation)return false;this.state.isValidating=false;const r=this.cachedLicense;if(r&&r.licenseKey===e&&(0,_cacheSignature.verifyCacheSignature)(r)&&this.isCacheValid(r)){this.applyTier(tierOfCache(r));this.state.error=null;this.state.errorKind=null;this.state.expiresAt=r.expiresAt?new Date(r.expiresAt):null;this.setVerifiedAt(r.cachedAt);if(this.keyTier()!=="pro")this.scheduleRetryIn(e,s);this.emit({type:"validated",isPro:this.state.isPro});return true}this.state.error=i;this.state.errorKind="transport";this.scheduleRetryIn(e,s);this.emit({type:"error",isPro:this.state.isPro,error:i});return false}scheduleRetryIn(e,t){this.cancelRetry();const i=this.generation;this.retryTimer=setTimeout(()=>{this.retryTimer=null;if(i!==this.generation)return;if(this.state.isValidating)return;void this.setLicenseKey(e,{force:true,isRetry:true})},Math.max(1,Math.min(t,2147483647)));if(typeof __DEV__!=="undefined"&&__DEV__)devTimers.__LICENSE_MANAGER_RETRY_TIMER__=this.retryTimer}cancelRetry(){if(this.retryTimer){clearTimeout(this.retryTimer);this.retryTimer=null}}async clearLicense(){this.generation+=1;this.cancelRetry();this.retryAttempt=0;this.configuredKey=null;this.state.licenseKey=null;this.lock();this.state.expiresAt=null;this.state.error=null;this.state.errorKind=null;this.cachedLicense=null;this.pendingRegistration=null;this.state.isValidating=false;this.emit({type:"deactivated",isPro:false});await this.clearCachedLicense();if(this.hold?.verdictAt!==void 0){await this.saveHold(this.hold.backoffUntil?{backoffUntil:this.hold.backoffUntil}:null)}}applyTier(e){this.state.tier=e;this.state.tierSource="key";this.state.isPro=e==="pro"}lock(){this.state.tier="free";this.state.tierSource="none";this.state.isPro=false;this.verifiedAt=null;if(this.expiryTimer)clearTimeout(this.expiryTimer);this.expiryTimer=null}getTier(){return this.credential().tier}credential(){const e=this.keyTier();const t=this.sessionTier();if(t!==null&&(!this.hasKeyAccess()||t==="pro"&&e!=="pro")){return{source:"session",tier:t}}return{source:this.state.tierSource,tier:e}}keyTier(){if(!this.hasKeyAccess())return"free";if(this.state.expiresAt&&(0,_realNow.realNow)()>=this.state.expiresAt.getTime())return"free";return this.state.tier}sessionTier(){const e=_sessionManager.SessionManager.getStatus();if(e.state!=="active")return null;return e.claims.tier==="free"?"free":"pro"}isPro(){return this.getTier()==="pro"}hasEntitlement(e){return this.isPro()}getState(){const{source:e,tier:t}=this.credential();return{...this.state,tier:t,tierSource:e,isPro:t==="pro",access:this.getAccountAccess()}}getAccountAccess(){const e=this.getKeyAccess();if(e.status==="admitted")return e;const t=_sessionManager.SessionManager.getStatus();if(t.state==="active")return{status:"admitted",reason:null,validUntil:t.validUntil};return e}getKeyAccess(){return(0,_accountAccess.resolveAccountAccess)({initialized:this.state.isInitialized,validating:this.state.isValidating,key:this.state.licenseKey,tierSource:this.state.tierSource,verifiedAt:this.verifiedAt})}hasAccountAccess(){return this.getAccountAccess().status==="admitted"}hasKeyAccess(){return this.getKeyAccess().status==="admitted"}setVerifiedAt(e){this.verifiedAt=e;if(this.expiryTimer)clearTimeout(this.expiryTimer);const t=e+_config.LICENSE_CACHE_DURATION;const i=this.state.expiresAt?.getTime();const s=i&&i>(0,_realNow.realNow)()?Math.min(t,i):t;const r=s-(0,_realNow.realNow)();this.expiryTimer=setTimeout(()=>{this.expiryTimer=null;if(this.verifiedAt!==e)return;this.emit({type:"validated",isPro:this.isPro()});if((0,_realNow.realNow)()<t)this.setVerifiedAt(e)},Math.max(1,Math.min(r,2147483647)));if(typeof __DEV__!=="undefined"&&__DEV__)devTimers.__LICENSE_MANAGER_EXPIRY_TIMER__=this.expiryTimer}subscribe(e){this.listeners.add(e);return()=>this.listeners.delete(e)}onDeviceRegistrationNeeded(e){this.deviceRegistrationCallback=e;return()=>{this.deviceRegistrationCallback=null}}async completeDeviceRegistration(e){if(!this.pendingRegistration){console.warn("[Buoy] No pending device registration");return}const{licenseId:t,licenseKey:i,fingerprint:s}=this.pendingRegistration;const r=this.generation;const c=e.trim()||(0,_fingerprint.getDefaultDeviceName)();const u=(0,_fingerprint.getDeviceMetadata)();try{await(0,_api.activateMachine)(t,i,s,c,u)}catch(n){const a=n instanceof Error?n.message:String(n);if(a==="FINGERPRINT_TAKEN"||a==="MACHINE_LIMIT_EXCEEDED"){}else{console.warn("[Buoy] Device registration failed:",a);throw n}}if(r!==this.generation)return;if(this.cachedLicense?.licenseKey===i){const n=await this.saveCache({...this.cachedLicense,fingerprint:s,deviceName:c},r);if(r!==this.generation)return;if(n)this.cachedLicense=n}this.pendingRegistration=null}emit(e){const t=[...this.listeners];t.forEach(i=>{try{i(e)}catch(s){console.warn("[React Buoy] License listener error:",s)}})}isCacheValid(e){const t=(0,_realNow.realNow)();const i=t-e.cachedAt;if(!e.valid||!Number.isFinite(e.cachedAt)||i<0||i>=_config.LICENSE_CACHE_DURATION){return false}return true}isCacheFresh(e){const t=this.isQuiet(e)?_config.LICENSE_QUIET_VALIDATION_TTL:_config.LICENSE_LAUNCH_VALIDATION_TTL;return(0,_realNow.realNow)()-(e.lastValidatedAt??0)<t}isQuiet(e){if(e.quiet!==void 0)return e.quiet;return tierOfCache(e)==="free"&&!(0,_fingerprint.isDevBundle)()}async loadHold(){if(this.hold!==void 0)return this.hold;try{const e=await(0,_storage.getLicenseStorage)();const t=await e.getItem(_config.LICENSE_HOLD_STORAGE_KEY);const i=t?JSON.parse(t):null;this.hold=i&&typeof i==="object"?i:null}catch{this.hold=null}return this.hold}async saveHold(e){this.hold=e;try{const t=await(0,_storage.getLicenseStorage)();if(e)await t.setItem(_config.LICENSE_HOLD_STORAGE_KEY,JSON.stringify(e));else await t.removeItem(_config.LICENSE_HOLD_STORAGE_KEY)}catch{}}async persistCache(e){const t=(0,_cacheSignature.signCache)(e);const i=await(0,_storage.getLicenseStorage)();await i.setItem(_config.LICENSE_STORAGE_KEY,JSON.stringify(t));return t}saveCache(e,t){const i=this.persistence.catch(()=>{}).then(async()=>{if(t!==this.generation)return null;const s=await this.persistCache(e);return t===this.generation?s:null});this.persistence=i;return boundedStorage(i,(0,_cacheSignature.signCache)(e))}async loadCachedLicense(){try{await this.persistence.catch(()=>{});const e=await(0,_storage.getLicenseStorage)();const t=await e.getItem(_config.LICENSE_STORAGE_KEY);if(!t)return null;const i=JSON.parse(t);return i}catch(e){console.warn("[Buoy] Error loading cached license:",e);return null}}getOrCreateDeviceFingerprint(){if(!this.fingerprintPromise){this.fingerprintPromise=(async()=>{const e=await(0,_storage.getLicenseStorage)();const t=await e.getItem(_config.DEVICE_FINGERPRINT_STORAGE_KEY);if(t)return t;const i=this.cachedLicense?.fingerprint||(0,_fingerprint.generateUUID)();await e.setItem(_config.DEVICE_FINGERPRINT_STORAGE_KEY,i);return i})()}return this.fingerprintPromise}async clearCachedLicense(){this.cachedLicense=null;const e=this.persistence.catch(()=>{}).then(async()=>{const t=await(0,_storage.getLicenseStorage)();await t.removeItem(_config.LICENSE_STORAGE_KEY)});this.persistence=e;await boundedStorage(e.catch(()=>{}),void 0)}registerDeviceAsync(e,t,i,s){const r=(0,_fingerprint.getDeviceMetadata)();(0,_api.activateMachine)(e,t,i,s,r).catch(c=>{if(c.message!=="FINGERPRINT_TAKEN"&&c.message!=="MACHINE_LIMIT_EXCEEDED"){console.warn("[Buoy] Device registration failed (non-blocking):",c.message)}})}validateInBackground(e){void this.setLicenseKey(e,{force:true,isRetry:true})}refreshAccess(){this.emit({type:"validated",isPro:this.isPro()})}startRevalidationTimer(){if(!this.removeForegroundListener){this.removeForegroundListener=(0,_foreground.subscribeForeground)(()=>this.refreshAccess());if(typeof __DEV__!=="undefined"&&__DEV__)devTimers.__LICENSE_MANAGER_FOREGROUND_OFF__=this.removeForegroundListener}if(this.revalidationTimer){clearInterval(this.revalidationTimer)}this.revalidationTimer=setInterval(()=>{if(!this.state.licenseKey||this.state.isValidating)return;const e=this.cachedLicense;if(e&&e.licenseKey===this.state.licenseKey&&this.isCacheFresh(e))return;this.validateInBackground(this.state.licenseKey)},_config.LICENSE_REVALIDATION_INTERVAL);if(typeof __DEV__!=="undefined"&&__DEV__){global.__LICENSE_MANAGER_TIMER__=this.revalidationTimer}}stopRevalidationTimer(){this.removeForegroundListener?.();this.removeForegroundListener=null;if(this.expiryTimer)clearTimeout(this.expiryTimer);this.expiryTimer=null;if(this.revalidationTimer){clearInterval(this.revalidationTimer);this.revalidationTimer=null}this.cancelRetry()}async forceReregister(){if(this.cachedLicense){this.cachedLicense.fingerprint=void 0;this.cachedLicense.deviceName=void 0}this.fingerprintPromise=null;await this.clearCachedLicense();try{const e=await(0,_storage.getLicenseStorage)();await e.removeItem(_config.DEVICE_FINGERPRINT_STORAGE_KEY)}catch{}}}const LicenseManager=exports.LicenseManager=new LicenseManagerImpl;const devTimers=globalThis;if(typeof __DEV__!=="undefined"&&__DEV__){devTimers.__LICENSE_MANAGER_FOREGROUND_OFF__?.();devTimers.__LICENSE_MANAGER_FOREGROUND_OFF__=void 0;if(devTimers.__LICENSE_MANAGER_EXPIRY_TIMER__)clearTimeout(devTimers.__LICENSE_MANAGER_EXPIRY_TIMER__);if(devTimers.__LICENSE_MANAGER_TIMER__){clearInterval(devTimers.__LICENSE_MANAGER_TIMER__)}if(devTimers.__LICENSE_MANAGER_RETRY_TIMER__){clearTimeout(devTimers.__LICENSE_MANAGER_RETRY_TIMER__);devTimers.__LICENSE_MANAGER_RETRY_TIMER__=void 0}}
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.LICENSE_VERDICT_CACHE_DURATION=exports.LICENSE_TRANSIENT_RETRY_DELAYS=exports.LICENSE_STORAGE_KEY=exports.LICENSE_REVALIDATION_INTERVAL=exports.LICENSE_RATE_LIMIT_DEFAULT_WAIT=exports.LICENSE_QUOTA_COOLDOWN=exports.LICENSE_QUIET_VALIDATION_TTL=exports.LICENSE_LAUNCH_VALIDATION_TTL=exports.LICENSE_HOLD_STORAGE_KEY=exports.LICENSE_FLEET_MACHINE_THRESHOLD=exports.LICENSE_CACHE_DURATION=exports.KEYGEN_POLICIES=exports.KEYGEN_CONFIG=exports.FREE_TOKEN_PUBLIC_KEY=exports.DEVICE_FINGERPRINT_STORAGE_KEY=void 0;/*!
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.SESSION_TOKEN_PUBLIC_KEY=exports.LICENSE_VERDICT_CACHE_DURATION=exports.LICENSE_TRANSIENT_RETRY_DELAYS=exports.LICENSE_STORAGE_KEY=exports.LICENSE_REVALIDATION_INTERVAL=exports.LICENSE_RATE_LIMIT_DEFAULT_WAIT=exports.LICENSE_QUOTA_COOLDOWN=exports.LICENSE_QUIET_VALIDATION_TTL=exports.LICENSE_LAUNCH_VALIDATION_TTL=exports.LICENSE_HOLD_STORAGE_KEY=exports.LICENSE_FLEET_MACHINE_THRESHOLD=exports.LICENSE_CACHE_DURATION=exports.KEYGEN_POLICIES=exports.KEYGEN_CONFIG=exports.FREE_TOKEN_PUBLIC_KEY=exports.DEVICE_FINGERPRINT_STORAGE_KEY=void 0;/*!
2
2
  * PROPRIETARY — Buoy Pro license enforcement. NOT open source.
3
3
  *
4
4
  * Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
@@ -14,4 +14,4 @@
14
14
  * Pro is $9/mo, and is free every weekend for anyone holding a key —
15
15
  * including a free one (`npx buoy login`). Buy a key at
16
16
  * https://buoy.gg or use it free on Saturday and Sunday.
17
- */const KEYGEN_CONFIG=exports.KEYGEN_CONFIG={accountId:"b0eba0e8-e904-4906-b644-38f9aab57bed",productId:"bf67cb43-eeef-40ca-b308-e6e1b22c0eaa",apiUrl:"https://buoy.gg/api/license"};const FREE_TOKEN_PUBLIC_KEY=exports.FREE_TOKEN_PUBLIC_KEY="3b546fc717a62683f3236c70167899a271bee3ffc04df6ec1eea60a394a2f1e9";const KEYGEN_POLICIES=exports.KEYGEN_POLICIES={free:"394e3351-1249-4f73-807a-703408604c0e",solo:"fa5d3c8f-5379-40f1-b63e-ab8a974b2f28",business:"690c2212-8e54-426f-b4b4-002ee1c0ae2b"};const LICENSE_CACHE_DURATION=exports.LICENSE_CACHE_DURATION=30*24*60*60*1e3;const LICENSE_REVALIDATION_INTERVAL=exports.LICENSE_REVALIDATION_INTERVAL=24*60*60*1e3;const LICENSE_STORAGE_KEY=exports.LICENSE_STORAGE_KEY="buoy-gg-license";const DEVICE_FINGERPRINT_STORAGE_KEY=exports.DEVICE_FINGERPRINT_STORAGE_KEY="buoy-gg-device-fingerprint";const LICENSE_LAUNCH_VALIDATION_TTL=exports.LICENSE_LAUNCH_VALIDATION_TTL=60*60*1e3;const LICENSE_TRANSIENT_RETRY_DELAYS=exports.LICENSE_TRANSIENT_RETRY_DELAYS=[5*1e3,20*1e3,60*1e3,5*60*1e3,15*60*1e3];const LICENSE_RATE_LIMIT_DEFAULT_WAIT=exports.LICENSE_RATE_LIMIT_DEFAULT_WAIT=60*1e3;const LICENSE_QUOTA_COOLDOWN=exports.LICENSE_QUOTA_COOLDOWN=60*60*1e3;const LICENSE_VERDICT_CACHE_DURATION=exports.LICENSE_VERDICT_CACHE_DURATION=24*60*60*1e3;const LICENSE_FLEET_MACHINE_THRESHOLD=exports.LICENSE_FLEET_MACHINE_THRESHOLD=50;const LICENSE_QUIET_VALIDATION_TTL=exports.LICENSE_QUIET_VALIDATION_TTL=LICENSE_CACHE_DURATION;const LICENSE_HOLD_STORAGE_KEY=exports.LICENSE_HOLD_STORAGE_KEY="buoy-gg-license-hold";
17
+ */const KEYGEN_CONFIG=exports.KEYGEN_CONFIG={accountId:"b0eba0e8-e904-4906-b644-38f9aab57bed",productId:"bf67cb43-eeef-40ca-b308-e6e1b22c0eaa",apiUrl:"https://buoy.gg/api/license"};const FREE_TOKEN_PUBLIC_KEY=exports.FREE_TOKEN_PUBLIC_KEY="3b546fc717a62683f3236c70167899a271bee3ffc04df6ec1eea60a394a2f1e9";const SESSION_TOKEN_PUBLIC_KEY=exports.SESSION_TOKEN_PUBLIC_KEY="36abba0267f7f379d992a5b6df641daab4190bcc9e639e36f1378e3c1ac52746";const KEYGEN_POLICIES=exports.KEYGEN_POLICIES={free:"394e3351-1249-4f73-807a-703408604c0e",solo:"fa5d3c8f-5379-40f1-b63e-ab8a974b2f28",business:"690c2212-8e54-426f-b4b4-002ee1c0ae2b"};const LICENSE_CACHE_DURATION=exports.LICENSE_CACHE_DURATION=30*24*60*60*1e3;const LICENSE_REVALIDATION_INTERVAL=exports.LICENSE_REVALIDATION_INTERVAL=24*60*60*1e3;const LICENSE_STORAGE_KEY=exports.LICENSE_STORAGE_KEY="buoy-gg-license";const DEVICE_FINGERPRINT_STORAGE_KEY=exports.DEVICE_FINGERPRINT_STORAGE_KEY="buoy-gg-device-fingerprint";const LICENSE_LAUNCH_VALIDATION_TTL=exports.LICENSE_LAUNCH_VALIDATION_TTL=60*60*1e3;const LICENSE_TRANSIENT_RETRY_DELAYS=exports.LICENSE_TRANSIENT_RETRY_DELAYS=[5*1e3,20*1e3,60*1e3,5*60*1e3,15*60*1e3];const LICENSE_RATE_LIMIT_DEFAULT_WAIT=exports.LICENSE_RATE_LIMIT_DEFAULT_WAIT=60*1e3;const LICENSE_QUOTA_COOLDOWN=exports.LICENSE_QUOTA_COOLDOWN=60*60*1e3;const LICENSE_VERDICT_CACHE_DURATION=exports.LICENSE_VERDICT_CACHE_DURATION=24*60*60*1e3;const LICENSE_FLEET_MACHINE_THRESHOLD=exports.LICENSE_FLEET_MACHINE_THRESHOLD=50;const LICENSE_QUIET_VALIDATION_TTL=exports.LICENSE_QUIET_VALIDATION_TTL=LICENSE_CACHE_DURATION;const LICENSE_HOLD_STORAGE_KEY=exports.LICENSE_HOLD_STORAGE_KEY="buoy-gg-license-hold";
@@ -0,0 +1,6 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.DEV_TOKEN_IN_RELEASE=exports.DEV_AUDIENCE=void 0;exports.checkDevToken=checkDevToken;exports.isDevToken=isDevToken;var _sessionToken=require("./sessionToken.js");var _realNow=require("./realNow.js");/*!
2
+ * PROPRIETARY — Buoy license enforcement. NOT open source.
3
+ *
4
+ * Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
5
+ * (https://buoy.gg/terms), not an OSS license.
6
+ */const DEV_AUDIENCE=exports.DEV_AUDIENCE="dev";function isDevToken(e){return(0,_sessionToken.isSessionToken)(e)}function checkDevToken(e,n=(0,_realNow.realNow)()){const o=(0,_sessionToken.verifySessionToken)(e,{audience:DEV_AUDIENCE,ignoreTime:true});if(!o.ok)return{ok:false,reason:"invalid",message:"This dev token is not valid. Run `npx buoy login` again."};if(n>=o.claims.exp*1e3){return{ok:false,reason:"expired",message:"Your dev token ran out. Run `npx buoy login` again."}}return{ok:true,claims:o.claims}}const DEV_TOKEN_IN_RELEASE=exports.DEV_TOKEN_IN_RELEASE="This is a dev token. It only works in dev builds. A live build turns on Buoy with Sign in with Buoy.";
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});Object.defineProperty(exports,"KEYGEN_CONFIG",{enumerable:true,get:function(){return _config.KEYGEN_CONFIG}});Object.defineProperty(exports,"LICENSE_CACHE_DURATION",{enumerable:true,get:function(){return _config.LICENSE_CACHE_DURATION}});Object.defineProperty(exports,"LICENSE_LAUNCH_VALIDATION_TTL",{enumerable:true,get:function(){return _config.LICENSE_LAUNCH_VALIDATION_TTL}});Object.defineProperty(exports,"LICENSE_REVALIDATION_INTERVAL",{enumerable:true,get:function(){return _config.LICENSE_REVALIDATION_INTERVAL}});Object.defineProperty(exports,"LICENSE_TRANSIENT_RETRY_DELAYS",{enumerable:true,get:function(){return _config.LICENSE_TRANSIENT_RETRY_DELAYS}});Object.defineProperty(exports,"LicenseTransportError",{enumerable:true,get:function(){return _api.LicenseTransportError}});Object.defineProperty(exports,"__setFreeTokenPublicKeyForTests",{enumerable:true,get:function(){return _freeToken.__setFreeTokenPublicKeyForTests}});Object.defineProperty(exports,"accountHashFor",{enumerable:true,get:function(){return _freeToken.accountHashFor}});Object.defineProperty(exports,"isAcceptedValidation",{enumerable:true,get:function(){return _api.isAcceptedValidation}});Object.defineProperty(exports,"isBuoyToken",{enumerable:true,get:function(){return _freeToken.isBuoyToken}});Object.defineProperty(exports,"isRecognizedAccount",{enumerable:true,get:function(){return _tier.isRecognizedAccount}});Object.defineProperty(exports,"isTransientLicenseError",{enumerable:true,get:function(){return _api.isTransientLicenseError}});Object.defineProperty(exports,"mintFreeToken",{enumerable:true,get:function(){return _freeToken.mintFreeToken}});Object.defineProperty(exports,"publicKeyFor",{enumerable:true,get:function(){return _freeToken.publicKeyFor}});Object.defineProperty(exports,"resolveAccountAccess",{enumerable:true,get:function(){return _accountAccess.resolveAccountAccess}});Object.defineProperty(exports,"resolveTier",{enumerable:true,get:function(){return _tier.resolveTier}});Object.defineProperty(exports,"signCache",{enumerable:true,get:function(){return _cacheSignature.signCache}});Object.defineProperty(exports,"validateLicense",{enumerable:true,get:function(){return _api.validateLicense}});Object.defineProperty(exports,"verifyCacheSignature",{enumerable:true,get:function(){return _cacheSignature.verifyCacheSignature}});Object.defineProperty(exports,"verifyFreeToken",{enumerable:true,get:function(){return _freeToken.verifyFreeToken}});var _api=require("./api.js");var _tier=require("./tier.js");var _freeToken=require("./freeToken.js");var _accountAccess=require("./accountAccess.js");var _cacheSignature=require("./cacheSignature.js");var _config=require("./config.js");
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});Object.defineProperty(exports,"CLI_AUDIENCE",{enumerable:true,get:function(){return _nodeSession.CLI_AUDIENCE}});Object.defineProperty(exports,"DESKTOP_AUDIENCE",{enumerable:true,get:function(){return _nodeSession.DESKTOP_AUDIENCE}});Object.defineProperty(exports,"DEV_AUDIENCE",{enumerable:true,get:function(){return _devToken.DEV_AUDIENCE}});Object.defineProperty(exports,"KEYGEN_CONFIG",{enumerable:true,get:function(){return _config.KEYGEN_CONFIG}});Object.defineProperty(exports,"LICENSE_CACHE_DURATION",{enumerable:true,get:function(){return _config.LICENSE_CACHE_DURATION}});Object.defineProperty(exports,"LICENSE_LAUNCH_VALIDATION_TTL",{enumerable:true,get:function(){return _config.LICENSE_LAUNCH_VALIDATION_TTL}});Object.defineProperty(exports,"LICENSE_REVALIDATION_INTERVAL",{enumerable:true,get:function(){return _config.LICENSE_REVALIDATION_INTERVAL}});Object.defineProperty(exports,"LICENSE_TRANSIENT_RETRY_DELAYS",{enumerable:true,get:function(){return _config.LICENSE_TRANSIENT_RETRY_DELAYS}});Object.defineProperty(exports,"LicenseTransportError",{enumerable:true,get:function(){return _api.LicenseTransportError}});Object.defineProperty(exports,"SERVICE_AUDIENCE",{enumerable:true,get:function(){return _serviceKey.SERVICE_AUDIENCE}});Object.defineProperty(exports,"SERVICE_KEY_PREFIX",{enumerable:true,get:function(){return _serviceKey.SERVICE_KEY_PREFIX}});Object.defineProperty(exports,"SESSION_OFFLINE_GRACE_MS",{enumerable:true,get:function(){return _sessionManager.SESSION_OFFLINE_GRACE_MS}});Object.defineProperty(exports,"SessionError",{enumerable:true,get:function(){return _sessionManager.SessionError}});Object.defineProperty(exports,"SessionManagerImpl",{enumerable:true,get:function(){return _sessionManager.SessionManagerImpl}});Object.defineProperty(exports,"__setFreeTokenPublicKeyForTests",{enumerable:true,get:function(){return _freeToken.__setFreeTokenPublicKeyForTests}});Object.defineProperty(exports,"__setSessionTokenPublicKeyForTests",{enumerable:true,get:function(){return _sessionToken.__setSessionTokenPublicKeyForTests}});Object.defineProperty(exports,"accountHashFor",{enumerable:true,get:function(){return _freeToken.accountHashFor}});Object.defineProperty(exports,"checkDevToken",{enumerable:true,get:function(){return _devToken.checkDevToken}});Object.defineProperty(exports,"createNodeSession",{enumerable:true,get:function(){return _nodeSession.createNodeSession}});Object.defineProperty(exports,"defaultSessionFile",{enumerable:true,get:function(){return _nodeSession.defaultSessionFile}});Object.defineProperty(exports,"exchangeServiceKey",{enumerable:true,get:function(){return _serviceKey.exchangeServiceKey}});Object.defineProperty(exports,"fileLock",{enumerable:true,get:function(){return _nodeSession.fileLock}});Object.defineProperty(exports,"fileSessionStorage",{enumerable:true,get:function(){return _nodeSession.fileSessionStorage}});Object.defineProperty(exports,"isAcceptedValidation",{enumerable:true,get:function(){return _api.isAcceptedValidation}});Object.defineProperty(exports,"isBuoyToken",{enumerable:true,get:function(){return _freeToken.isBuoyToken}});Object.defineProperty(exports,"isDevToken",{enumerable:true,get:function(){return _devToken.isDevToken}});Object.defineProperty(exports,"isRecognizedAccount",{enumerable:true,get:function(){return _tier.isRecognizedAccount}});Object.defineProperty(exports,"isServiceKey",{enumerable:true,get:function(){return _serviceKey.isServiceKey}});Object.defineProperty(exports,"isTransientLicenseError",{enumerable:true,get:function(){return _api.isTransientLicenseError}});Object.defineProperty(exports,"mintFreeToken",{enumerable:true,get:function(){return _freeToken.mintFreeToken}});Object.defineProperty(exports,"mintSessionToken",{enumerable:true,get:function(){return _sessionToken.mintSessionToken}});Object.defineProperty(exports,"normalizeLicenseKey",{enumerable:true,get:function(){return _serviceKey.normalizeLicenseKey}});Object.defineProperty(exports,"publicKeyFor",{enumerable:true,get:function(){return _freeToken.publicKeyFor}});Object.defineProperty(exports,"receiveCodeOnLoopback",{enumerable:true,get:function(){return _nodeSession.receiveCodeOnLoopback}});Object.defineProperty(exports,"resolveAccountAccess",{enumerable:true,get:function(){return _accountAccess.resolveAccountAccess}});Object.defineProperty(exports,"resolveTier",{enumerable:true,get:function(){return _tier.resolveTier}});Object.defineProperty(exports,"sameLicenseKey",{enumerable:true,get:function(){return _serviceKey.sameLicenseKey}});Object.defineProperty(exports,"signCache",{enumerable:true,get:function(){return _cacheSignature.signCache}});Object.defineProperty(exports,"validateLicense",{enumerable:true,get:function(){return _api.validateLicense}});Object.defineProperty(exports,"verifyCacheSignature",{enumerable:true,get:function(){return _cacheSignature.verifyCacheSignature}});Object.defineProperty(exports,"verifyFreeToken",{enumerable:true,get:function(){return _freeToken.verifyFreeToken}});Object.defineProperty(exports,"verifySessionToken",{enumerable:true,get:function(){return _sessionToken.verifySessionToken}});var _api=require("./api.js");var _tier=require("./tier.js");var _freeToken=require("./freeToken.js");var _accountAccess=require("./accountAccess.js");var _cacheSignature=require("./cacheSignature.js");var _config=require("./config.js");var _nodeSession=require("./nodeSession.js");var _sessionManager=require("./sessionManager.js");var _sessionToken=require("./sessionToken.js");var _serviceKey=require("./serviceKey.js");var _devToken=require("./devToken.js");
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.useAccountAccess=useAccountAccess;exports.useFeatureAccess=useFeatureAccess;exports.useIsPro=useIsPro;exports.useLicense=useLicense;exports.useProAccess=useProAccess;exports.useTier=useTier;var _react=require("react");var _LicenseManager=require("./LicenseManager.js");var _weekendPro=require("./weekendPro.js");/*!
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.useAccountAccess=useAccountAccess;exports.useBuoySession=useBuoySession;exports.useFeatureAccess=useFeatureAccess;exports.useIsPro=useIsPro;exports.useLicense=useLicense;exports.useProAccess=useProAccess;exports.useTier=useTier;var _react=require("react");var _LicenseManager=require("./LicenseManager.js");var _weekendPro=require("./weekendPro.js");var _sessionManager=require("./sessionManager.js");/*!
2
2
  * PROPRIETARY — Buoy Pro license enforcement. NOT open source.
3
3
  *
4
4
  * Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
@@ -14,4 +14,4 @@
14
14
  * Pro is $9/mo, and is free every weekend for anyone holding a key —
15
15
  * including a free one (`npx buoy login`). Buy a key at
16
16
  * https://buoy.gg or use it free on Saturday and Sunday.
17
- */function useLicense(){const[t,e]=(0,_react.useState)(_LicenseManager.LicenseManager.getState());(0,_react.useEffect)(()=>{const n=_LicenseManager.LicenseManager.subscribe(r=>{e(_LicenseManager.LicenseManager.getState())});_LicenseManager.LicenseManager.initialize().then(()=>{e(_LicenseManager.LicenseManager.getState())});return n},[]);const c=(0,_react.useCallback)(async n=>{const r=await _LicenseManager.LicenseManager.setLicenseKey(n,{force:true});e(_LicenseManager.LicenseManager.getState());return r},[]);const s=(0,_react.useCallback)(async()=>{await _LicenseManager.LicenseManager.clearLicense();e(_LicenseManager.LicenseManager.getState())},[]);return{...t,setLicenseKey:c,clearLicense:s}}function useAccountAccess(){return useLicense().access}function useTier(){const{tier:t,isInitialized:e}=useLicense();return e?t:"free"}function useFeatureAccess(t){const{isPro:e,isInitialized:c,isValidating:s}=useLicense();const n=e;const r=!c||s;return{hasAccess:n,isPro:e,isLoading:r}}function useIsPro(){const{isPro:t,isInitialized:e,access:c}=useLicense();const s=(0,_weekendPro.weekendPassAppliesTo)(c.status==="admitted",(0,_weekendPro.useWeekendFreePro)());return e&&t||s}function useProAccess(){const{isPro:t,isInitialized:e,access:c}=useLicense();const s=e&&t;const n=(0,_weekendPro.weekendPassAppliesTo)(c.status==="admitted",(0,_weekendPro.useWeekendFreePro)())&&!s;const r=s?"licensed":n?"weekend":null;return{isPro:s||n,isLicensed:s,isWeekendFree:n,reason:r}}
17
+ */function useLicense(){const[t,e]=(0,_react.useState)(_LicenseManager.LicenseManager.getState());(0,_react.useEffect)(()=>{const s=_LicenseManager.LicenseManager.subscribe(a=>{e(_LicenseManager.LicenseManager.getState())});_LicenseManager.LicenseManager.initialize().then(()=>{e(_LicenseManager.LicenseManager.getState())});return s},[]);const r=(0,_react.useCallback)(async s=>{const a=await _LicenseManager.LicenseManager.setLicenseKey(s,{force:true});e(_LicenseManager.LicenseManager.getState());return a},[]);const n=(0,_react.useCallback)(async()=>{await _LicenseManager.LicenseManager.clearLicense();e(_LicenseManager.LicenseManager.getState())},[]);return{...t,setLicenseKey:r,clearLicense:n}}function useAccountAccess(){return useLicense().access}function useTier(){const{tier:t,isInitialized:e}=useLicense();return e?t:"free"}function useFeatureAccess(t){const{isPro:e,isInitialized:r,isValidating:n}=useLicense();const s=e;const a=!r||n;return{hasAccess:s,isPro:e,isLoading:a}}function useIsPro(){const{isPro:t,isInitialized:e,access:r}=useLicense();const n=(0,_weekendPro.weekendPassAppliesTo)(r.status==="admitted",(0,_weekendPro.useWeekendFreePro)());return e&&t||n}function useProAccess(){const{isPro:t,isInitialized:e,access:r}=useLicense();const n=e&&t;const s=(0,_weekendPro.weekendPassAppliesTo)(r.status==="admitted",(0,_weekendPro.useWeekendFreePro)())&&!n;const a=n?"licensed":s?"weekend":null;return{isPro:n||s,isLicensed:n,isWeekendFree:s,reason:a}}function useBuoySession(){const[t,e]=(0,_react.useState)(()=>_sessionManager.SessionManager.getStatus());(0,_react.useEffect)(()=>{const s=()=>e(_sessionManager.SessionManager.getStatus());const a=_sessionManager.SessionManager.subscribe(s);_sessionManager.SessionManager.load().then(s,s);return a},[]);const r=(0,_react.useCallback)(()=>_sessionManager.SessionManager.signIn(),[]);const n=(0,_react.useCallback)(()=>_sessionManager.SessionManager.signOut(),[]);return{status:t,signIn:r,signOut:n}}
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});Object.defineProperty(exports,"DeviceRegistrationModal",{enumerable:true,get:function(){return _DeviceRegistrationModal.DeviceRegistrationModal}});Object.defineProperty(exports,"LicenseManager",{enumerable:true,get:function(){return _LicenseManager.LicenseManager}});Object.defineProperty(exports,"LicenseTransportError",{enumerable:true,get:function(){return _api.LicenseTransportError}});exports.hasEntitlement=hasEntitlement;Object.defineProperty(exports,"isBuoyToken",{enumerable:true,get:function(){return _freeToken.isBuoyToken}});exports.isPro=isPro;Object.defineProperty(exports,"isTransientLicenseError",{enumerable:true,get:function(){return _api.isTransientLicenseError}});Object.defineProperty(exports,"isWeekendFreePro",{enumerable:true,get:function(){return _weekendPro.isWeekendFreePro}});Object.defineProperty(exports,"resolveAccountAccess",{enumerable:true,get:function(){return _accountAccess.resolveAccountAccess}});exports.setLicenseKey=setLicenseKey;Object.defineProperty(exports,"useAccountAccess",{enumerable:true,get:function(){return _hooks.useAccountAccess}});Object.defineProperty(exports,"useFeatureAccess",{enumerable:true,get:function(){return _hooks.useFeatureAccess}});Object.defineProperty(exports,"useIsPro",{enumerable:true,get:function(){return _hooks.useIsPro}});Object.defineProperty(exports,"useLicense",{enumerable:true,get:function(){return _hooks.useLicense}});Object.defineProperty(exports,"useProAccess",{enumerable:true,get:function(){return _hooks.useProAccess}});Object.defineProperty(exports,"useTier",{enumerable:true,get:function(){return _hooks.useTier}});Object.defineProperty(exports,"useWeekendFreePro",{enumerable:true,get:function(){return _weekendPro.useWeekendFreePro}});var _LicenseManager=require("./LicenseManager.js");var _DeviceRegistrationModal=require("./DeviceRegistrationModal.js");var _hooks=require("./hooks.js");var _accountAccess=require("./accountAccess.js");var _api=require("./api.js");var _freeToken=require("./freeToken.js");var _weekendPro=require("./weekendPro.js");function _interopRequireWildcard(r,t){if("function"==typeof WeakMap)var i=new WeakMap,a=new WeakMap;return(_interopRequireWildcard=function(e,c){if(!c&&e&&e.__esModule)return e;var n,u,o={__proto__:null,default:e};if(null===e||"object"!=typeof e&&"function"!=typeof e)return o;if(n=c?a:i){if(n.has(e))return n.get(e);n.set(e,o)}for(const s in e)"default"!==s&&{}.hasOwnProperty.call(e,s)&&((u=(n=Object.defineProperty)&&Object.getOwnPropertyDescriptor(e,s))&&(u.get||u.set)?n(o,s,u):o[s]=e[s]);return o})(r,t)}/*!
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});Object.defineProperty(exports,"DeviceRegistrationModal",{enumerable:true,get:function(){return _DeviceRegistrationModal.DeviceRegistrationModal}});Object.defineProperty(exports,"LicenseManager",{enumerable:true,get:function(){return _LicenseManager.LicenseManager}});Object.defineProperty(exports,"LicenseTransportError",{enumerable:true,get:function(){return _api.LicenseTransportError}});Object.defineProperty(exports,"SessionError",{enumerable:true,get:function(){return _sessionManager.SessionError}});Object.defineProperty(exports,"SessionManager",{enumerable:true,get:function(){return _sessionManager.SessionManager}});Object.defineProperty(exports,"getSyncCredential",{enumerable:true,get:function(){return _syncCredential.getSyncCredential}});exports.hasEntitlement=hasEntitlement;Object.defineProperty(exports,"isBuoyToken",{enumerable:true,get:function(){return _freeToken.isBuoyToken}});Object.defineProperty(exports,"isDevToken",{enumerable:true,get:function(){return _devToken.isDevToken}});exports.isPro=isPro;Object.defineProperty(exports,"isServiceKey",{enumerable:true,get:function(){return _serviceKey.isServiceKey}});Object.defineProperty(exports,"isTransientLicenseError",{enumerable:true,get:function(){return _api.isTransientLicenseError}});Object.defineProperty(exports,"isWeekendFreePro",{enumerable:true,get:function(){return _weekendPro.isWeekendFreePro}});Object.defineProperty(exports,"normalizeLicenseKey",{enumerable:true,get:function(){return _serviceKey.normalizeLicenseKey}});Object.defineProperty(exports,"resolveAccountAccess",{enumerable:true,get:function(){return _accountAccess.resolveAccountAccess}});Object.defineProperty(exports,"sameLicenseKey",{enumerable:true,get:function(){return _serviceKey.sameLicenseKey}});exports.setLicenseKey=setLicenseKey;Object.defineProperty(exports,"useAccountAccess",{enumerable:true,get:function(){return _hooks.useAccountAccess}});Object.defineProperty(exports,"useBuoySession",{enumerable:true,get:function(){return _hooks.useBuoySession}});Object.defineProperty(exports,"useFeatureAccess",{enumerable:true,get:function(){return _hooks.useFeatureAccess}});Object.defineProperty(exports,"useIsPro",{enumerable:true,get:function(){return _hooks.useIsPro}});Object.defineProperty(exports,"useLicense",{enumerable:true,get:function(){return _hooks.useLicense}});Object.defineProperty(exports,"useProAccess",{enumerable:true,get:function(){return _hooks.useProAccess}});Object.defineProperty(exports,"useTier",{enumerable:true,get:function(){return _hooks.useTier}});Object.defineProperty(exports,"useWeekendFreePro",{enumerable:true,get:function(){return _weekendPro.useWeekendFreePro}});var _LicenseManager=require("./LicenseManager.js");var _DeviceRegistrationModal=require("./DeviceRegistrationModal.js");var _hooks=require("./hooks.js");var _accountAccess=require("./accountAccess.js");var _api=require("./api.js");var _sessionManager=require("./sessionManager.js");var _serviceKey=require("./serviceKey.js");var _devToken=require("./devToken.js");var _syncCredential=require("./syncCredential.js");var _freeToken=require("./freeToken.js");var _weekendPro=require("./weekendPro.js");function _interopRequireWildcard(r,n){if("function"==typeof WeakMap)var u=new WeakMap,a=new WeakMap;return(_interopRequireWildcard=function(e,c){if(!c&&e&&e.__esModule)return e;var t,o,i={__proto__:null,default:e};if(null===e||"object"!=typeof e&&"function"!=typeof e)return i;if(t=c?a:u){if(t.has(e))return t.get(e);t.set(e,i)}for(const s in e)"default"!==s&&{}.hasOwnProperty.call(e,s)&&((o=(t=Object.defineProperty)&&Object.getOwnPropertyDescriptor(e,s))&&(o.get||o.set)?t(i,s,o):i[s]=e[s]);return i})(r,n)}/*!
2
2
  * PROPRIETARY — Buoy Pro license enforcement. NOT open source.
3
3
  *
4
4
  * Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
@@ -15,4 +15,4 @@
15
15
  * Pro is $9/mo, and is free every weekend for anyone holding a key —
16
16
  * including a free one (`npx buoy login`). Buy a key at
17
17
  * https://buoy.gg or use it free on Saturday and Sunday.
18
- */async function setLicenseKey(r){const{LicenseManager:t}=await Promise.resolve().then(()=>_interopRequireWildcard(require("./LicenseManager")));await t.initialize();return t.setLicenseKey(r)}function weekendPassActive(){const{isWeekendFreePro:r,weekendPassAppliesTo:t}=require("./weekendPro");const{LicenseManager:i}=require("./LicenseManager");return t(i.hasAccountAccess(),r())}function isPro(){const{LicenseManager:r}=require("./LicenseManager");if(r.isPro())return true;return weekendPassActive()}function hasEntitlement(r){const{LicenseManager:t}=require("./LicenseManager");if(t.hasEntitlement(r))return true;return weekendPassActive()}
18
+ */async function setLicenseKey(r){const{LicenseManager:n}=await Promise.resolve().then(()=>_interopRequireWildcard(require("./LicenseManager")));await n.initialize();return n.setLicenseKey(r)}function weekendPassActive(){const{isWeekendFreePro:r,weekendPassAppliesTo:n}=require("./weekendPro");const{LicenseManager:u}=require("./LicenseManager");return n(u.hasAccountAccess(),r())}function isPro(){const{LicenseManager:r}=require("./LicenseManager");if(r.isPro())return true;return weekendPassActive()}function hasEntitlement(r){const{LicenseManager:n}=require("./LicenseManager");if(n.hasEntitlement(r))return true;return weekendPassActive()}
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});Object.defineProperty(exports,"LicenseManager",{enumerable:true,get:function(){return _LicenseManager.LicenseManager}});Object.defineProperty(exports,"LicenseTransportError",{enumerable:true,get:function(){return _api.LicenseTransportError}});exports.hasEntitlement=hasEntitlement;Object.defineProperty(exports,"isBuoyToken",{enumerable:true,get:function(){return _freeToken.isBuoyToken}});exports.isPro=isPro;Object.defineProperty(exports,"isTransientLicenseError",{enumerable:true,get:function(){return _api.isTransientLicenseError}});Object.defineProperty(exports,"isWeekendFreePro",{enumerable:true,get:function(){return _weekendPro.isWeekendFreePro}});Object.defineProperty(exports,"resolveAccountAccess",{enumerable:true,get:function(){return _accountAccess.resolveAccountAccess}});exports.setLicenseKey=setLicenseKey;Object.defineProperty(exports,"useAccountAccess",{enumerable:true,get:function(){return _hooks.useAccountAccess}});Object.defineProperty(exports,"useFeatureAccess",{enumerable:true,get:function(){return _hooks.useFeatureAccess}});Object.defineProperty(exports,"useIsPro",{enumerable:true,get:function(){return _hooks.useIsPro}});Object.defineProperty(exports,"useLicense",{enumerable:true,get:function(){return _hooks.useLicense}});Object.defineProperty(exports,"useProAccess",{enumerable:true,get:function(){return _hooks.useProAccess}});Object.defineProperty(exports,"useTier",{enumerable:true,get:function(){return _hooks.useTier}});Object.defineProperty(exports,"useWeekendFreePro",{enumerable:true,get:function(){return _weekendPro.useWeekendFreePro}});var _LicenseManager=require("./LicenseManager.js");var _weekendPro=require("./weekendPro.js");var _hooks=require("./hooks.js");var _accountAccess=require("./accountAccess.js");var _api=require("./api.js");var _freeToken=require("./freeToken.js");function _interopRequireWildcard(n,u){if("function"==typeof WeakMap)var i=new WeakMap,a=new WeakMap;return(_interopRequireWildcard=function(e,c){if(!c&&e&&e.__esModule)return e;var r,o,s={__proto__:null,default:e};if(null===e||"object"!=typeof e&&"function"!=typeof e)return s;if(r=c?a:i){if(r.has(e))return r.get(e);r.set(e,s)}for(const t in e)"default"!==t&&{}.hasOwnProperty.call(e,t)&&((o=(r=Object.defineProperty)&&Object.getOwnPropertyDescriptor(e,t))&&(o.get||o.set)?r(s,t,o):s[t]=e[t]);return s})(n,u)}/*!
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});Object.defineProperty(exports,"LicenseManager",{enumerable:true,get:function(){return _LicenseManager.LicenseManager}});Object.defineProperty(exports,"LicenseTransportError",{enumerable:true,get:function(){return _api.LicenseTransportError}});Object.defineProperty(exports,"SessionError",{enumerable:true,get:function(){return _sessionManager.SessionError}});Object.defineProperty(exports,"SessionManager",{enumerable:true,get:function(){return _sessionManager.SessionManager}});Object.defineProperty(exports,"getSyncCredential",{enumerable:true,get:function(){return _syncCredential.getSyncCredential}});exports.hasEntitlement=hasEntitlement;Object.defineProperty(exports,"isBuoyToken",{enumerable:true,get:function(){return _freeToken.isBuoyToken}});Object.defineProperty(exports,"isDevToken",{enumerable:true,get:function(){return _devToken.isDevToken}});exports.isPro=isPro;Object.defineProperty(exports,"isServiceKey",{enumerable:true,get:function(){return _serviceKey.isServiceKey}});Object.defineProperty(exports,"isTransientLicenseError",{enumerable:true,get:function(){return _api.isTransientLicenseError}});Object.defineProperty(exports,"isWeekendFreePro",{enumerable:true,get:function(){return _weekendPro.isWeekendFreePro}});Object.defineProperty(exports,"normalizeLicenseKey",{enumerable:true,get:function(){return _serviceKey.normalizeLicenseKey}});Object.defineProperty(exports,"resolveAccountAccess",{enumerable:true,get:function(){return _accountAccess.resolveAccountAccess}});Object.defineProperty(exports,"sameLicenseKey",{enumerable:true,get:function(){return _serviceKey.sameLicenseKey}});exports.setLicenseKey=setLicenseKey;Object.defineProperty(exports,"useAccountAccess",{enumerable:true,get:function(){return _hooks.useAccountAccess}});Object.defineProperty(exports,"useBuoySession",{enumerable:true,get:function(){return _hooks.useBuoySession}});Object.defineProperty(exports,"useFeatureAccess",{enumerable:true,get:function(){return _hooks.useFeatureAccess}});Object.defineProperty(exports,"useIsPro",{enumerable:true,get:function(){return _hooks.useIsPro}});Object.defineProperty(exports,"useLicense",{enumerable:true,get:function(){return _hooks.useLicense}});Object.defineProperty(exports,"useProAccess",{enumerable:true,get:function(){return _hooks.useProAccess}});Object.defineProperty(exports,"useTier",{enumerable:true,get:function(){return _hooks.useTier}});Object.defineProperty(exports,"useWeekendFreePro",{enumerable:true,get:function(){return _weekendPro.useWeekendFreePro}});var _LicenseManager=require("./LicenseManager.js");var _weekendPro=require("./weekendPro.js");var _hooks=require("./hooks.js");var _accountAccess=require("./accountAccess.js");var _api=require("./api.js");var _sessionManager=require("./sessionManager.js");var _serviceKey=require("./serviceKey.js");var _devToken=require("./devToken.js");var _syncCredential=require("./syncCredential.js");var _freeToken=require("./freeToken.js");function _interopRequireWildcard(t,u){if("function"==typeof WeakMap)var c=new WeakMap,a=new WeakMap;return(_interopRequireWildcard=function(e,i){if(!i&&e&&e.__esModule)return e;var r,o,s={__proto__:null,default:e};if(null===e||"object"!=typeof e&&"function"!=typeof e)return s;if(r=i?a:c){if(r.has(e))return r.get(e);r.set(e,s)}for(const n in e)"default"!==n&&{}.hasOwnProperty.call(e,n)&&((o=(r=Object.defineProperty)&&Object.getOwnPropertyDescriptor(e,n))&&(o.get||o.set)?r(s,n,o):s[n]=e[n]);return s})(t,u)}/*!
2
2
  * PROPRIETARY — Buoy Pro license enforcement. NOT open source.
3
3
  *
4
4
  * Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
@@ -15,4 +15,4 @@
15
15
  * Pro is $9/mo, and is free every weekend for anyone holding a key —
16
16
  * including a free one (`npx buoy login`). Buy a key at
17
17
  * https://buoy.gg or use it free on Saturday and Sunday.
18
- */async function setLicenseKey(n){const{LicenseManager:u}=await Promise.resolve().then(()=>_interopRequireWildcard(require("./LicenseManager")));await u.initialize();return u.setLicenseKey(n)}function weekendPassActive(){return(0,_weekendPro.weekendPassAppliesTo)(_LicenseManager.LicenseManager.hasAccountAccess(),(0,_weekendPro.isWeekendFreePro)())}function isPro(){if(_LicenseManager.LicenseManager.isPro())return true;return weekendPassActive()}function hasEntitlement(n){if(_LicenseManager.LicenseManager.hasEntitlement(n))return true;return weekendPassActive()}
18
+ */async function setLicenseKey(t){const{LicenseManager:u}=await Promise.resolve().then(()=>_interopRequireWildcard(require("./LicenseManager")));await u.initialize();return u.setLicenseKey(t)}function weekendPassActive(){return(0,_weekendPro.weekendPassAppliesTo)(_LicenseManager.LicenseManager.hasAccountAccess(),(0,_weekendPro.isWeekendFreePro)())}function isPro(){if(_LicenseManager.LicenseManager.isPro())return true;return weekendPassActive()}function hasEntitlement(t){if(_LicenseManager.LicenseManager.hasEntitlement(t))return true;return weekendPassActive()}
@@ -0,0 +1,6 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.DESKTOP_AUDIENCE=exports.CLI_AUDIENCE=void 0;exports.createNodeSession=createNodeSession;exports.defaultSessionFile=defaultSessionFile;exports.fileLock=fileLock;exports.fileSessionStorage=fileSessionStorage;exports.receiveCodeOnLoopback=receiveCodeOnLoopback;var _nodeHttp=_interopRequireDefault(require("node:http"));var _nodeCrypto=require("node:crypto");var _nodeFs=require("node:fs");var _nodePath=require("node:path");var _nodeOs=require("node:os");var _sessionManager=require("./sessionManager.js");function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}/*!
2
+ * PROPRIETARY — Buoy license enforcement. NOT open source.
3
+ *
4
+ * Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
5
+ * (https://buoy.gg/terms), not an OSS license.
6
+ */const DESKTOP_AUDIENCE=exports.DESKTOP_AUDIENCE="app:gg.buoy.desktop";const CLI_AUDIENCE=exports.CLI_AUDIENCE="app:gg.buoy.cli";const LOGIN_TIMEOUT_MS=5*60*1e3;const MAX_BODY_BYTES=4096;const LOCK_STALE_MS=6e4;const LOCK_WAIT_MS=3e4;function defaultSessionFile(){return process.env.BUOY_SESSION_FILE||(0,_nodePath.join)((0,_nodeOs.homedir)(),".buoy","session.json")}function fileSessionStorage(e){const a=async()=>{try{const o=JSON.parse(await _nodeFs.promises.readFile(e,"utf8"));return o&&typeof o==="object"?o:{}}catch{return{}}};const c=async o=>{await _nodeFs.promises.mkdir((0,_nodePath.dirname)(e),{recursive:true,mode:448});if(Object.keys(o).length===0){await _nodeFs.promises.rm(e,{force:true});return}const i=`${e}.${process.pid}.${(0,_nodeCrypto.randomBytes)(4).toString("hex")}.tmp`;await _nodeFs.promises.writeFile(i,JSON.stringify(o),{mode:384});await _nodeFs.promises.rename(i,e)};return{async getItem(o){return(await a())[o]??null},async setItem(o,i){const u=await a();u[o]=i;await c(u)},async removeItem(o){const i=await a();if(!(o in i))return;delete i[o];await c(i)}}}function fileLock(e,a={}){const c=a.staleMs??LOCK_STALE_MS;const o=a.waitMs??LOCK_WAIT_MS;return async(i,u)=>{const r=`${process.pid}:${(0,_nodeCrypto.randomBytes)(8).toString("hex")}`;const t=Date.now()+o;await _nodeFs.promises.mkdir((0,_nodePath.dirname)(e),{recursive:true,mode:448});for(;;){try{await _nodeFs.promises.writeFile(e,r,{flag:"wx",mode:384});break}catch(n){if(n.code!=="EEXIST")throw n;const s=await _nodeFs.promises.stat(e).catch(()=>null);if(s&&Date.now()-s.mtimeMs>c){await _nodeFs.promises.rm(e,{force:true});continue}if(Date.now()>t)throw new Error("Another Buoy process holds the sign-in lock.");await new Promise(p=>setTimeout(p,50))}}try{return await u()}finally{const n=await _nodeFs.promises.readFile(e,"utf8").catch(()=>null);if(n===r)await _nodeFs.promises.rm(e,{force:true})}}}function safeEqual(e,a){const c=Buffer.from(e);const o=Buffer.from(a);return c.length===o.length&&(0,_nodeCrypto.timingSafeEqual)(c,o)}async function receiveCodeOnLoopback(e,a,c,o={}){let i;let u;const r=new Promise((d,l)=>{i=d;u=l});r.catch(()=>{});const t=_nodeHttp.default.createServer((d,l)=>{if(d.headers.origin===c){l.setHeader("Access-Control-Allow-Origin",c);l.setHeader("Access-Control-Allow-Headers","Content-Type");l.setHeader("Access-Control-Allow-Methods","POST, OPTIONS");l.setHeader("Access-Control-Allow-Private-Network","true")}if(d.method==="OPTIONS")return void l.writeHead(204).end();if(d.method!=="POST")return void l.writeHead(405).end();let m="";d.on("data",f=>{m+=f;if(m.length>MAX_BODY_BYTES)d.destroy()});d.on("end",()=>{let f=null;try{f=JSON.parse(m)}catch{}if(!f||typeof f.state!=="string"||!safeEqual(f.state,a))return void l.writeHead(400).end();l.writeHead(200,{"Content-Type":"application/json"}).end('{"ok":true}');if(typeof f.code==="string"&&f.code)p(()=>i(f.code));else p(()=>u(new _sessionManager.SessionError("access_denied","Sign-in was cancelled.")))})});const n=setTimeout(()=>p(()=>u(new _sessionManager.SessionError("timeout","Sign-in took too long."))),o.timeoutMs??LOGIN_TIMEOUT_MS);n.unref?.();const s=()=>p(()=>u(new _sessionManager.SessionError("popup_closed","Sign-in was cancelled.")));o.signal?.addEventListener("abort",s);function p(d){clearTimeout(n);o.signal?.removeEventListener("abort",s);t.close();d()}await new Promise((d,l)=>{t.once("error",l);t.listen(0,"127.0.0.1",()=>d())});const w=t.address();if(!w||typeof w==="string"){p(()=>u(new Error("Could not open a local port")));throw new Error("Could not open a local port")}return{url:`${e}&port=${w.port}`,code:r}}function createNodeSession(e){const a=defaultSessionFile();const c=e.storage??fileSessionStorage(a);const o=(e.signinOrigin??process.env.BUOY_SITE_URL??"https://buoy.gg").replace(/\/$/,"");const i=e.fetch??((t,n)=>fetch(t,n));const u={fetch:i,storage:async()=>c,now:e.now??(()=>Date.now()),random:t=>new Uint8Array((0,_nodeCrypto.randomBytes)(t)),sha256:async t=>new Uint8Array((0,_nodeCrypto.createHash)("sha256").update(t).digest()),openPopup:()=>null,onMessage:()=>()=>{},withLock:fileLock(e.lockFile??`${a}.lock`),setTimer:(t,n)=>{const s=setTimeout(t,Math.min(n,2147483647));s.unref?.();return s},clearTimer:t=>clearTimeout(t),publicKeyHex:e.publicKeyHex};const r=new _sessionManager.SessionManagerImpl(u);r.configure({audience:e.audience,signinOrigin:o});return{manager:r,async load(){await r.load();return r.getStatus()},getStatus:()=>r.getStatus(),signIn:(t={})=>r.signInWith(async(n,s)=>{const{url:p,code:w}=await receiveCodeOnLoopback(n,s,o,t);await e.openBrowser(p);return w}),signOut:()=>r.signOut(),refresh:t=>r.refresh(t),sync:()=>r.sync(),async devToken(){const t=r.getAccessToken();if(!t)return{ok:false,detail:"This computer is not signed in. Run `npx buoy login`."};try{const n=await i(`${o}/api/auth/dev-token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({access_token:t})});const s=await n.json().catch(()=>null);if(n.status===200&&typeof s?.dev_token==="string"){return{ok:true,token:s.dev_token,tier:typeof s.tier==="string"?s.tier:"free"}}return{ok:false,detail:typeof s?.error_description==="string"?s.error_description:"buoy.gg did not make a dev token."}}catch{return{ok:false,detail:"Buoy could not be reached. Check your connection and try again."}}},async isAvailable(){try{const t=await i(`${o}/api/auth/status`,{method:"GET",headers:{}});const n=await t.json().catch(()=>null);return t.status===200&&n?.enabled===true}catch{return false}},subscribe:t=>r.subscribe(t)}}
@@ -0,0 +1,6 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.SERVICE_KEY_PREFIX=exports.SERVICE_AUDIENCE=void 0;exports.exchangeServiceKey=exchangeServiceKey;exports.isServiceKey=isServiceKey;exports.normalizeLicenseKey=normalizeLicenseKey;exports.sameLicenseKey=sameLicenseKey;var _sessionToken=require("./sessionToken.js");var _realNow=require("./realNow.js");/*!
2
+ * PROPRIETARY — Buoy license enforcement. NOT open source.
3
+ *
4
+ * Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
5
+ * (https://buoy.gg/terms), not an OSS license.
6
+ */const SERVICE_KEY_PREFIX=exports.SERVICE_KEY_PREFIX="bsk1_";const SERVICE_AUDIENCE=exports.SERVICE_AUDIENCE="service";const CALL_TIMEOUT_MS=15e3;function isServiceKey(o){return o.startsWith(SERVICE_KEY_PREFIX)}function normalizeLicenseKey(o){const e=o.trim();return isServiceKey(e)||(0,_sessionToken.isSessionToken)(e)?e:e.toUpperCase()}function sameLicenseKey(o,e){return normalizeLicenseKey(o??"")===normalizeLicenseKey(e??"")}async function exchangeServiceKey(o,e){const c=e.fetch??((r,l)=>fetch(r,l));const n=typeof AbortController!=="undefined"?new AbortController:void 0;const a=setTimeout(()=>n?.abort(),CALL_TIMEOUT_MS);let s;let t;try{const r=await c(`${e.origin.replace(/\/$/,"")}/api/auth/service-token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:o}),signal:n?.signal});s=r.status;t=await r.json().catch(()=>null)}catch{return{ok:false,reason:"network",detail:"Buoy could not be reached to check the bot key."}}finally{clearTimeout(a)}if(s>=500||s===429)return{ok:false,reason:"network",detail:"Buoy is busy. The bot key will be checked again soon."};if(s!==200||typeof t?.access_token!=="string"){return{ok:false,reason:"rejected",detail:typeof t?.error_description==="string"?t.error_description:"This bot key was not accepted."}}const i=(0,_sessionToken.verifySessionToken)(t.access_token,{audience:SERVICE_AUDIENCE,nowMs:(0,_realNow.realNow)(),publicKeyHex:e.publicKeyHex});return i.ok?{ok:true,claims:i.claims}:{ok:false,reason:"rejected",detail:"Buoy sent a token this app could not check."}}
@@ -0,0 +1,6 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.SessionManagerImpl=exports.SessionManager=exports.SessionError=exports.SESSION_STORAGE_PREFIX=exports.SESSION_RETRY_MS=exports.SESSION_REFRESH_LEAD_MS=exports.SESSION_OFFLINE_GRACE_MS=exports.SESSION_CALL_TIMEOUT_MS=exports.DEFAULT_SIGNIN_ORIGIN=void 0;var _storage=require("./storage");var _sessionToken=require("./sessionToken.js");var _realNow=require("./realNow.js");/*!
2
+ * PROPRIETARY — Buoy license enforcement. NOT open source.
3
+ *
4
+ * Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
5
+ * (https://buoy.gg/terms), not an OSS license.
6
+ */const SESSION_STORAGE_PREFIX=exports.SESSION_STORAGE_PREFIX="@buoy/session:";const SESSION_OFFLINE_GRACE_MS=exports.SESSION_OFFLINE_GRACE_MS=7*24*60*60*1e3;const SESSION_REFRESH_LEAD_MS=exports.SESSION_REFRESH_LEAD_MS=6*60*60*1e3;const SESSION_RETRY_MS=exports.SESSION_RETRY_MS=5*60*1e3;const SESSION_CALL_TIMEOUT_MS=exports.SESSION_CALL_TIMEOUT_MS=15e3;const DEFAULT_SIGNIN_ORIGIN=exports.DEFAULT_SIGNIN_ORIGIN="https://buoy.gg";const MESSAGE_TYPE="buoy:signin";const POPUP_TIMEOUT_MS=10*60*1e3;class SessionError extends Error{constructor(e,t){super(t);this.code=e;this.name="SessionError"}}exports.SessionError=SessionError;function browserDeps(){const s=globalThis;return{fetch:(e,t)=>fetch(e,t),storage:_storage.getLicenseStorage,now:_realNow.realNow,random:e=>{const t=new Uint8Array(e);if(!s.crypto?.getRandomValues)throw new SessionError("not_configured","This platform has no secure random source.");return s.crypto.getRandomValues(t)},sha256:async e=>{if(!s.crypto?.subtle)throw new SessionError("not_configured","Sign-in needs a secure page (https or localhost).");return new Uint8Array(await s.crypto.subtle.digest("SHA-256",e))},openPopup:()=>{if(!s.window?.open)return null;const e=480;const t=640;const i=Math.max(0,(s.window.screenX??0)+((s.window.outerWidth??e)-e)/2);const n=Math.max(0,(s.window.screenY??0)+((s.window.outerHeight??t)-t)/2);return s.window.open("about:blank","buoy-signin",`popup,width=${e},height=${t},left=${i},top=${n}`)},onMessage:e=>{if(!s.window?.addEventListener)return()=>{};const t=i=>e({origin:i.origin,data:i.data});s.window.addEventListener("message",t);return()=>s.window?.removeEventListener("message",t)},withLock:(e,t)=>s.navigator?.locks?s.navigator.locks.request(e,t):t(),watch:e=>{const t=s.window;if(!t?.addEventListener)return()=>{};const i=r=>e.storage(r.key);const n=()=>{if(t.document?.visibilityState!=="hidden")e.wake()};t.addEventListener("storage",i);t.addEventListener("online",e.wake);t.document?.addEventListener?.("visibilitychange",n);return()=>{t.removeEventListener("storage",i);t.removeEventListener("online",e.wake);t.document?.removeEventListener?.("visibilitychange",n)}},setTimer:(e,t)=>setTimeout(e,Math.min(t,2147483647)),clearTimer:e=>clearTimeout(e)}}function defaultAudience(){const s=globalThis.location;if(!s?.origin||!/^https?:$/.test(s.protocol??""))return void 0;return s.origin}class SessionManagerImpl{signinOrigin=DEFAULT_SIGNIN_ORIGIN;current=null;claims=null;listeners=new Set;timer=null;refreshing=null;loaded=null;unwatch=null;limitTimer=null;epoch=0;constructor(e){this.deps=e??browserDeps();this.audience=defaultAudience()}get origin(){return this.signinOrigin}configure(e){if(e.audience!==void 0)this.audience=e.audience;if(e.signinOrigin!==void 0)this.signinOrigin=e.signinOrigin.replace(/\/$/,"");this.reset()}__setDeps(e){this.deps=e;this.reset()}reset(){this.unwatch?.();this.unwatch=null;this.epoch+=1;if(this.limitTimer!==null)this.deps.clearTimer(this.limitTimer);this.limitTimer=null;if(this.timer!==null)this.deps.clearTimer(this.timer);this.timer=null;this.current=null;this.claims=null;this.loaded=null;this.refreshing=null}get storageKey(){return SESSION_STORAGE_PREFIX+(this.audience??"")}subscribe(e){this.listeners.add(e);return()=>this.listeners.delete(e)}notify(){for(const e of[...this.listeners]){try{e()}catch(t){console.warn("[Buoy] sign-in listener error:",t)}}}getAccessToken(){const e=this.getStatus();return e.state==="active"&&!e.grace?this.current?.accessToken??null:null}getStatus(){const e=this.claims;if(!e)return{state:"signed_out"};const t=e.exp*1e3;const i=this.deps.now();if(i<(e.iat-_sessionToken.SESSION_CLOCK_SKEW_SECONDS)*1e3)return{state:"signed_out"};if(i<t)return{state:"active",claims:e,grace:false,validUntil:t};if(i<t+SESSION_OFFLINE_GRACE_MS){return{state:"active",claims:e,grace:true,validUntil:t+SESSION_OFFLINE_GRACE_MS}}return{state:"signed_out"}}load(){if(!this.loaded)this.loaded=this.loadOnce();return this.loaded}async loadOnce(){if(!this.audience)return;this.unwatch??=this.deps.watch?.({storage:t=>{if(t===null||t===this.storageKey)void this.sync()},wake:()=>{if(this.claims)void this.refresh()}})??null;const e=await this.read();if(e&&this.adopt(e)){this.notify();this.schedule()}}async sync(){if(!this.audience)return;const e=await this.read();if(!e){if(this.current)this.clearLocal();return}if(e.refreshToken!==this.current?.refreshToken&&this.adopt(e)){this.notify();this.schedule()}}async read(){try{const e=await(await this.deps.storage()).getItem(this.storageKey);if(!e)return null;const t=JSON.parse(e);return t?.v===1&&typeof t.accessToken==="string"&&typeof t.refreshToken==="string"?t:null}catch{return null}}async write(e){const t=await this.deps.storage();if(e)await t.setItem(this.storageKey,JSON.stringify(e));else await t.removeItem(this.storageKey)}adopt(e){if(!this.audience)return false;const t=(0,_sessionToken.verifySessionToken)(e.accessToken,{audience:this.audience,ignoreTime:true,publicKeyHex:this.deps.publicKeyHex});const i=t.ok?t.claims:null;if(!i)return false;this.current=e;this.claims=i;return true}armLimit(){if(this.limitTimer!==null)this.deps.clearTimer(this.limitTimer);this.limitTimer=null;if(!this.claims)return;const e=this.claims.exp*1e3;const t=this.deps.now();const i=t<e?e:t<e+SESSION_OFFLINE_GRACE_MS?e+SESSION_OFFLINE_GRACE_MS:null;if(i===null)return;this.limitTimer=this.deps.setTimer(()=>{this.limitTimer=null;this.notify();this.armLimit()},i-t)}call(e,t){return new Promise((i,n)=>{const r=this.deps.setTimer(()=>n(new Error("timeout")),SESSION_CALL_TIMEOUT_MS);this.deps.fetch(e,t).then(o=>{this.deps.clearTimer(r);i(o)},o=>{this.deps.clearTimer(r);n(o)})})}schedule(){this.armLimit();if(this.timer!==null)this.deps.clearTimer(this.timer);this.timer=null;if(!this.claims)return;const e=this.claims.exp*1e3-SESSION_REFRESH_LEAD_MS-this.deps.now();this.timer=this.deps.setTimer(()=>{this.timer=null;void this.refresh()},Math.max(0,e))}refresh(e=false){if(!this.refreshing){this.refreshing=this.deps.withLock(this.lockName,()=>this.refreshLocked(e)).catch(()=>this.retryLater()).finally(()=>{this.refreshing=null})}return this.refreshing}get lockName(){return`buoy-session:${this.audience??""}`}async refreshLocked(e){const t=this.epoch;const i=await this.read();if(!i){if(this.current)this.clearLocal();return}if(i.refreshToken!==this.current?.refreshToken){if(this.adopt(i)){this.notify();this.schedule();return}}if(!this.claims)return;if(!e&&this.claims.exp*1e3-this.deps.now()>SESSION_REFRESH_LEAD_MS){this.schedule();return}let n;let r;try{const o=await this.call(`${this.signinOrigin}/api/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refresh_token:i.refreshToken,audience:this.audience})});n=o.status;r=await o.json().catch(()=>null)}catch{this.retryLater();return}if(t!==this.epoch)return;if(n===200&&r&&typeof r.access_token==="string"&&typeof r.refresh_token==="string"){const o={v:1,accessToken:r.access_token,refreshToken:r.refresh_token};if(this.adopt(o)){await this.write(o);this.notify();this.schedule();return}}if(n===400||n===401||n===403){await this.write(null);this.clearLocal();return}this.retryLater()}retryLater(){this.armLimit();if(this.timer!==null)this.deps.clearTimer(this.timer);this.timer=this.deps.setTimer(()=>{this.timer=null;void this.refresh(true)},SESSION_RETRY_MS);this.notify()}clearLocal(){if(this.timer!==null)this.deps.clearTimer(this.timer);this.timer=null;if(this.limitTimer!==null)this.deps.clearTimer(this.limitTimer);this.limitTimer=null;this.current=null;this.claims=null;this.notify()}async signIn(){if(!this.audience)throw new SessionError("not_configured","Sign-in needs a web page or a configured app id.");const e=this.deps.openPopup();if(!e)throw new SessionError("popup_blocked","The browser blocked the sign-in window. Allow pop-ups for this site and try again.");try{return await this.signInWith((t,i)=>new Promise((n,r)=>{e.location.href=t;const o=this.deps.now();let h=null;const c=l=>{if(h!==null)this.deps.clearTimer(h);a();l()};const a=this.deps.onMessage(l=>{if(l.origin!==this.signinOrigin)return;const d=l.data;if(!d||d.type!==MESSAGE_TYPE||d.state!==i)return;if(typeof d.code==="string")c(()=>n(d.code));else c(()=>r(new SessionError("access_denied","Sign-in was cancelled.")))});const u=()=>{if(e.closed)return c(()=>r(new SessionError("popup_closed","The sign-in window was closed.")));if(this.deps.now()-o>POPUP_TIMEOUT_MS)return c(()=>r(new SessionError("timeout","Sign-in took too long.")));h=this.deps.setTimer(u,500)};h=this.deps.setTimer(u,500)}))}finally{try{if(!e.closed)e.close()}catch{}}}async signInWith(e){const t=this.audience;if(!t)throw new SessionError("not_configured","Sign-in needs a web page or a configured app id.");const i=(0,_sessionToken.base64urlEncode)(this.deps.random(32));const n=(0,_sessionToken.base64urlEncode)(this.deps.random(16));const r=(0,_sessionToken.base64urlEncode)(await this.deps.sha256(new TextEncoder().encode(i)));const o=`${this.signinOrigin}/auth/authorize?audience=${encodeURIComponent(t)}&code_challenge=${r}&code_challenge_method=S256&state=${n}`;const h=await e(o,n);let c;try{c=await this.call(`${this.signinOrigin}/api/auth/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:h,code_verifier:i,audience:t})})}catch{throw new SessionError("network","Buoy could not be reached. Check your connection and try again.")}const a=await c.json().catch(()=>null);if(c.status!==200||!a||typeof a.access_token!=="string"||typeof a.refresh_token!=="string"){const l=a&&typeof a.error_description==="string"?a.error_description:"Buoy did not accept this sign-in.";throw new SessionError(c.status===503?"unavailable":"rejected",l)}const u={v:1,accessToken:a.access_token,refreshToken:a.refresh_token};this.epoch+=1;if(!this.adopt(u))throw new SessionError("rejected","Buoy sent a sign-in this app could not check.");await this.write(u);await this.load();this.notify();this.schedule();return this.getStatus()}async signOut(){this.epoch+=1;const e=this.current;this.clearLocal();let t=e;try{await this.deps.withLock(this.lockName,async()=>{t=await this.read()??e;await this.write(null)})}catch{await this.write(null).catch(()=>{})}if(!t)return;try{await this.call(`${this.signinOrigin}/api/auth/revoke`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refresh_token:t.refreshToken})})}catch{}}}exports.SessionManagerImpl=SessionManagerImpl;const SessionManager=exports.SessionManager=new SessionManagerImpl;
@@ -0,0 +1,6 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.SESSION_TOKEN_PREFIX=exports.SESSION_CLOCK_SKEW_SECONDS=void 0;exports.__setSessionTokenPublicKeyForTests=__setSessionTokenPublicKeyForTests;exports.base64urlEncode=base64urlEncode;exports.isSessionToken=isSessionToken;exports.mintSessionToken=mintSessionToken;exports.verifySessionToken=verifySessionToken;var _tweetnacl=_interopRequireDefault(require("tweetnacl"));var _config=require("./config.js");var _realNow=require("./realNow.js");function _interopRequireDefault(t){return t&&t.__esModule?t:{default:t}}/*!
2
+ * PROPRIETARY — Buoy Pro license enforcement. NOT open source.
3
+ *
4
+ * Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
5
+ * (https://buoy.gg/terms), not an OSS license.
6
+ */const SESSION_TOKEN_PREFIX=exports.SESSION_TOKEN_PREFIX="buoys1";const SESSION_TOKEN_DOMAIN="buoy-session-v1:";const SESSION_TOKEN_VERSION=1;const SESSION_CLOCK_SKEW_SECONDS=exports.SESSION_CLOCK_SKEW_SECONDS=60;const SIGNATURE_LENGTH=64;const TIERS=["free","pro","business"];const B64="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";function base64urlEncode(t){let e="";let r=0;for(;r+2<t.length;r+=3){const n=t[r]<<16|t[r+1]<<8|t[r+2];e+=B64[n>>>18&63]+B64[n>>>12&63]+B64[n>>>6&63]+B64[n&63]}const o=t.length-r;if(o===1){const n=t[r]<<16;e+=B64[n>>>18&63]+B64[n>>>12&63]}else if(o===2){const n=t[r]<<16|t[r+1]<<8;e+=B64[n>>>18&63]+B64[n>>>12&63]+B64[n>>>6&63]}return e}function base64urlDecode(t){if(!/^[A-Za-z0-9_-]*$/.test(t)||t.length%4===1)return null;const e=[];let r=0;let o=0;for(const n of t){o=o<<6|B64.indexOf(n);r+=6;if(r>=8){e.push(o>>>r-8&255);r-=8}}return new Uint8Array(e)}function utf8Encode(t){if(typeof TextEncoder!=="undefined")return new TextEncoder().encode(t);const e=unescape(encodeURIComponent(t));const r=new Uint8Array(e.length);for(let o=0;o<e.length;o+=1)r[o]=e.charCodeAt(o);return r}function utf8Decode(t){try{if(typeof TextDecoder!=="undefined")return new TextDecoder("utf-8",{fatal:true}).decode(t);let e="";for(const r of t)e+=String.fromCharCode(r);return decodeURIComponent(escape(e))}catch{return null}}function hexToBytes(t){const e=t.trim().toLowerCase();const r=new Uint8Array(e.length/2);for(let o=0;o<r.length;o+=1)r[o]=parseInt(e.slice(o*2,o*2+2),16);return r}function signedMessage(t){return utf8Encode(SESSION_TOKEN_DOMAIN+t)}function isShortString(t,e=256){return typeof t==="string"&&t.length>0&&t.length<=e}function isSeconds(t){return typeof t==="number"&&Number.isInteger(t)&&t>0}function readClaims(t){if(!t||typeof t!=="object"||Array.isArray(t))return null;const e=t;if(!isShortString(e.sid)||!isShortString(e.sub)||!isShortString(e.aud,512))return null;if(e.team!==null&&!isShortString(e.team))return null;if(!TIERS.includes(e.tier))return null;if(e.role!==void 0&&!isShortString(e.role,64))return null;if(e.tools!==void 0&&(!Array.isArray(e.tools)||e.tools.length>256||!e.tools.every(r=>isShortString(r,64)))){return null}if(!isSeconds(e.iat)||!isSeconds(e.exp)||e.exp<=e.iat)return null;return{v:SESSION_TOKEN_VERSION,sid:e.sid,sub:e.sub,team:e.team,tier:e.tier,...e.role!==void 0?{role:e.role}:{},...e.tools!==void 0?{tools:[...e.tools]}:{},aud:e.aud,iat:e.iat,exp:e.exp}}function mintSessionToken(t,e){const r=base64urlEncode(utf8Encode(JSON.stringify(t)));const{secretKey:o}=_tweetnacl.default.sign.keyPair.fromSeed(hexToBytes(e));const n=_tweetnacl.default.sign.detached(signedMessage(r),o);return`${SESSION_TOKEN_PREFIX}.${r}.${base64urlEncode(n)}`}let activePublicKey=_config.SESSION_TOKEN_PUBLIC_KEY;function __setSessionTokenPublicKeyForTests(t){activePublicKey=t??_config.SESSION_TOKEN_PUBLIC_KEY}function isSessionToken(t){return t.startsWith(`${SESSION_TOKEN_PREFIX}.`)}function verifySessionToken(t,e){const r=e.publicKeyHex??activePublicKey;if(!r)return{ok:false,reason:"no-key"};const o=typeof t==="string"?t.split("."):[];if(o.length!==3||o[0]!==SESSION_TOKEN_PREFIX)return{ok:false,reason:"malformed"};const[,n,f]=o;const l=base64urlDecode(n);const u=base64urlDecode(f);if(!l||!u||u.length!==SIGNATURE_LENGTH)return{ok:false,reason:"malformed"};try{if(!_tweetnacl.default.sign.detached.verify(signedMessage(n),u,hexToBytes(r))){return{ok:false,reason:"signature"}}}catch{return{ok:false,reason:"signature"}}const a=utf8Decode(l);let s;try{s=a===null?null:JSON.parse(a)}catch{return{ok:false,reason:"malformed"}}if(!s||typeof s!=="object"||s.v!==SESSION_TOKEN_VERSION){return{ok:false,reason:s&&typeof s==="object"?"version":"malformed"}}const i=readClaims(s);if(!i)return{ok:false,reason:"claims"};if(i.aud!==e.audience)return{ok:false,reason:"audience"};if(e.ignoreTime)return{ok:true,claims:i};const c=Math.floor((e.nowMs??(0,_realNow.realNow)())/1e3);if(c>=i.exp+SESSION_CLOCK_SKEW_SECONDS)return{ok:false,reason:"expired"};if(i.iat>c+SESSION_CLOCK_SKEW_SECONDS)return{ok:false,reason:"not-yet-valid"};return{ok:true,claims:i}}
@@ -0,0 +1,6 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.getSyncCredential=getSyncCredential;var _LicenseManager=require("./LicenseManager.js");var _sessionManager=require("./sessionManager.js");var _devToken=require("./devToken.js");/*!
2
+ * PROPRIETARY — Buoy license enforcement. NOT open source.
3
+ *
4
+ * Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
5
+ * (https://buoy.gg/terms), not an OSS license.
6
+ */function getSyncCredential(){const n=_sessionManager.SessionManager.getAccessToken();if(n)return{token:n,origin:_sessionManager.SessionManager.origin};const e=_LicenseManager.LicenseManager.getState().licenseKey;if(e&&(0,_devToken.isDevToken)(e)&&_LicenseManager.LicenseManager.hasAccountAccess()&&(0,_devToken.checkDevToken)(e).ok){return{token:e,origin:_sessionManager.SessionManager.origin}}return null}
@@ -13,4 +13,4 @@
13
13
  * Pro is $9/mo, and is free every weekend for anyone holding a key —
14
14
  * including a free one (`npx buoy login`). Buy a key at
15
15
  * https://buoy.gg or use it free on Saturday and Sunday.
16
- */import{getLicenseStorage as u}from"./storage";import{KEYGEN_CONFIG as H,LICENSE_STORAGE_KEY as R,LICENSE_CACHE_DURATION as M,LICENSE_REVALIDATION_INTERVAL as Y,LICENSE_LAUNCH_VALIDATION_TTL as B,LICENSE_TRANSIENT_RETRY_DELAYS as X,LICENSE_RATE_LIMIT_DEFAULT_WAIT as q,LICENSE_QUOTA_COOLDOWN as k,LICENSE_VERDICT_CACHE_DURATION as J,LICENSE_FLEET_MACHINE_THRESHOLD as Q,LICENSE_QUIET_VALIDATION_TTL as W,LICENSE_HOLD_STORAGE_KEY as C,DEVICE_FINGERPRINT_STORAGE_KEY as N}from"./config.js";import{validateLicense as j,activateMachine as F,parseValidationResult as $,isFatalLicenseError as Z,isTransientLicenseError as ee,isAcceptedValidation as te,isRateLimited as ie,backoffAfter as se,machineCount as re}from"./api.js";import{generateUUID as P,getDeviceMetadata as O,getDefaultDeviceName as V,isDevBundle as G}from"./fingerprint";import{signCache as b,verifyCacheSignature as p}from"./cacheSignature.js";import{isBuoyToken as ae,verifyFreeToken as ne}from"./freeToken.js";import{resolveTier as ce,isRecognizedAccount as he}from"./tier.js";import{resolveAccountAccess as oe}from"./accountAccess.js";import{subscribeForeground as le}from"./foreground";import{realNow as h}from"./realNow.js";async function _(d,e){let t;try{return await Promise.race([d,new Promise(i=>{t=setTimeout(()=>i(e),15e3)})])}finally{if(t)clearTimeout(t)}}function m(d){if(d.tier==="pro"||d.tier==="free")return d.tier;return d.isPro?"pro":"free"}class de{state={isInitialized:false,isValidating:false,isPro:false,tier:"free",tierSource:"none",licenseKey:null,error:null,errorKind:null,expiresAt:null};listeners=new Set;revalidationTimer=null;cachedLicense=null;fingerprintPromise=null;initPromise=null;generation=0;persistence=Promise.resolve();verifiedAt=null;expiryTimer=null;removeForegroundListener=null;retryTimer=null;retryAttempt=0;deviceRegistrationCallback=null;pendingRegistration=null;async initialize(){if(this.initPromise)return this.initPromise;if(this.state.isInitialized)return;this.initPromise=this._doInitialize();return this.initPromise}async _doInitialize(){if(this.state.isInitialized)return;const e=this.generation;try{const t=await _(this.loadCachedLicense(),null);if(e!==this.generation){this.state.isInitialized=true;this.emit({type:"initialized",isPro:this.state.isPro});this.startRevalidationTimer();return}if(t&&(this.configuredKey===void 0||t.licenseKey===this.configuredKey)){const i=p(t);this.cachedLicense=t;this.state.licenseKey=t.licenseKey;if(i&&this.isCacheValid(t))this.applyTier(m(t));else this.lock();this.state.expiresAt=t.expiresAt?new Date(t.expiresAt):null;if(i&&this.isCacheValid(t))this.setVerifiedAt(t.cachedAt);if(this.configuredKey===void 0&&t.licenseKey&&!(i&&this.isCacheValid(t)&&this.isCacheFresh(t))){this.validateInBackground(t.licenseKey)}}this.state.isInitialized=true;this.emit({type:"initialized",isPro:this.state.isPro});this.startRevalidationTimer()}catch(t){console.warn("[React Buoy] License initialization failed:",t);this.state.isInitialized=true;this.emit({type:"initialized",isPro:false})}}async configure(e){if(e===void 0){await this.initialize();return this.hasAccountAccess()}const t=e.trim().toUpperCase();const i=++this.generation;this.cancelRetry();this.configuredKey=t||null;if(this.state.licenseKey!==this.configuredKey)this.lock();this.state.licenseKey=this.configuredKey;this.state.isValidating=!!t;this.emit({type:"validating",isPro:this.isPro()});await this.initialize();if(i!==this.generation)return false;if(!t){await this.clearLicense();return false}return this.setLicenseKey(t)}async setLicenseKey(e,t){if(!e||e.trim().length===0){this.state.error="License key is required";this.state.errorKind="verdict";return false}const i=e.trim().toUpperCase();const s=++this.generation;this.cancelRetry();if(!t?.isRetry)this.retryAttempt=0;if(this.state.licenseKey!==i)this.lock();this.state.licenseKey=i;this.state.isValidating=true;this.state.error=null;this.state.errorKind=null;this.emit({type:"validating",isPro:this.isPro()});if(ae(i))return this.admitToken(i,s);if(!this.cachedLicense){const a=await _(this.loadCachedLicense(),null);if(s!==this.generation)return false;if(a?.licenseKey===i){this.cachedLicense=a;if(p(a)&&this.isCacheValid(a)){this.applyTier(m(a));this.state.expiresAt=a.expiresAt?new Date(a.expiresAt):null;this.setVerifiedAt(a.cachedAt);this.emit({type:"validating",isPro:this.isPro()})}}}const r=this.cachedLicense;if(!t?.force&&r&&r.valid&&r.licenseKey===i&&r.fingerprint&&p(r)&&this.isCacheValid(r)&&this.isCacheFresh(r)){this.applyTier(m(r));this.state.licenseKey=i;this.state.isValidating=false;this.state.error=null;this.state.errorKind=null;this.state.expiresAt=r.expiresAt?new Date(r.expiresAt):null;this.setVerifiedAt(r.cachedAt);this.emit({type:"validated",isPro:this.state.isPro});return true}const c=await _(this.loadHold(),null);if(s!==this.generation)return false;const g=(c?.backoffUntil??0)-h();if(g>0){return this.standDown(i,s,"License server is rate limited; retrying later.",g)}if(!t?.force&&c?.key===i&&c.verdictAt!==void 0&&h()-c.verdictAt>=0&&h()-c.verdictAt<J){this.lock();this.state.isValidating=false;this.state.error=c.detail||"License could not be verified";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});return false}let n;try{n=await j(i)}catch(a){const l=a instanceof Error?a.message:"Validation failed";if(s!==this.generation)return false;if(ee(a)){if(ie(a)){const f=Math.min(se(a,k,q)*2**this.retryAttempt,k);this.retryAttempt+=1;await this.saveHold({...this.hold,backoffUntil:h()+f});if(s!==this.generation)return false;return this.standDown(i,s,l,f)}this.state.isValidating=false;if(this.cachedLicense&&this.cachedLicense.licenseKey===i&&p(this.cachedLicense)&&this.isCacheValid(this.cachedLicense)){this.applyTier(m(this.cachedLicense));this.state.error=null;this.state.errorKind=null;this.state.expiresAt=this.cachedLicense.expiresAt?new Date(this.cachedLicense.expiresAt):null;this.setVerifiedAt(this.cachedLicense.cachedAt);if(!this.isPro())this.scheduleRetry(i);this.emit({type:"validated",isPro:this.state.isPro});return true}this.state.error=l;this.state.errorKind="transport";this.scheduleRetry(i);this.emit({type:"error",isPro:this.state.isPro,error:l});return false}this.state.isValidating=false;this.state.error=l;this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:l});return false}try{if(s!==this.generation)return false;const a=$(n);const l=n.data?.relationships?.product?.data?.id;if((!l||l===H.productId)&&a.code==="EXPIRED"&&(he(n.data)||this.cachedLicense?.licenseKey===i&&p(this.cachedLicense)&&this.isCacheValid(this.cachedLicense))){const I=h();const x=await this.saveCache({licenseKey:i,licenseId:n.data?.id??"",valid:true,isPro:false,tier:"free",expiresAt:null,cachedAt:I,lastValidatedAt:I,fingerprint:this.cachedLicense?.licenseKey===i?this.cachedLicense.fingerprint:void 0},s);if(s!==this.generation||!x)return false;this.cachedLicense=x;this.applyTier("free");this.state.isValidating=false;this.state.expiresAt=null;this.setVerifiedAt(I);this.emit({type:"validated",isPro:false});return true}if(Z(a.code)||!te(n)){this.lock();this.state.isValidating=false;this.state.error=a.detail||"License could not be verified";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});await this.clearCachedLicense();await this.saveHold({key:i,code:a.code,detail:this.state.error,verdictAt:h()});return false}if(!n.data){this.lock();this.state.isValidating=false;this.state.error=a.detail||"License not found";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});await this.clearCachedLicense();return false}const f=ce(n.data);const A=n.data.id;const v=h();const w=re(n)>=Q;const K=G();const z=K&&!w;const U=f==="free"&&(w||!K);let y=this.cachedLicense?.fingerprint;let E=this.cachedLicense?.deviceName;let D=false;if(!y){y=await _(this.getOrCreateDeviceFingerprint(),P());if(s!==this.generation)return false;E=V();D=z}let T=false;if(D){if(this.deviceRegistrationCallback){this.pendingRegistration={licenseId:A,licenseKey:i,fingerprint:y};this.deviceRegistrationCallback({fingerprint:y,defaultName:E});T=true}else{this.registerDeviceAsync(A,i,y,E)}}const L={licenseKey:i,licenseId:A,valid:true,isPro:f==="pro",tier:f,expiresAt:n.data.attributes.expiry??null,cachedAt:v,lastValidatedAt:v,fingerprint:T?void 0:y,deviceName:T?void 0:E,quiet:U||void 0};const S=await this.saveCache(L,s);if(s!==this.generation||!S)return false;this.cachedLicense=S;this.applyTier(f);this.state.isValidating=false;this.state.expiresAt=L.expiresAt?new Date(L.expiresAt):null;this.setVerifiedAt(v);if(this.hold)await this.saveHold(null);if(s!==this.generation)return false;this.retryAttempt=0;this.emit({type:"validated",isPro:this.state.isPro});return true}catch(a){const l=a instanceof Error?a.message:"Validation failed";if(s!==this.generation)return false;this.state.isValidating=false;this.state.error=l;this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:l});return false}}scheduleRetry(e){this.cancelRetry();const t=X[this.retryAttempt];if(t===void 0)return;this.retryAttempt+=1;const i=this.generation;this.retryTimer=setTimeout(()=>{this.retryTimer=null;if(i!==this.generation)return;if(this.state.isValidating)return;void this.setLicenseKey(e,{force:true,isRetry:true})},t);if(typeof __DEV__!=="undefined"&&__DEV__){global.__LICENSE_MANAGER_RETRY_TIMER__=this.retryTimer}}async admitToken(e,t){const i=ne(e);if(t!==this.generation)return false;if(!i){this.lock();this.state.isValidating=false;this.state.error="This key is not valid. Check that it was copied completely.";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});await this.clearCachedLicense();return false}const s=h();const r=this.cachedLicense?.fingerprint??await _(this.getOrCreateDeviceFingerprint(),P());if(t!==this.generation)return false;const c=await this.saveCache({licenseKey:e,licenseId:`token:${i.accountHash}`,valid:true,isPro:false,tier:"free",expiresAt:null,cachedAt:s,lastValidatedAt:s,fingerprint:r,deviceName:this.cachedLicense?.deviceName??V(),quiet:true},t);if(t!==this.generation||!c)return false;this.cachedLicense=c;this.applyTier("free");this.state.isValidating=false;this.state.expiresAt=null;this.setVerifiedAt(s);this.retryAttempt=0;this.emit({type:"validated",isPro:false});return true}standDown(e,t,i,s){if(t!==this.generation)return false;this.state.isValidating=false;const r=this.cachedLicense;if(r&&r.licenseKey===e&&p(r)&&this.isCacheValid(r)){this.applyTier(m(r));this.state.error=null;this.state.errorKind=null;this.state.expiresAt=r.expiresAt?new Date(r.expiresAt):null;this.setVerifiedAt(r.cachedAt);if(!this.isPro())this.scheduleRetryIn(e,s);this.emit({type:"validated",isPro:this.state.isPro});return true}this.state.error=i;this.state.errorKind="transport";this.scheduleRetryIn(e,s);this.emit({type:"error",isPro:this.state.isPro,error:i});return false}scheduleRetryIn(e,t){this.cancelRetry();const i=this.generation;this.retryTimer=setTimeout(()=>{this.retryTimer=null;if(i!==this.generation)return;if(this.state.isValidating)return;void this.setLicenseKey(e,{force:true,isRetry:true})},Math.max(1,Math.min(t,2147483647)));if(typeof __DEV__!=="undefined"&&__DEV__)o.__LICENSE_MANAGER_RETRY_TIMER__=this.retryTimer}cancelRetry(){if(this.retryTimer){clearTimeout(this.retryTimer);this.retryTimer=null}}async clearLicense(){this.generation+=1;this.cancelRetry();this.retryAttempt=0;this.configuredKey=null;this.state.licenseKey=null;this.lock();this.state.expiresAt=null;this.state.error=null;this.state.errorKind=null;this.cachedLicense=null;this.pendingRegistration=null;this.state.isValidating=false;this.emit({type:"deactivated",isPro:false});await this.clearCachedLicense();if(this.hold?.verdictAt!==void 0){await this.saveHold(this.hold.backoffUntil?{backoffUntil:this.hold.backoffUntil}:null)}}applyTier(e){this.state.tier=e;this.state.tierSource="key";this.state.isPro=e==="pro"}lock(){this.state.tier="free";this.state.tierSource="none";this.state.isPro=false;this.verifiedAt=null;if(this.expiryTimer)clearTimeout(this.expiryTimer);this.expiryTimer=null}getTier(){if(!this.hasAccountAccess())return"free";if(this.state.expiresAt&&h()>=this.state.expiresAt.getTime())return"free";return this.state.tier}isPro(){return this.getTier()==="pro"}hasEntitlement(e){return this.isPro()}getState(){const e=this.getAccountAccess();const t=this.getTier();return{...this.state,tier:t,isPro:t==="pro",access:e}}getAccountAccess(){return oe({initialized:this.state.isInitialized,validating:this.state.isValidating,key:this.state.licenseKey,tierSource:this.state.tierSource,verifiedAt:this.verifiedAt})}hasAccountAccess(){return this.getAccountAccess().status==="admitted"}setVerifiedAt(e){this.verifiedAt=e;if(this.expiryTimer)clearTimeout(this.expiryTimer);const t=e+M;const i=this.state.expiresAt?.getTime();const s=i&&i>h()?Math.min(t,i):t;const r=s-h();this.expiryTimer=setTimeout(()=>{this.expiryTimer=null;if(this.verifiedAt!==e)return;this.emit({type:"validated",isPro:this.isPro()});if(h()<t)this.setVerifiedAt(e)},Math.max(1,Math.min(r,2147483647)));if(typeof __DEV__!=="undefined"&&__DEV__)o.__LICENSE_MANAGER_EXPIRY_TIMER__=this.expiryTimer}subscribe(e){this.listeners.add(e);return()=>this.listeners.delete(e)}onDeviceRegistrationNeeded(e){this.deviceRegistrationCallback=e;return()=>{this.deviceRegistrationCallback=null}}async completeDeviceRegistration(e){if(!this.pendingRegistration){console.warn("[Buoy] No pending device registration");return}const{licenseId:t,licenseKey:i,fingerprint:s}=this.pendingRegistration;const r=this.generation;const c=e.trim()||V();const g=O();try{await F(t,i,s,c,g)}catch(n){const a=n instanceof Error?n.message:String(n);if(a==="FINGERPRINT_TAKEN"||a==="MACHINE_LIMIT_EXCEEDED"){}else{console.warn("[Buoy] Device registration failed:",a);throw n}}if(r!==this.generation)return;if(this.cachedLicense?.licenseKey===i){const n=await this.saveCache({...this.cachedLicense,fingerprint:s,deviceName:c},r);if(r!==this.generation)return;if(n)this.cachedLicense=n}this.pendingRegistration=null}emit(e){const t=[...this.listeners];t.forEach(i=>{try{i(e)}catch(s){console.warn("[React Buoy] License listener error:",s)}})}isCacheValid(e){const t=h();const i=t-e.cachedAt;if(!e.valid||!Number.isFinite(e.cachedAt)||i<0||i>=M){return false}return true}isCacheFresh(e){const t=this.isQuiet(e)?W:B;return h()-(e.lastValidatedAt??0)<t}isQuiet(e){if(e.quiet!==void 0)return e.quiet;return m(e)==="free"&&!G()}async loadHold(){if(this.hold!==void 0)return this.hold;try{const e=await u();const t=await e.getItem(C);const i=t?JSON.parse(t):null;this.hold=i&&typeof i==="object"?i:null}catch{this.hold=null}return this.hold}async saveHold(e){this.hold=e;try{const t=await u();if(e)await t.setItem(C,JSON.stringify(e));else await t.removeItem(C)}catch{}}async persistCache(e){const t=b(e);const i=await u();await i.setItem(R,JSON.stringify(t));return t}saveCache(e,t){const i=this.persistence.catch(()=>{}).then(async()=>{if(t!==this.generation)return null;const s=await this.persistCache(e);return t===this.generation?s:null});this.persistence=i;return _(i,b(e))}async loadCachedLicense(){try{await this.persistence.catch(()=>{});const e=await u();const t=await e.getItem(R);if(!t)return null;const i=JSON.parse(t);return i}catch(e){console.warn("[Buoy] Error loading cached license:",e);return null}}getOrCreateDeviceFingerprint(){if(!this.fingerprintPromise){this.fingerprintPromise=(async()=>{const e=await u();const t=await e.getItem(N);if(t)return t;const i=this.cachedLicense?.fingerprint||P();await e.setItem(N,i);return i})()}return this.fingerprintPromise}async clearCachedLicense(){this.cachedLicense=null;const e=this.persistence.catch(()=>{}).then(async()=>{const t=await u();await t.removeItem(R)});this.persistence=e;await _(e.catch(()=>{}),void 0)}registerDeviceAsync(e,t,i,s){const r=O();F(e,t,i,s,r).catch(c=>{if(c.message!=="FINGERPRINT_TAKEN"&&c.message!=="MACHINE_LIMIT_EXCEEDED"){console.warn("[Buoy] Device registration failed (non-blocking):",c.message)}})}validateInBackground(e){void this.setLicenseKey(e,{force:true,isRetry:true})}refreshAccess(){this.emit({type:"validated",isPro:this.isPro()})}startRevalidationTimer(){if(!this.removeForegroundListener){this.removeForegroundListener=le(()=>this.refreshAccess());if(typeof __DEV__!=="undefined"&&__DEV__)o.__LICENSE_MANAGER_FOREGROUND_OFF__=this.removeForegroundListener}if(this.revalidationTimer){clearInterval(this.revalidationTimer)}this.revalidationTimer=setInterval(()=>{if(!this.state.licenseKey||this.state.isValidating)return;const e=this.cachedLicense;if(e&&e.licenseKey===this.state.licenseKey&&this.isCacheFresh(e))return;this.validateInBackground(this.state.licenseKey)},Y);if(typeof __DEV__!=="undefined"&&__DEV__){global.__LICENSE_MANAGER_TIMER__=this.revalidationTimer}}stopRevalidationTimer(){this.removeForegroundListener?.();this.removeForegroundListener=null;if(this.expiryTimer)clearTimeout(this.expiryTimer);this.expiryTimer=null;if(this.revalidationTimer){clearInterval(this.revalidationTimer);this.revalidationTimer=null}this.cancelRetry()}async forceReregister(){if(this.cachedLicense){this.cachedLicense.fingerprint=void 0;this.cachedLicense.deviceName=void 0}this.fingerprintPromise=null;await this.clearCachedLicense();try{const e=await u();await e.removeItem(N)}catch{}}}export const LicenseManager=new de;const o=globalThis;if(typeof __DEV__!=="undefined"&&__DEV__){o.__LICENSE_MANAGER_FOREGROUND_OFF__?.();o.__LICENSE_MANAGER_FOREGROUND_OFF__=void 0;if(o.__LICENSE_MANAGER_EXPIRY_TIMER__)clearTimeout(o.__LICENSE_MANAGER_EXPIRY_TIMER__);if(o.__LICENSE_MANAGER_TIMER__){clearInterval(o.__LICENSE_MANAGER_TIMER__)}if(o.__LICENSE_MANAGER_RETRY_TIMER__){clearTimeout(o.__LICENSE_MANAGER_RETRY_TIMER__);o.__LICENSE_MANAGER_RETRY_TIMER__=void 0}}
16
+ */import{getLicenseStorage as y}from"./storage";import{KEYGEN_CONFIG as B,LICENSE_STORAGE_KEY as N,LICENSE_CACHE_DURATION as b,LICENSE_REVALIDATION_INTERVAL as X,LICENSE_LAUNCH_VALIDATION_TTL as q,LICENSE_TRANSIENT_RETRY_DELAYS as J,LICENSE_RATE_LIMIT_DEFAULT_WAIT as Q,LICENSE_QUOTA_COOLDOWN as F,LICENSE_VERDICT_CACHE_DURATION as W,LICENSE_FLEET_MACHINE_THRESHOLD as j,LICENSE_QUIET_VALIDATION_TTL as $,LICENSE_HOLD_STORAGE_KEY as C,DEVICE_FINGERPRINT_STORAGE_KEY as K}from"./config.js";import{validateLicense as Z,activateMachine as O,parseValidationResult as ee,isFatalLicenseError as te,isTransientLicenseError as ie,isAcceptedValidation as se,isRateLimited as re,backoffAfter as ae,machineCount as ne}from"./api.js";import{generateUUID as P,getDeviceMetadata as G,getDefaultDeviceName as V,isDevBundle as w}from"./fingerprint";import{signCache as U,verifyCacheSignature as p}from"./cacheSignature.js";import{isBuoyToken as ce,verifyFreeToken as he}from"./freeToken.js";import{resolveTier as oe,isRecognizedAccount as le}from"./tier.js";import{resolveAccountAccess as de}from"./accountAccess.js";import{subscribeForeground as fe}from"./foreground";import{realNow as c}from"./realNow.js";import{SessionManager as g}from"./sessionManager.js";import{exchangeServiceKey as ue,isServiceKey as ye,normalizeLicenseKey as z}from"./serviceKey.js";import{checkDevToken as me,isDevToken as pe,DEV_TOKEN_IN_RELEASE as _e}from"./devToken.js";async function d(f,e){let t;try{return await Promise.race([f,new Promise(i=>{t=setTimeout(()=>i(e),15e3)})])}finally{if(t)clearTimeout(t)}}function _(f){if(f.tier==="pro"||f.tier==="free")return f.tier;return f.isPro?"pro":"free"}class ge{state={isInitialized:false,isValidating:false,isPro:false,tier:"free",tierSource:"none",licenseKey:null,error:null,errorKind:null,expiresAt:null};listeners=new Set;revalidationTimer=null;cachedLicense=null;fingerprintPromise=null;initPromise=null;generation=0;persistence=Promise.resolve();verifiedAt=null;expiryTimer=null;removeForegroundListener=null;sessionUnsubscribe=null;retryTimer=null;retryAttempt=0;deviceRegistrationCallback=null;pendingRegistration=null;async initialize(){if(this.initPromise)return this.initPromise;if(this.state.isInitialized)return;this.initPromise=this._doInitialize();return this.initPromise}async _doInitialize(){if(this.state.isInitialized)return;const e=this.generation;if(!this.sessionUnsubscribe){this.sessionUnsubscribe=g.subscribe(()=>this.emit({type:"validated",isPro:this.isPro()}))}await d(g.load().catch(()=>void 0),void 0);try{const t=await d(this.loadCachedLicense(),null);if(e!==this.generation){this.state.isInitialized=true;this.emit({type:"initialized",isPro:this.state.isPro});this.startRevalidationTimer();return}if(t&&(this.configuredKey===void 0||t.licenseKey===this.configuredKey)){const i=p(t);this.cachedLicense=t;this.state.licenseKey=t.licenseKey;if(i&&this.isCacheValid(t))this.applyTier(_(t));else this.lock();this.state.expiresAt=t.expiresAt?new Date(t.expiresAt):null;if(i&&this.isCacheValid(t))this.setVerifiedAt(t.cachedAt);if(this.configuredKey===void 0&&t.licenseKey&&!(i&&this.isCacheValid(t)&&this.isCacheFresh(t))){this.validateInBackground(t.licenseKey)}}this.state.isInitialized=true;this.emit({type:"initialized",isPro:this.state.isPro});this.startRevalidationTimer()}catch(t){console.warn("[React Buoy] License initialization failed:",t);this.state.isInitialized=true;this.emit({type:"initialized",isPro:false})}}async configure(e){if(e===void 0){await this.initialize();return this.hasAccountAccess()}const t=z(e);const i=++this.generation;this.cancelRetry();this.configuredKey=t||null;if(this.state.licenseKey!==this.configuredKey)this.lock();this.state.licenseKey=this.configuredKey;this.state.isValidating=!!t;this.emit({type:"validating",isPro:this.isPro()});await this.initialize();if(i!==this.generation)return false;if(!t){await this.clearLicense();return false}return this.setLicenseKey(t)}async setLicenseKey(e,t){if(!e||e.trim().length===0){this.state.error="License key is required";this.state.errorKind="verdict";return false}const i=z(e);const s=++this.generation;this.cancelRetry();if(!t?.isRetry)this.retryAttempt=0;if(this.state.licenseKey!==i)this.lock();this.state.licenseKey=i;this.state.isValidating=true;this.state.error=null;this.state.errorKind=null;this.emit({type:"validating",isPro:this.isPro()});if(ce(i))return this.admitToken(i,s);if(ye(i))return this.admitServiceKey(i,s);if(pe(i))return this.admitDevToken(i);if(!this.cachedLicense){const a=await d(this.loadCachedLicense(),null);if(s!==this.generation)return false;if(a?.licenseKey===i){this.cachedLicense=a;if(p(a)&&this.isCacheValid(a)){this.applyTier(_(a));this.state.expiresAt=a.expiresAt?new Date(a.expiresAt):null;this.setVerifiedAt(a.cachedAt);this.emit({type:"validating",isPro:this.isPro()})}}}const r=this.cachedLicense;if(!t?.force&&r&&r.valid&&r.licenseKey===i&&r.fingerprint&&p(r)&&this.isCacheValid(r)&&this.isCacheFresh(r)){this.applyTier(_(r));this.state.licenseKey=i;this.state.isValidating=false;this.state.error=null;this.state.errorKind=null;this.state.expiresAt=r.expiresAt?new Date(r.expiresAt):null;this.setVerifiedAt(r.cachedAt);this.emit({type:"validated",isPro:this.state.isPro});return true}const h=await d(this.loadHold(),null);if(s!==this.generation)return false;const A=(h?.backoffUntil??0)-c();if(A>0){return this.standDown(i,s,"License server is rate limited; retrying later.",A)}if(!t?.force&&h?.key===i&&h.verdictAt!==void 0&&c()-h.verdictAt>=0&&c()-h.verdictAt<W){this.lock();this.state.isValidating=false;this.state.error=h.detail||"License could not be verified";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});return false}let n;try{n=await Z(i)}catch(a){const l=a instanceof Error?a.message:"Validation failed";if(s!==this.generation)return false;if(ie(a)){if(re(a)){const u=Math.min(ae(a,F,Q)*2**this.retryAttempt,F);this.retryAttempt+=1;await this.saveHold({...this.hold,backoffUntil:c()+u});if(s!==this.generation)return false;return this.standDown(i,s,l,u)}this.state.isValidating=false;if(this.cachedLicense&&this.cachedLicense.licenseKey===i&&p(this.cachedLicense)&&this.isCacheValid(this.cachedLicense)){this.applyTier(_(this.cachedLicense));this.state.error=null;this.state.errorKind=null;this.state.expiresAt=this.cachedLicense.expiresAt?new Date(this.cachedLicense.expiresAt):null;this.setVerifiedAt(this.cachedLicense.cachedAt);if(this.keyTier()!=="pro")this.scheduleRetry(i);this.emit({type:"validated",isPro:this.state.isPro});return true}this.state.error=l;this.state.errorKind="transport";this.scheduleRetry(i);this.emit({type:"error",isPro:this.state.isPro,error:l});return false}this.state.isValidating=false;this.state.error=l;this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:l});return false}try{if(s!==this.generation)return false;const a=ee(n);const l=n.data?.relationships?.product?.data?.id;if((!l||l===B.productId)&&a.code==="EXPIRED"&&(le(n.data)||this.cachedLicense?.licenseKey===i&&p(this.cachedLicense)&&this.isCacheValid(this.cachedLicense))){const R=c();const M=await this.saveCache({licenseKey:i,licenseId:n.data?.id??"",valid:true,isPro:false,tier:"free",expiresAt:null,cachedAt:R,lastValidatedAt:R,fingerprint:this.cachedLicense?.licenseKey===i?this.cachedLicense.fingerprint:void 0},s);if(s!==this.generation||!M)return false;this.cachedLicense=M;this.applyTier("free");this.state.isValidating=false;this.state.expiresAt=null;this.setVerifiedAt(R);this.emit({type:"validated",isPro:false});return true}if(te(a.code)||!se(n)){this.lock();this.state.isValidating=false;this.state.error=a.detail||"License could not be verified";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});await this.clearCachedLicense();await this.saveHold({key:i,code:a.code,detail:this.state.error,verdictAt:c()});return false}if(!n.data){this.lock();this.state.isValidating=false;this.state.error=a.detail||"License not found";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});await this.clearCachedLicense();return false}const u=oe(n.data);const v=n.data.id;const T=c();const D=ne(n)>=j;const S=w();const H=S&&!D;const Y=u==="free"&&(D||!S);let m=this.cachedLicense?.fingerprint;let E=this.cachedLicense?.deviceName;let k=false;if(!m){m=await d(this.getOrCreateDeviceFingerprint(),P());if(s!==this.generation)return false;E=V();k=H}let L=false;if(k){if(this.deviceRegistrationCallback){this.pendingRegistration={licenseId:v,licenseKey:i,fingerprint:m};this.deviceRegistrationCallback({fingerprint:m,defaultName:E});L=true}else{this.registerDeviceAsync(v,i,m,E)}}const I={licenseKey:i,licenseId:v,valid:true,isPro:u==="pro",tier:u,expiresAt:n.data.attributes.expiry??null,cachedAt:T,lastValidatedAt:T,fingerprint:L?void 0:m,deviceName:L?void 0:E,quiet:Y||void 0};const x=await this.saveCache(I,s);if(s!==this.generation||!x)return false;this.cachedLicense=x;this.applyTier(u);this.state.isValidating=false;this.state.expiresAt=I.expiresAt?new Date(I.expiresAt):null;this.setVerifiedAt(T);if(this.hold)await this.saveHold(null);if(s!==this.generation)return false;this.retryAttempt=0;this.emit({type:"validated",isPro:this.state.isPro});return true}catch(a){const l=a instanceof Error?a.message:"Validation failed";if(s!==this.generation)return false;this.state.isValidating=false;this.state.error=l;this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:l});return false}}scheduleRetry(e){this.cancelRetry();const t=J[this.retryAttempt];if(t===void 0)return;this.retryAttempt+=1;const i=this.generation;this.retryTimer=setTimeout(()=>{this.retryTimer=null;if(i!==this.generation)return;if(this.state.isValidating)return;void this.setLicenseKey(e,{force:true,isRetry:true})},t);if(typeof __DEV__!=="undefined"&&__DEV__){global.__LICENSE_MANAGER_RETRY_TIMER__=this.retryTimer}}async admitServiceKey(e,t){const i=await ue(e,{origin:g.origin});if(t!==this.generation)return false;if(!i.ok){this.lock();this.state.isValidating=false;this.state.error=i.detail;this.state.errorKind=i.reason==="network"?"transport":"verdict";this.emit({type:"error",isPro:false,error:i.detail});if(i.reason==="network")this.scheduleRetry(e);return false}const s=i.claims.exp*1e3;this.applyTier(i.claims.tier==="free"?"free":"pro");this.state.isValidating=false;this.state.expiresAt=new Date(s);this.setVerifiedAt(c());this.retryAttempt=0;this.scheduleRetryIn(e,Math.max(6e4,s-60*60*1e3-c()));this.emit({type:"validated",isPro:this.isPro()});return true}admitDevToken(e){const t=me(e);if(!t.ok||!w()){const s=t.ok?_e:t.message;this.lock();this.state.isValidating=false;this.state.error=s;this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:s});return false}const i=c();this.applyTier(t.claims.tier==="free"?"free":"pro");this.state.isValidating=false;this.state.expiresAt=new Date(t.claims.exp*1e3);this.setVerifiedAt(Math.min(i,t.claims.iat*1e3));this.retryAttempt=0;this.emit({type:"validated",isPro:this.isPro()});return true}async admitToken(e,t){const i=he(e);if(t!==this.generation)return false;if(!i){this.lock();this.state.isValidating=false;this.state.error="This key is not valid. Check that it was copied completely.";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});await this.clearCachedLicense();return false}const s=c();const r=this.cachedLicense?.fingerprint??await d(this.getOrCreateDeviceFingerprint(),P());if(t!==this.generation)return false;const h=await this.saveCache({licenseKey:e,licenseId:`token:${i.accountHash}`,valid:true,isPro:false,tier:"free",expiresAt:null,cachedAt:s,lastValidatedAt:s,fingerprint:r,deviceName:this.cachedLicense?.deviceName??V(),quiet:true},t);if(t!==this.generation||!h)return false;this.cachedLicense=h;this.applyTier("free");this.state.isValidating=false;this.state.expiresAt=null;this.setVerifiedAt(s);this.retryAttempt=0;this.emit({type:"validated",isPro:false});return true}standDown(e,t,i,s){if(t!==this.generation)return false;this.state.isValidating=false;const r=this.cachedLicense;if(r&&r.licenseKey===e&&p(r)&&this.isCacheValid(r)){this.applyTier(_(r));this.state.error=null;this.state.errorKind=null;this.state.expiresAt=r.expiresAt?new Date(r.expiresAt):null;this.setVerifiedAt(r.cachedAt);if(this.keyTier()!=="pro")this.scheduleRetryIn(e,s);this.emit({type:"validated",isPro:this.state.isPro});return true}this.state.error=i;this.state.errorKind="transport";this.scheduleRetryIn(e,s);this.emit({type:"error",isPro:this.state.isPro,error:i});return false}scheduleRetryIn(e,t){this.cancelRetry();const i=this.generation;this.retryTimer=setTimeout(()=>{this.retryTimer=null;if(i!==this.generation)return;if(this.state.isValidating)return;void this.setLicenseKey(e,{force:true,isRetry:true})},Math.max(1,Math.min(t,2147483647)));if(typeof __DEV__!=="undefined"&&__DEV__)o.__LICENSE_MANAGER_RETRY_TIMER__=this.retryTimer}cancelRetry(){if(this.retryTimer){clearTimeout(this.retryTimer);this.retryTimer=null}}async clearLicense(){this.generation+=1;this.cancelRetry();this.retryAttempt=0;this.configuredKey=null;this.state.licenseKey=null;this.lock();this.state.expiresAt=null;this.state.error=null;this.state.errorKind=null;this.cachedLicense=null;this.pendingRegistration=null;this.state.isValidating=false;this.emit({type:"deactivated",isPro:false});await this.clearCachedLicense();if(this.hold?.verdictAt!==void 0){await this.saveHold(this.hold.backoffUntil?{backoffUntil:this.hold.backoffUntil}:null)}}applyTier(e){this.state.tier=e;this.state.tierSource="key";this.state.isPro=e==="pro"}lock(){this.state.tier="free";this.state.tierSource="none";this.state.isPro=false;this.verifiedAt=null;if(this.expiryTimer)clearTimeout(this.expiryTimer);this.expiryTimer=null}getTier(){return this.credential().tier}credential(){const e=this.keyTier();const t=this.sessionTier();if(t!==null&&(!this.hasKeyAccess()||t==="pro"&&e!=="pro")){return{source:"session",tier:t}}return{source:this.state.tierSource,tier:e}}keyTier(){if(!this.hasKeyAccess())return"free";if(this.state.expiresAt&&c()>=this.state.expiresAt.getTime())return"free";return this.state.tier}sessionTier(){const e=g.getStatus();if(e.state!=="active")return null;return e.claims.tier==="free"?"free":"pro"}isPro(){return this.getTier()==="pro"}hasEntitlement(e){return this.isPro()}getState(){const{source:e,tier:t}=this.credential();return{...this.state,tier:t,tierSource:e,isPro:t==="pro",access:this.getAccountAccess()}}getAccountAccess(){const e=this.getKeyAccess();if(e.status==="admitted")return e;const t=g.getStatus();if(t.state==="active")return{status:"admitted",reason:null,validUntil:t.validUntil};return e}getKeyAccess(){return de({initialized:this.state.isInitialized,validating:this.state.isValidating,key:this.state.licenseKey,tierSource:this.state.tierSource,verifiedAt:this.verifiedAt})}hasAccountAccess(){return this.getAccountAccess().status==="admitted"}hasKeyAccess(){return this.getKeyAccess().status==="admitted"}setVerifiedAt(e){this.verifiedAt=e;if(this.expiryTimer)clearTimeout(this.expiryTimer);const t=e+b;const i=this.state.expiresAt?.getTime();const s=i&&i>c()?Math.min(t,i):t;const r=s-c();this.expiryTimer=setTimeout(()=>{this.expiryTimer=null;if(this.verifiedAt!==e)return;this.emit({type:"validated",isPro:this.isPro()});if(c()<t)this.setVerifiedAt(e)},Math.max(1,Math.min(r,2147483647)));if(typeof __DEV__!=="undefined"&&__DEV__)o.__LICENSE_MANAGER_EXPIRY_TIMER__=this.expiryTimer}subscribe(e){this.listeners.add(e);return()=>this.listeners.delete(e)}onDeviceRegistrationNeeded(e){this.deviceRegistrationCallback=e;return()=>{this.deviceRegistrationCallback=null}}async completeDeviceRegistration(e){if(!this.pendingRegistration){console.warn("[Buoy] No pending device registration");return}const{licenseId:t,licenseKey:i,fingerprint:s}=this.pendingRegistration;const r=this.generation;const h=e.trim()||V();const A=G();try{await O(t,i,s,h,A)}catch(n){const a=n instanceof Error?n.message:String(n);if(a==="FINGERPRINT_TAKEN"||a==="MACHINE_LIMIT_EXCEEDED"){}else{console.warn("[Buoy] Device registration failed:",a);throw n}}if(r!==this.generation)return;if(this.cachedLicense?.licenseKey===i){const n=await this.saveCache({...this.cachedLicense,fingerprint:s,deviceName:h},r);if(r!==this.generation)return;if(n)this.cachedLicense=n}this.pendingRegistration=null}emit(e){const t=[...this.listeners];t.forEach(i=>{try{i(e)}catch(s){console.warn("[React Buoy] License listener error:",s)}})}isCacheValid(e){const t=c();const i=t-e.cachedAt;if(!e.valid||!Number.isFinite(e.cachedAt)||i<0||i>=b){return false}return true}isCacheFresh(e){const t=this.isQuiet(e)?$:q;return c()-(e.lastValidatedAt??0)<t}isQuiet(e){if(e.quiet!==void 0)return e.quiet;return _(e)==="free"&&!w()}async loadHold(){if(this.hold!==void 0)return this.hold;try{const e=await y();const t=await e.getItem(C);const i=t?JSON.parse(t):null;this.hold=i&&typeof i==="object"?i:null}catch{this.hold=null}return this.hold}async saveHold(e){this.hold=e;try{const t=await y();if(e)await t.setItem(C,JSON.stringify(e));else await t.removeItem(C)}catch{}}async persistCache(e){const t=U(e);const i=await y();await i.setItem(N,JSON.stringify(t));return t}saveCache(e,t){const i=this.persistence.catch(()=>{}).then(async()=>{if(t!==this.generation)return null;const s=await this.persistCache(e);return t===this.generation?s:null});this.persistence=i;return d(i,U(e))}async loadCachedLicense(){try{await this.persistence.catch(()=>{});const e=await y();const t=await e.getItem(N);if(!t)return null;const i=JSON.parse(t);return i}catch(e){console.warn("[Buoy] Error loading cached license:",e);return null}}getOrCreateDeviceFingerprint(){if(!this.fingerprintPromise){this.fingerprintPromise=(async()=>{const e=await y();const t=await e.getItem(K);if(t)return t;const i=this.cachedLicense?.fingerprint||P();await e.setItem(K,i);return i})()}return this.fingerprintPromise}async clearCachedLicense(){this.cachedLicense=null;const e=this.persistence.catch(()=>{}).then(async()=>{const t=await y();await t.removeItem(N)});this.persistence=e;await d(e.catch(()=>{}),void 0)}registerDeviceAsync(e,t,i,s){const r=G();O(e,t,i,s,r).catch(h=>{if(h.message!=="FINGERPRINT_TAKEN"&&h.message!=="MACHINE_LIMIT_EXCEEDED"){console.warn("[Buoy] Device registration failed (non-blocking):",h.message)}})}validateInBackground(e){void this.setLicenseKey(e,{force:true,isRetry:true})}refreshAccess(){this.emit({type:"validated",isPro:this.isPro()})}startRevalidationTimer(){if(!this.removeForegroundListener){this.removeForegroundListener=fe(()=>this.refreshAccess());if(typeof __DEV__!=="undefined"&&__DEV__)o.__LICENSE_MANAGER_FOREGROUND_OFF__=this.removeForegroundListener}if(this.revalidationTimer){clearInterval(this.revalidationTimer)}this.revalidationTimer=setInterval(()=>{if(!this.state.licenseKey||this.state.isValidating)return;const e=this.cachedLicense;if(e&&e.licenseKey===this.state.licenseKey&&this.isCacheFresh(e))return;this.validateInBackground(this.state.licenseKey)},X);if(typeof __DEV__!=="undefined"&&__DEV__){global.__LICENSE_MANAGER_TIMER__=this.revalidationTimer}}stopRevalidationTimer(){this.removeForegroundListener?.();this.removeForegroundListener=null;if(this.expiryTimer)clearTimeout(this.expiryTimer);this.expiryTimer=null;if(this.revalidationTimer){clearInterval(this.revalidationTimer);this.revalidationTimer=null}this.cancelRetry()}async forceReregister(){if(this.cachedLicense){this.cachedLicense.fingerprint=void 0;this.cachedLicense.deviceName=void 0}this.fingerprintPromise=null;await this.clearCachedLicense();try{const e=await y();await e.removeItem(K)}catch{}}}export const LicenseManager=new ge;const o=globalThis;if(typeof __DEV__!=="undefined"&&__DEV__){o.__LICENSE_MANAGER_FOREGROUND_OFF__?.();o.__LICENSE_MANAGER_FOREGROUND_OFF__=void 0;if(o.__LICENSE_MANAGER_EXPIRY_TIMER__)clearTimeout(o.__LICENSE_MANAGER_EXPIRY_TIMER__);if(o.__LICENSE_MANAGER_TIMER__){clearInterval(o.__LICENSE_MANAGER_TIMER__)}if(o.__LICENSE_MANAGER_RETRY_TIMER__){clearTimeout(o.__LICENSE_MANAGER_RETRY_TIMER__);o.__LICENSE_MANAGER_RETRY_TIMER__=void 0}}
@@ -14,4 +14,4 @@
14
14
  * Pro is $9/mo, and is free every weekend for anyone holding a key —
15
15
  * including a free one (`npx buoy login`). Buy a key at
16
16
  * https://buoy.gg or use it free on Saturday and Sunday.
17
- */export const KEYGEN_CONFIG={accountId:"b0eba0e8-e904-4906-b644-38f9aab57bed",productId:"bf67cb43-eeef-40ca-b308-e6e1b22c0eaa",apiUrl:"https://buoy.gg/api/license"};export const FREE_TOKEN_PUBLIC_KEY="3b546fc717a62683f3236c70167899a271bee3ffc04df6ec1eea60a394a2f1e9";export const KEYGEN_POLICIES={free:"394e3351-1249-4f73-807a-703408604c0e",solo:"fa5d3c8f-5379-40f1-b63e-ab8a974b2f28",business:"690c2212-8e54-426f-b4b4-002ee1c0ae2b"};export const LICENSE_CACHE_DURATION=30*24*60*60*1e3;export const LICENSE_REVALIDATION_INTERVAL=24*60*60*1e3;export const LICENSE_STORAGE_KEY="buoy-gg-license";export const DEVICE_FINGERPRINT_STORAGE_KEY="buoy-gg-device-fingerprint";export const LICENSE_LAUNCH_VALIDATION_TTL=60*60*1e3;export const LICENSE_TRANSIENT_RETRY_DELAYS=[5*1e3,20*1e3,60*1e3,5*60*1e3,15*60*1e3];export const LICENSE_RATE_LIMIT_DEFAULT_WAIT=60*1e3;export const LICENSE_QUOTA_COOLDOWN=60*60*1e3;export const LICENSE_VERDICT_CACHE_DURATION=24*60*60*1e3;export const LICENSE_FLEET_MACHINE_THRESHOLD=50;export const LICENSE_QUIET_VALIDATION_TTL=LICENSE_CACHE_DURATION;export const LICENSE_HOLD_STORAGE_KEY="buoy-gg-license-hold";
17
+ */export const KEYGEN_CONFIG={accountId:"b0eba0e8-e904-4906-b644-38f9aab57bed",productId:"bf67cb43-eeef-40ca-b308-e6e1b22c0eaa",apiUrl:"https://buoy.gg/api/license"};export const FREE_TOKEN_PUBLIC_KEY="3b546fc717a62683f3236c70167899a271bee3ffc04df6ec1eea60a394a2f1e9";export const SESSION_TOKEN_PUBLIC_KEY="36abba0267f7f379d992a5b6df641daab4190bcc9e639e36f1378e3c1ac52746";export const KEYGEN_POLICIES={free:"394e3351-1249-4f73-807a-703408604c0e",solo:"fa5d3c8f-5379-40f1-b63e-ab8a974b2f28",business:"690c2212-8e54-426f-b4b4-002ee1c0ae2b"};export const LICENSE_CACHE_DURATION=30*24*60*60*1e3;export const LICENSE_REVALIDATION_INTERVAL=24*60*60*1e3;export const LICENSE_STORAGE_KEY="buoy-gg-license";export const DEVICE_FINGERPRINT_STORAGE_KEY="buoy-gg-device-fingerprint";export const LICENSE_LAUNCH_VALIDATION_TTL=60*60*1e3;export const LICENSE_TRANSIENT_RETRY_DELAYS=[5*1e3,20*1e3,60*1e3,5*60*1e3,15*60*1e3];export const LICENSE_RATE_LIMIT_DEFAULT_WAIT=60*1e3;export const LICENSE_QUOTA_COOLDOWN=60*60*1e3;export const LICENSE_VERDICT_CACHE_DURATION=24*60*60*1e3;export const LICENSE_FLEET_MACHINE_THRESHOLD=50;export const LICENSE_QUIET_VALIDATION_TTL=LICENSE_CACHE_DURATION;export const LICENSE_HOLD_STORAGE_KEY="buoy-gg-license-hold";
@@ -0,0 +1,6 @@
1
+ "use strict";/*!
2
+ * PROPRIETARY — Buoy license enforcement. NOT open source.
3
+ *
4
+ * Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
5
+ * (https://buoy.gg/terms), not an OSS license.
6
+ */import{isSessionToken as i,verifySessionToken as s}from"./sessionToken.js";import{realNow as r}from"./realNow.js";export const DEV_AUDIENCE="dev";export function isDevToken(e){return i(e)}export function checkDevToken(e,n=r()){const o=s(e,{audience:DEV_AUDIENCE,ignoreTime:true});if(!o.ok)return{ok:false,reason:"invalid",message:"This dev token is not valid. Run `npx buoy login` again."};if(n>=o.claims.exp*1e3){return{ok:false,reason:"expired",message:"Your dev token ran out. Run `npx buoy login` again."}}return{ok:true,claims:o.claims}}export const DEV_TOKEN_IN_RELEASE="This is a dev token. It only works in dev builds. A live build turns on Buoy with Sign in with Buoy.";
@@ -1 +1 @@
1
- "use strict";export{validateLicense,isAcceptedValidation,isTransientLicenseError,LicenseTransportError}from"./api.js";export{resolveTier,isRecognizedAccount}from"./tier.js";export{isBuoyToken,verifyFreeToken,mintFreeToken,accountHashFor,publicKeyFor,__setFreeTokenPublicKeyForTests}from"./freeToken.js";export{resolveAccountAccess}from"./accountAccess.js";export{signCache,verifyCacheSignature}from"./cacheSignature.js";export{LICENSE_CACHE_DURATION,LICENSE_REVALIDATION_INTERVAL,LICENSE_LAUNCH_VALIDATION_TTL,LICENSE_TRANSIENT_RETRY_DELAYS,KEYGEN_CONFIG}from"./config.js";
1
+ "use strict";export{validateLicense,isAcceptedValidation,isTransientLicenseError,LicenseTransportError}from"./api.js";export{resolveTier,isRecognizedAccount}from"./tier.js";export{isBuoyToken,verifyFreeToken,mintFreeToken,accountHashFor,publicKeyFor,__setFreeTokenPublicKeyForTests}from"./freeToken.js";export{resolveAccountAccess}from"./accountAccess.js";export{signCache,verifyCacheSignature}from"./cacheSignature.js";export{LICENSE_CACHE_DURATION,LICENSE_REVALIDATION_INTERVAL,LICENSE_LAUNCH_VALIDATION_TTL,LICENSE_TRANSIENT_RETRY_DELAYS,KEYGEN_CONFIG}from"./config.js";export{createNodeSession,fileSessionStorage,fileLock,receiveCodeOnLoopback,defaultSessionFile,DESKTOP_AUDIENCE,CLI_AUDIENCE}from"./nodeSession.js";export{SessionError,SessionManagerImpl,SESSION_OFFLINE_GRACE_MS}from"./sessionManager.js";export{verifySessionToken,mintSessionToken,__setSessionTokenPublicKeyForTests}from"./sessionToken.js";export{exchangeServiceKey,isServiceKey,normalizeLicenseKey,sameLicenseKey,SERVICE_KEY_PREFIX,SERVICE_AUDIENCE}from"./serviceKey.js";export{checkDevToken,isDevToken,DEV_AUDIENCE}from"./devToken.js";
@@ -14,4 +14,4 @@
14
14
  * Pro is $9/mo, and is free every weekend for anyone holding a key —
15
15
  * including a free one (`npx buoy login`). Buy a key at
16
16
  * https://buoy.gg or use it free on Saturday and Sunday.
17
- */import{useState as d,useEffect as l,useCallback as o}from"react";import{LicenseManager as i}from"./LicenseManager.js";import{useWeekendFreePro as a,weekendPassAppliesTo as u}from"./weekendPro.js";export function useLicense(){const[n,e]=d(i.getState());l(()=>{const t=i.subscribe(r=>{e(i.getState())});i.initialize().then(()=>{e(i.getState())});return t},[]);const c=o(async t=>{const r=await i.setLicenseKey(t,{force:true});e(i.getState());return r},[]);const s=o(async()=>{await i.clearLicense();e(i.getState())},[]);return{...n,setLicenseKey:c,clearLicense:s}}export function useAccountAccess(){return useLicense().access}export function useTier(){const{tier:n,isInitialized:e}=useLicense();return e?n:"free"}export function useFeatureAccess(n){const{isPro:e,isInitialized:c,isValidating:s}=useLicense();const t=e;const r=!c||s;return{hasAccess:t,isPro:e,isLoading:r}}export function useIsPro(){const{isPro:n,isInitialized:e,access:c}=useLicense();const s=u(c.status==="admitted",a());return e&&n||s}export function useProAccess(){const{isPro:n,isInitialized:e,access:c}=useLicense();const s=e&&n;const t=u(c.status==="admitted",a())&&!s;const r=s?"licensed":t?"weekend":null;return{isPro:s||t,isLicensed:s,isWeekendFree:t,reason:r}}
17
+ */import{useState as u,useEffect as d,useCallback as a}from"react";import{LicenseManager as r}from"./LicenseManager.js";import{useWeekendFreePro as f,weekendPassAppliesTo as l}from"./weekendPro.js";import{SessionManager as o}from"./sessionManager.js";export function useLicense(){const[n,e]=u(r.getState());d(()=>{const s=r.subscribe(c=>{e(r.getState())});r.initialize().then(()=>{e(r.getState())});return s},[]);const i=a(async s=>{const c=await r.setLicenseKey(s,{force:true});e(r.getState());return c},[]);const t=a(async()=>{await r.clearLicense();e(r.getState())},[]);return{...n,setLicenseKey:i,clearLicense:t}}export function useAccountAccess(){return useLicense().access}export function useTier(){const{tier:n,isInitialized:e}=useLicense();return e?n:"free"}export function useFeatureAccess(n){const{isPro:e,isInitialized:i,isValidating:t}=useLicense();const s=e;const c=!i||t;return{hasAccess:s,isPro:e,isLoading:c}}export function useIsPro(){const{isPro:n,isInitialized:e,access:i}=useLicense();const t=l(i.status==="admitted",f());return e&&n||t}export function useProAccess(){const{isPro:n,isInitialized:e,access:i}=useLicense();const t=e&&n;const s=l(i.status==="admitted",f())&&!t;const c=t?"licensed":s?"weekend":null;return{isPro:t||s,isLicensed:t,isWeekendFree:s,reason:c}}export function useBuoySession(){const[n,e]=u(()=>o.getStatus());d(()=>{const s=()=>e(o.getStatus());const c=o.subscribe(s);o.load().then(s,s);return c},[]);const i=a(()=>o.signIn(),[]);const t=a(()=>o.signOut(),[]);return{status:n,signIn:i,signOut:t}}
@@ -15,4 +15,4 @@
15
15
  * Pro is $9/mo, and is free every weekend for anyone holding a key —
16
16
  * including a free one (`npx buoy login`). Buy a key at
17
17
  * https://buoy.gg or use it free on Saturday and Sunday.
18
- */export{LicenseManager}from"./LicenseManager.js";export{DeviceRegistrationModal}from"./DeviceRegistrationModal.js";export{useLicense,useFeatureAccess,useIsPro,useProAccess,useTier}from"./hooks.js";export{useAccountAccess}from"./hooks.js";export{resolveAccountAccess}from"./accountAccess.js";export{LicenseTransportError,isTransientLicenseError}from"./api.js";export{isBuoyToken}from"./freeToken.js";export{isWeekendFreePro,useWeekendFreePro}from"./weekendPro.js";export async function setLicenseKey(e){const{LicenseManager:r}=await import("./LicenseManager");await r.initialize();return r.setLicenseKey(e)}function n(){const{isWeekendFreePro:e,weekendPassAppliesTo:r}=require("./weekendPro");const{LicenseManager:s}=require("./LicenseManager");return r(s.hasAccountAccess(),e())}export function isPro(){const{LicenseManager:e}=require("./LicenseManager");if(e.isPro())return true;return n()}export function hasEntitlement(e){const{LicenseManager:r}=require("./LicenseManager");if(r.hasEntitlement(e))return true;return n()}
18
+ */export{LicenseManager}from"./LicenseManager.js";export{DeviceRegistrationModal}from"./DeviceRegistrationModal.js";export{useLicense,useFeatureAccess,useIsPro,useProAccess,useTier}from"./hooks.js";export{useAccountAccess}from"./hooks.js";export{resolveAccountAccess}from"./accountAccess.js";export{LicenseTransportError,isTransientLicenseError}from"./api.js";export{SessionManager,SessionError}from"./sessionManager.js";export{useBuoySession}from"./hooks.js";export{isServiceKey,normalizeLicenseKey,sameLicenseKey}from"./serviceKey.js";export{isDevToken}from"./devToken.js";export{getSyncCredential}from"./syncCredential.js";export{isBuoyToken}from"./freeToken.js";export{isWeekendFreePro,useWeekendFreePro}from"./weekendPro.js";export async function setLicenseKey(e){const{LicenseManager:r}=await import("./LicenseManager");await r.initialize();return r.setLicenseKey(e)}function n(){const{isWeekendFreePro:e,weekendPassAppliesTo:r}=require("./weekendPro");const{LicenseManager:s}=require("./LicenseManager");return r(s.hasAccountAccess(),e())}export function isPro(){const{LicenseManager:e}=require("./LicenseManager");if(e.isPro())return true;return n()}export function hasEntitlement(e){const{LicenseManager:r}=require("./LicenseManager");if(r.hasEntitlement(e))return true;return n()}
@@ -15,4 +15,4 @@
15
15
  * Pro is $9/mo, and is free every weekend for anyone holding a key —
16
16
  * including a free one (`npx buoy login`). Buy a key at
17
17
  * https://buoy.gg or use it free on Saturday and Sunday.
18
- */import{LicenseManager as r}from"./LicenseManager.js";import{isWeekendFreePro as o,weekendPassAppliesTo as n}from"./weekendPro.js";export{LicenseManager}from"./LicenseManager.js";export{useLicense,useFeatureAccess,useIsPro,useProAccess,useTier}from"./hooks.js";export{useAccountAccess}from"./hooks.js";export{resolveAccountAccess}from"./accountAccess.js";export{LicenseTransportError,isTransientLicenseError}from"./api.js";export{isBuoyToken}from"./freeToken.js";export{isWeekendFreePro,useWeekendFreePro}from"./weekendPro.js";export async function setLicenseKey(e){const{LicenseManager:s}=await import("./LicenseManager");await s.initialize();return s.setLicenseKey(e)}function t(){return n(r.hasAccountAccess(),o())}export function isPro(){if(r.isPro())return true;return t()}export function hasEntitlement(e){if(r.hasEntitlement(e))return true;return t()}
18
+ */import{LicenseManager as r}from"./LicenseManager.js";import{isWeekendFreePro as n,weekendPassAppliesTo as t}from"./weekendPro.js";export{LicenseManager}from"./LicenseManager.js";export{useLicense,useFeatureAccess,useIsPro,useProAccess,useTier}from"./hooks.js";export{useAccountAccess}from"./hooks.js";export{resolveAccountAccess}from"./accountAccess.js";export{LicenseTransportError,isTransientLicenseError}from"./api.js";export{SessionManager,SessionError}from"./sessionManager.js";export{useBuoySession}from"./hooks.js";export{isServiceKey,normalizeLicenseKey,sameLicenseKey}from"./serviceKey.js";export{isDevToken}from"./devToken.js";export{getSyncCredential}from"./syncCredential.js";export{isBuoyToken}from"./freeToken.js";export{isWeekendFreePro,useWeekendFreePro}from"./weekendPro.js";export async function setLicenseKey(e){const{LicenseManager:s}=await import("./LicenseManager");await s.initialize();return s.setLicenseKey(e)}function o(){return t(r.hasAccountAccess(),n())}export function isPro(){if(r.isPro())return true;return o()}export function hasEntitlement(e){if(r.hasEntitlement(e))return true;return o()}
@@ -0,0 +1,6 @@
1
+ "use strict";/*!
2
+ * PROPRIETARY — Buoy license enforcement. NOT open source.
3
+ *
4
+ * Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
5
+ * (https://buoy.gg/terms), not an OSS license.
6
+ */import k from"node:http";import{createHash as b,randomBytes as y,timingSafeEqual as O}from"node:crypto";import{promises as p}from"node:fs";import{dirname as S,join as T}from"node:path";import{homedir as v}from"node:os";import{SessionManagerImpl as E,SessionError as h}from"./sessionManager.js";export const DESKTOP_AUDIENCE="app:gg.buoy.desktop";export const CLI_AUDIENCE="app:gg.buoy.cli";const A=5*60*1e3;const I=4096;const C=6e4;const _=3e4;export function defaultSessionFile(){return process.env.BUOY_SESSION_FILE||T(v(),".buoy","session.json")}export function fileSessionStorage(n){const i=async()=>{try{const t=JSON.parse(await p.readFile(n,"utf8"));return t&&typeof t==="object"?t:{}}catch{return{}}};const c=async t=>{await p.mkdir(S(n),{recursive:true,mode:448});if(Object.keys(t).length===0){await p.rm(n,{force:true});return}const a=`${n}.${process.pid}.${y(4).toString("hex")}.tmp`;await p.writeFile(a,JSON.stringify(t),{mode:384});await p.rename(a,n)};return{async getItem(t){return(await i())[t]??null},async setItem(t,a){const u=await i();u[t]=a;await c(u)},async removeItem(t){const a=await i();if(!(t in a))return;delete a[t];await c(a)}}}export function fileLock(n,i={}){const c=i.staleMs??C;const t=i.waitMs??_;return async(a,u)=>{const o=`${process.pid}:${y(8).toString("hex")}`;const e=Date.now()+t;await p.mkdir(S(n),{recursive:true,mode:448});for(;;){try{await p.writeFile(n,o,{flag:"wx",mode:384});break}catch(r){if(r.code!=="EEXIST")throw r;const s=await p.stat(n).catch(()=>null);if(s&&Date.now()-s.mtimeMs>c){await p.rm(n,{force:true});continue}if(Date.now()>e)throw new Error("Another Buoy process holds the sign-in lock.");await new Promise(f=>setTimeout(f,50))}}try{return await u()}finally{const r=await p.readFile(n,"utf8").catch(()=>null);if(r===o)await p.rm(n,{force:true})}}}function x(n,i){const c=Buffer.from(n);const t=Buffer.from(i);return c.length===t.length&&O(c,t)}export async function receiveCodeOnLoopback(n,i,c,t={}){let a;let u;const o=new Promise((l,d)=>{a=l;u=d});o.catch(()=>{});const e=k.createServer((l,d)=>{if(l.headers.origin===c){d.setHeader("Access-Control-Allow-Origin",c);d.setHeader("Access-Control-Allow-Headers","Content-Type");d.setHeader("Access-Control-Allow-Methods","POST, OPTIONS");d.setHeader("Access-Control-Allow-Private-Network","true")}if(l.method==="OPTIONS")return void d.writeHead(204).end();if(l.method!=="POST")return void d.writeHead(405).end();let g="";l.on("data",w=>{g+=w;if(g.length>I)l.destroy()});l.on("end",()=>{let w=null;try{w=JSON.parse(g)}catch{}if(!w||typeof w.state!=="string"||!x(w.state,i))return void d.writeHead(400).end();d.writeHead(200,{"Content-Type":"application/json"}).end('{"ok":true}');if(typeof w.code==="string"&&w.code)f(()=>a(w.code));else f(()=>u(new h("access_denied","Sign-in was cancelled.")))})});const r=setTimeout(()=>f(()=>u(new h("timeout","Sign-in took too long."))),t.timeoutMs??A);r.unref?.();const s=()=>f(()=>u(new h("popup_closed","Sign-in was cancelled.")));t.signal?.addEventListener("abort",s);function f(l){clearTimeout(r);t.signal?.removeEventListener("abort",s);e.close();l()}await new Promise((l,d)=>{e.once("error",d);e.listen(0,"127.0.0.1",()=>l())});const m=e.address();if(!m||typeof m==="string"){f(()=>u(new Error("Could not open a local port")));throw new Error("Could not open a local port")}return{url:`${n}&port=${m.port}`,code:o}}export function createNodeSession(n){const i=defaultSessionFile();const c=n.storage??fileSessionStorage(i);const t=(n.signinOrigin??process.env.BUOY_SITE_URL??"https://buoy.gg").replace(/\/$/,"");const a=n.fetch??((e,r)=>fetch(e,r));const u={fetch:a,storage:async()=>c,now:n.now??(()=>Date.now()),random:e=>new Uint8Array(y(e)),sha256:async e=>new Uint8Array(b("sha256").update(e).digest()),openPopup:()=>null,onMessage:()=>()=>{},withLock:fileLock(n.lockFile??`${i}.lock`),setTimer:(e,r)=>{const s=setTimeout(e,Math.min(r,2147483647));s.unref?.();return s},clearTimer:e=>clearTimeout(e),publicKeyHex:n.publicKeyHex};const o=new E(u);o.configure({audience:n.audience,signinOrigin:t});return{manager:o,async load(){await o.load();return o.getStatus()},getStatus:()=>o.getStatus(),signIn:(e={})=>o.signInWith(async(r,s)=>{const{url:f,code:m}=await receiveCodeOnLoopback(r,s,t,e);await n.openBrowser(f);return m}),signOut:()=>o.signOut(),refresh:e=>o.refresh(e),sync:()=>o.sync(),async devToken(){const e=o.getAccessToken();if(!e)return{ok:false,detail:"This computer is not signed in. Run `npx buoy login`."};try{const r=await a(`${t}/api/auth/dev-token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({access_token:e})});const s=await r.json().catch(()=>null);if(r.status===200&&typeof s?.dev_token==="string"){return{ok:true,token:s.dev_token,tier:typeof s.tier==="string"?s.tier:"free"}}return{ok:false,detail:typeof s?.error_description==="string"?s.error_description:"buoy.gg did not make a dev token."}}catch{return{ok:false,detail:"Buoy could not be reached. Check your connection and try again."}}},async isAvailable(){try{const e=await a(`${t}/api/auth/status`,{method:"GET",headers:{}});const r=await e.json().catch(()=>null);return e.status===200&&r?.enabled===true}catch{return false}},subscribe:e=>o.subscribe(e)}}
@@ -0,0 +1,6 @@
1
+ "use strict";/*!
2
+ * PROPRIETARY — Buoy license enforcement. NOT open source.
3
+ *
4
+ * Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
5
+ * (https://buoy.gg/terms), not an OSS license.
6
+ */import{isSessionToken as u,verifySessionToken as p}from"./sessionToken.js";import{realNow as y}from"./realNow.js";export const SERVICE_KEY_PREFIX="bsk1_";export const SERVICE_AUDIENCE="service";const k=15e3;export function isServiceKey(t){return t.startsWith(SERVICE_KEY_PREFIX)}export function normalizeLicenseKey(t){const e=t.trim();return isServiceKey(e)||u(e)?e:e.toUpperCase()}export function sameLicenseKey(t,e){return normalizeLicenseKey(t??"")===normalizeLicenseKey(e??"")}export async function exchangeServiceKey(t,e){const c=e.fetch??((r,l)=>fetch(r,l));const s=typeof AbortController!=="undefined"?new AbortController:void 0;const a=setTimeout(()=>s?.abort(),k);let n;let o;try{const r=await c(`${e.origin.replace(/\/$/,"")}/api/auth/service-token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:t}),signal:s?.signal});n=r.status;o=await r.json().catch(()=>null)}catch{return{ok:false,reason:"network",detail:"Buoy could not be reached to check the bot key."}}finally{clearTimeout(a)}if(n>=500||n===429)return{ok:false,reason:"network",detail:"Buoy is busy. The bot key will be checked again soon."};if(n!==200||typeof o?.access_token!=="string"){return{ok:false,reason:"rejected",detail:typeof o?.error_description==="string"?o.error_description:"This bot key was not accepted."}}const i=p(o.access_token,{audience:SERVICE_AUDIENCE,nowMs:y(),publicKeyHex:e.publicKeyHex});return i.ok?{ok:true,claims:i.claims}:{ok:false,reason:"rejected",detail:"Buoy sent a token this app could not check."}}