@burdenoff/be-sdk 2026.601.1 → 2026.601.2
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.
|
@@ -170,8 +170,7 @@ function normalizeStatus(status) {
|
|
|
170
170
|
}
|
|
171
171
|
__name(normalizeStatus, "normalizeStatus");
|
|
172
172
|
var ACTIVE_STATUSES = [
|
|
173
|
-
ShareStatus.ACCEPTED
|
|
174
|
-
"ACTIVE"
|
|
173
|
+
ShareStatus.ACCEPTED
|
|
175
174
|
];
|
|
176
175
|
var DENY = {
|
|
177
176
|
allowed: false,
|
|
@@ -1003,5 +1002,5 @@ CREATE UNIQUE INDEX IF NOT EXISTS share_grants_active_user_uq
|
|
|
1003
1002
|
`;
|
|
1004
1003
|
|
|
1005
1004
|
export { RESOURCE_CAPABILITY_MAP, RESOURCE_TYPE_LABELS, ROLE_CAPABILITIES, ROLE_ORDER, SHARE_EMAIL_TEMPLATE_SLUG, SHARE_GRANT_PARTIAL_UNIQUE_SQL, SHARE_GRANT_PRISMA, SHARE_GRANT_SDL, ShareRole, ShareService, ShareStatus, ShareVisibility, buildPerEntityShareSdl, buildShareEmailVariables, capabilitiesFor, legacyToRole, makeSendShareEmail, maxRole, normalizeStatus, resourceTypeLabel, roleAtLeast, roleLabel, roleToLegacy, sharing_exports };
|
|
1006
|
-
//# sourceMappingURL=chunk-
|
|
1007
|
-
//# sourceMappingURL=chunk-
|
|
1005
|
+
//# sourceMappingURL=chunk-XD5ZK727.js.map
|
|
1006
|
+
//# sourceMappingURL=chunk-XD5ZK727.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/sharing/index.ts","../src/sharing/types.ts","../src/sharing/share-service.ts","../src/sharing/email.ts","../src/sharing/sdl.ts","../src/sharing/prisma-fragment.ts"],"names":["ShareVisibility","ShareRole","ShareStatus","ROLE_ORDER","roleAtLeast","role","required","maxRole","a","b","ROLE_CAPABILITIES","canView","canComment","canEdit","canManage","canExecute","capabilitiesFor","RESOURCE_CAPABILITY_MAP","session","vibedeck","file","folder","roleToLegacy","resourceType","legacyToRole","legacy","table","toUpperCase","normalizeStatus","status","upper","ACTIVE_STATUSES","ACCEPTED","DENY","allowed","effectiveRole","via","notFound","message","GraphQLError","extensions","code","forbidden","badRequest","generateToken","randomBytes","toString","emailsMatch","trim","toLowerCase","pickHighestRole","candidates","best","c","ShareService","prisma","workspaceId","deps","sharedWithVibeRole","requireWorkspaceMember","config","options","VIEWER","resolveAccess","actorId","resourceId","meta","loadResourceMeta","ownerId","MANAGER","visibility","SHARED_WITH_VIBE","vibeId","hasVibeAccess","push","grant","queryActiveAccessGrants","isPublic","PUBLIC_LINK","isMyUserGrant","SHARED_WITH_USERS","granteeUserId","err","logger","warn","findMany","where","deletedAt","in","OR","AND","expiresAt","gt","Date","canAccess","requiredRole","result","assertAccess","mode","createUserShare","actor","input","id","email","granteeEmail","resolveUserByEmail","isMember","isWorkspaceMember","existing","findFirst","PENDING","update","data","create","token","createdBy","onBehalfOf","fireShareEmail","name","createLinkShare","acceptShare","findActiveByToken","idMatches","emailMatches","now","res","updateMany","acceptedAt","acceptedBy","count","fresh","updated","declineShare","REVOKED","revokedAt","revokedBy","shareGrantByToken","revoke","grantId","updateRole","resourceShares","orderBy","createdAt","sharesSharedWithMe","opts","take","skip","listAccessibleResourceIds","grants","Array","from","Set","map","g","listPublicResourceIds","touchAccess","lastAccessAt","accessCount","increment","debug","getTime","resourceName","sendShareEmail","recipientEmail","recipientUserId","acceptUrl","buildAcceptUrl","sharerName","idempotencyKey","SHARE_EMAIL_TEMPLATE_SLUG","RESOURCE_TYPE_LABELS","vibe","note","aiprompt","aicontext","instructionfile","tunnel","action","conversation","catalog","component","template","docs","resourceTypeLabel","ROLE_LABELS","COMMENTER","EDITOR","roleLabel","buildShareEmailVariables","args","makeSendShareEmail","notifier","recipient","userId","info","templateSlug","sendWithTemplate","variables","SHARE_GRANT_SDL","buildPerEntityShareSdl","entity","rbacResource","SHARE_GRANT_PRISMA","SHARE_GRANT_PARTIAL_UNIQUE_SQL"],"mappings":";;;;;;AAAA,IAAA,eAAA,GAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACuBO,IAAKA,eAAAA,6BAAAA,gBAAAA,EAAAA;AACkB,EAAAA,gBAAAA,CAAA,SAAA,CAAA,GAAA,SAAA;AAEsD,EAAAA,gBAAAA,CAAA,mBAAA,CAAA,GAAA,mBAAA;AAElC,EAAAA,gBAAAA,CAAA,kBAAA,CAAA,GAAA,kBAAA;AAEtB,EAAAA,gBAAAA,CAAA,aAAA,CAAA,GAAA,aAAA;AAPhBA,EAAAA,OAAAA,gBAAAA;;AAeL,IAAKC,SAAAA,6BAAAA,UAAAA,EAAAA;AACK,EAAAA,UAAAA,CAAA,QAAA,CAAA,GAAA,QAAA;AAEK,EAAAA,UAAAA,CAAA,WAAA,CAAA,GAAA,WAAA;AAEiD,EAAAA,UAAAA,CAAA,QAAA,CAAA,GAAA,QAAA;AAEvC,EAAAA,UAAAA,CAAA,SAAA,CAAA,GAAA,SAAA;AAPpBA,EAAAA,OAAAA,UAAAA;;AAYL,IAAKC,WAAAA,6BAAAA,YAAAA,EAAAA;AACkD,EAAAA,YAAAA,CAAA,SAAA,CAAA,GAAA,SAAA;AAEW,EAAAA,YAAAA,CAAA,UAAA,CAAA,GAAA,UAAA;AAEjD,EAAAA,YAAAA,CAAA,SAAA,CAAA,GAAA,SAAA;AAED,EAAAA,YAAAA,CAAA,SAAA,CAAA,GAAA,SAAA;AAPXA,EAAAA,OAAAA,YAAAA;;AAYL,IAAMC,UAAAA,GAAwC;AACnD,EAAA,CAAA,QAAA,GAAoB,CAAA;AACpB,EAAA,CAAA,WAAA,GAAuB,CAAA;AACvB,EAAA,CAAA,QAAA,GAAoB,CAAA;AACpB,EAAA,CAAA,SAAA,GAAqB;AACvB;AAGO,SAASC,WAAAA,CAAYC,MAAiBC,QAAAA,EAAmB;AAC9D,EAAA,OAAOH,UAAAA,CAAWE,IAAAA,CAAAA,IAASF,UAAAA,CAAWG,QAAAA,CAAAA;AACxC;AAFgBF,MAAAA,CAAAA,WAAAA,EAAAA,aAAAA,CAAAA;AAKT,SAASG,OAAAA,CAAQC,GAAcC,CAAAA,EAAY;AAChD,EAAA,OAAON,WAAWK,CAAAA,CAAAA,IAAML,UAAAA,CAAWM,CAAAA,IAAKD,CAAAA,GAAIC,CAAAA;AAC9C;AAFgBF,MAAAA,CAAAA,OAAAA,EAAAA,SAAAA,CAAAA;AAiBT,IAAMG,iBAAAA,GAA0D;AACrE,EAAA,CAAA,QAAA,GAAoB;IAAEC,OAAAA,EAAS,IAAA;IAAMC,UAAAA,EAAY,KAAA;IAAOC,OAAAA,EAAS,KAAA;IAAOC,SAAAA,EAAW,KAAA;IAAOC,UAAAA,EAAY;AAAM,GAAA;AAC5G,EAAA,CAAA,WAAA,GAAuB;IAAEJ,OAAAA,EAAS,IAAA;IAAMC,UAAAA,EAAY,IAAA;IAAMC,OAAAA,EAAS,KAAA;IAAOC,SAAAA,EAAW,KAAA;IAAOC,UAAAA,EAAY;AAAM,GAAA;AAC9G,EAAA,CAAA,QAAA,GAAoB;IAAEJ,OAAAA,EAAS,IAAA;IAAMC,UAAAA,EAAY,IAAA;IAAMC,OAAAA,EAAS,IAAA;IAAMC,SAAAA,EAAW,KAAA;IAAOC,UAAAA,EAAY;AAAK,GAAA;AACzG,EAAA,CAAA,SAAA,GAAqB;IAAEJ,OAAAA,EAAS,IAAA;IAAMC,UAAAA,EAAY,IAAA;IAAMC,OAAAA,EAAS,IAAA;IAAMC,SAAAA,EAAW,IAAA;IAAMC,UAAAA,EAAY;AAAK;AAC3G;AAGO,SAASC,gBAAgBX,IAAAA,EAAe;AAC7C,EAAA,OAAOK,kBAAkBL,IAAAA,CAAAA;AAC3B;AAFgBW,MAAAA,CAAAA,eAAAA,EAAAA,iBAAAA,CAAAA;AAST,IAAMC,uBAAAA,GAA8E;EACzFC,OAAAA,EAAS;AACP,IAAA,CAAA,QAAA,GAAoB,MAAA;AACpB,IAAA,CAAA,WAAA,GAAuB,MAAA;AACvB,IAAA,CAAA,QAAA,GAAoB,UAAA;AACpB,IAAA,CAAA,SAAA,GAAqB;AACvB,GAAA;EACAC,QAAAA,EAAU;AACR,IAAA,CAAA,QAAA,GAAoB,MAAA;AACpB,IAAA,CAAA,WAAA,GAAuB,MAAA;AACvB,IAAA,CAAA,QAAA,GAAoB,SAAA;AACpB,IAAA,CAAA,SAAA,GAAqB;AACvB,GAAA;EACAC,IAAAA,EAAM;AACJ,IAAA,CAAA,QAAA,GAAoB,MAAA;AACpB,IAAA,CAAA,WAAA,GAAuB,SAAA;AACvB,IAAA,CAAA,QAAA,GAAoB,MAAA;AACpB,IAAA,CAAA,SAAA,GAAqB;AACvB,GAAA;EACAC,MAAAA,EAAQ;AACN,IAAA,CAAA,QAAA,GAAoB,MAAA;AACpB,IAAA,CAAA,WAAA,GAAuB,SAAA;AACvB,IAAA,CAAA,QAAA,GAAoB,MAAA;AACpB,IAAA,CAAA,SAAA,GAAqB;AACvB;AACF;AAGO,SAASC,YAAAA,CAAaC,cAAsBlB,IAAAA,EAAe;AAChE,EAAA,OAAOY,uBAAAA,CAAwBM,YAAAA,CAAAA,GAAgBlB,IAAAA,CAAAA,IAASA,IAAAA;AAC1D;AAFgBiB,MAAAA,CAAAA,YAAAA,EAAAA,cAAAA,CAAAA;AAQT,SAASE,YAAAA,CAAaD,cAAsBE,MAAAA,EAAc;AAC/D,EAAA,MAAMC,KAAAA,GAAQT,wBAAwBM,YAAAA,CAAAA;AACtC,EAAA,IAAIG,KAAAA,EAAO;AAGT,IAAA,KAAA,MAAWrB,IAAAA,IAAQ;;;;;AAA8E,KAAA,EAAA;AAC/F,MAAA,IAAIqB,KAAAA,CAAMrB,IAAAA,CAAAA,KAAUoB,MAAAA,EAAQ,OAAOpB,IAAAA;AACrC,IAAA;AACF,EAAA;AACA,EAAA,QAAQoB,MAAAA,CAAOE,aAAW;IACxB,KAAK,SAAA;IACL,KAAK,OAAA;IACL,KAAK,OAAA;AACH,MAAA,OAAA,SAAA;IACF,KAAK,QAAA;IACL,KAAK,MAAA;IACL,KAAK,UAAA;IACL,KAAK,SAAA;IACL,KAAK,OAAA;AACH,MAAA,OAAA,QAAA;IACF,KAAK,WAAA;IACL,KAAK,SAAA;AACH,MAAA,OAAA,WAAA;AACF,IAAA;AACE,MAAA,OAAA,QAAA;AACJ;AACF;AA1BgBH,MAAAA,CAAAA,YAAAA,EAAAA,cAAAA,CAAAA;AAgCT,SAASI,gBAAgBC,MAAAA,EAAc;AAC5C,EAAA,MAAMC,KAAAA,GAAQD,OAAOF,WAAAA,EAAW;AAChC,EAAA,IAAIG,KAAAA,KAAU,UAAU,OAAA,UAAA;AACxB,EAAA,IAAIA,KAAAA,IAAS5B,aAAa,OAAO4B,KAAAA;AACjC,EAAA,OAAA,SAAA;AACF;AALgBF,MAAAA,CAAAA,eAAAA,EAAAA,iBAAAA,CAAAA;ACpIhB,IAAMG,eAAAA,GAAkB;EAAC7B,WAAAA,CAAY8B;;AAErC,IAAMC,IAAAA,GAAqB;EAAEC,OAAAA,EAAS,KAAA;EAAOC,aAAAA,EAAe,IAAA;EAAMC,GAAAA,EAAK;AAAO,CAAA;AAE9E,SAASC,QAAAA,CAASC,UAAU,WAAA,EAAW;AACrC,EAAA,OAAO,IAAIC,aAAaD,OAAAA,EAAS;IAAEE,UAAAA,EAAY;MAAEC,IAAAA,EAAM;AAAY;GAAE,CAAA;AACvE;AAFSJ,MAAAA,CAAAA,QAAAA,EAAAA,UAAAA,CAAAA;AAGT,SAASK,SAAAA,CAAUJ,UAAU,WAAA,EAAW;AACtC,EAAA,OAAO,IAAIC,aAAaD,OAAAA,EAAS;IAAEE,UAAAA,EAAY;MAAEC,IAAAA,EAAM;AAAY;GAAE,CAAA;AACvE;AAFSC,MAAAA,CAAAA,SAAAA,EAAAA,WAAAA,CAAAA;AAGT,SAASC,WAAWL,OAAAA,EAAe;AACjC,EAAA,OAAO,IAAIC,aAAaD,OAAAA,EAAS;IAAEE,UAAAA,EAAY;MAAEC,IAAAA,EAAM;AAAc;GAAE,CAAA;AACzE;AAFSE,MAAAA,CAAAA,UAAAA,EAAAA,YAAAA,CAAAA;AAIT,SAASC,aAAAA,GAAAA;AAEP,EAAA,OAAOC,WAAAA,CAAY,EAAA,CAAA,CAAIC,QAAAA,CAAS,KAAA,CAAA;AAClC;AAHSF,MAAAA,CAAAA,aAAAA,EAAAA,eAAAA,CAAAA;AAKT,SAASG,WAAAA,CAAYvC,GAA8BC,CAAAA,EAA4B;AAC7E,EAAA,OAAO,CAAC,CAACD,CAAAA,IAAK,CAAC,CAACC,CAAAA,IAAKD,CAAAA,CAAEwC,IAAAA,EAAI,CAAGC,WAAAA,EAAW,KAAOxC,CAAAA,CAAEuC,IAAAA,GAAOC,WAAAA,EAAW;AACtE;AAFSF,MAAAA,CAAAA,WAAAA,EAAAA,aAAAA,CAAAA;AAUT,SAASG,gBAAgBC,UAAAA,EAA2B;AAClD,EAAA,IAAIC,IAAAA,GAA6B,IAAA;AACjC,EAAA,KAAA,MAAWC,KAAKF,UAAAA,EAAY;AAC1B,IAAA,IAAI,CAACC,IAAAA,IAAS7C,OAAAA,CAAQ6C,IAAAA,CAAK/C,MAAMgD,CAAAA,CAAEhD,IAAI,CAAA,KAAMgD,CAAAA,CAAEhD,IAAAA,IAAQgD,CAAAA,CAAEhD,IAAAA,KAAS+C,IAAAA,CAAK/C,MAAO+C,IAAAA,GAAOC,CAAAA;AACvF,EAAA;AACA,EAAA,OAAOD,IAAAA;AACT;AANSF,MAAAA,CAAAA,eAAAA,EAAAA,iBAAAA,CAAAA;AAgBF,IAAMI,eAAN,MAAMA;EA1Fb;;;AA2FmBC,EAAAA,MAAAA;AACAhC,EAAAA,YAAAA;AACAiC,EAAAA,WAAAA;AACAC,EAAAA,IAAAA;AACAC,EAAAA,kBAAAA;AACAC,EAAAA,sBAAAA;AAEjB,EAAA,WAAA,CAAYC,MAAAA,EAA4B;AACtC,IAAA,IAAA,CAAKL,SAASK,MAAAA,CAAOL,MAAAA;AACrB,IAAA,IAAA,CAAKhC,eAAeqC,MAAAA,CAAOrC,YAAAA;AAC3B,IAAA,IAAA,CAAKiC,cAAcI,MAAAA,CAAOJ,WAAAA;AAC1B,IAAA,IAAA,CAAKC,OAAOG,MAAAA,CAAOH,IAAAA;AACnB,IAAA,IAAA,CAAKC,kBAAAA,GAAqBE,MAAAA,CAAOC,OAAAA,EAASH,kBAAAA,IAAsBzD,SAAAA,CAAU6D,MAAAA;AAC1E,IAAA,IAAA,CAAKH,sBAAAA,GAAyBC,MAAAA,CAAOC,OAAAA,EAASF,sBAAAA,IAA0B,IAAA;AAC1E,EAAA;;;;;;;;;;;;EAcA,MAAMI,aAAAA,CAAcC,SAAiBC,UAAAA,EAA2C;AAC9E,IAAA,IAAI;AACF,MAAA,MAAMC,IAAAA,GAAO,MAAM,IAAA,CAAKT,IAAAA,CAAKU,iBAAiBF,UAAAA,CAAAA;AAC9C,MAAA,IAAI,CAACC,MAAM,OAAOjC,IAAAA;AAGlB,MAAA,IAAI+B,OAAAA,IAAWE,IAAAA,CAAKE,OAAAA,KAAYJ,OAAAA,EAAS;AACvC,QAAA,OAAO;UAAE9B,OAAAA,EAAS,IAAA;AAAMC,UAAAA,aAAAA,EAAelC,SAAAA,CAAUoE,OAAAA;UAASjC,GAAAA,EAAK;AAAQ,SAAA;AACzE,MAAA;AAEA,MAAA,MAAMe,aAA8B,EAAA;AAGpC,MAAA,IAAIe,KAAKI,UAAAA,KAAetE,eAAAA,CAAgBuE,gBAAAA,IAAoBL,IAAAA,CAAKM,UAAUR,OAAAA,EAAS;AAClF,QAAA,IAAI,MAAM,KAAKP,IAAAA,CAAKgB,aAAAA,CAAcT,SAASE,IAAAA,CAAKM,MAAAA,EAAQ,IAAA,CAAKhB,WAAW,CAAA,EAAG;AACzEL,UAAAA,UAAAA,CAAWuB,IAAAA,CAAK;AAAErE,YAAAA,IAAAA,EAAM,IAAA,CAAKqD,kBAAAA;YAAoBtB,GAAAA,EAAK;WAAO,CAAA;AAC/D,QAAA;AACF,MAAA;AAGA,MAAA,KAAA,MAAWuC,SAAS,MAAM,IAAA,CAAKC,uBAAAA,CAAwBZ,OAAAA,EAASC,UAAAA,CAAAA,EAAa;AAC3E,QAAA,MAAMY,QAAAA,GAAWF,KAAAA,CAAML,UAAAA,KAAetE,eAAAA,CAAgB8E,WAAAA;AACtD,QAAA,MAAMC,gBAAgBJ,KAAAA,CAAML,UAAAA,KAAetE,eAAAA,CAAgBgF,iBAAAA,IAAqBL,MAAMM,aAAAA,KAAkBjB,OAAAA;AACxG,QAAA,IAAIa,QAAAA,aAAqBH,IAAAA,CAAK;AAAErE,UAAAA,IAAAA,EAAMsE,KAAAA,CAAMtE,IAAAA;UAAM+B,GAAAA,EAAK;SAAc,CAAA;AAC5D2C,aAAAA,IAAAA,aAAAA,aAA0BL,IAAAA,CAAK;AAAErE,UAAAA,IAAAA,EAAMsE,KAAAA,CAAMtE,IAAAA;UAAM+B,GAAAA,EAAK;SAAa,CAAA;AAChF,MAAA;AAEA,MAAA,MAAMgB,IAAAA,GAAOF,gBAAgBC,UAAAA,CAAAA;AAC7B,MAAA,IAAI,CAACC,MAAM,OAAOnB,IAAAA;AAClB,MAAA,OAAO;QAAEC,OAAAA,EAAS,IAAA;AAAMC,QAAAA,aAAAA,EAAeiB,IAAAA,CAAK/C,IAAAA;AAAM+B,QAAAA,GAAAA,EAAKgB,IAAAA,CAAKhB;AAAI,OAAA;AAClE,IAAA,CAAA,CAAA,OAAS8C,GAAAA,EAAK;AAEZC,MAAAA,MAAAA,CAAOC,KAAK,8CAAA,EAAgD;AAC1D7D,QAAAA,YAAAA,EAAc,IAAA,CAAKA,YAAAA;AACnB0C,QAAAA,UAAAA;AACAiB,QAAAA;OACF,CAAA;AACA,MAAA,OAAOjD,IAAAA;AACT,IAAA;AACF,EAAA;;EAGA,MAAc2C,uBAAAA,CAAwBZ,SAAiBC,UAAAA,EAAiD;AACtG,IAAA,OAAO,IAAA,CAAKV,OAAO8B,QAAAA,CAAS;MAC1BC,KAAAA,EAAO;AACL/D,QAAAA,YAAAA,EAAc,IAAA,CAAKA,YAAAA;AACnB0C,QAAAA,UAAAA;QACAsB,SAAAA,EAAW,IAAA;QACX1D,MAAAA,EAAQ;UAAE2D,EAAAA,EAAI;AAAIzD,YAAAA,GAAAA;;AAAiB,SAAA;QACnC0D,EAAAA,EAAI;AACF,UAAA;AAAEnB,YAAAA,UAAAA,EAAYtE,eAAAA,CAAgB8E;AAAY,WAAA;aACtCd,OAAAA,GAAU;AAAC,YAAA;cAAEiB,aAAAA,EAAejB,OAAAA;AAASM,cAAAA,UAAAA,EAAYtE,eAAAA,CAAgBgF;AAAkB;cAAK;;QAE9FU,GAAAA,EAAK;AAAC,UAAA;YAAED,EAAAA,EAAI;AAAC,cAAA;gBAAEE,SAAAA,EAAW;AAAK,eAAA;AAAG,cAAA;gBAAEA,SAAAA,EAAW;AAAEC,kBAAAA,EAAAA,sBAAQC,IAAAA;AAAO;AAAE;;AAAG;;AACvE;KACF,CAAA;AACF,EAAA;;EAGA,MAAMC,SAAAA,CAAU9B,OAAAA,EAAiBC,UAAAA,EAAoB8B,YAAAA,EAA2C;AAC9F,IAAA,MAAMC,MAAAA,GAAS,MAAM,IAAA,CAAKjC,aAAAA,CAAcC,SAASC,UAAAA,CAAAA;AACjD,IAAA,OAAO+B,MAAAA,CAAO9D,WAAW8D,MAAAA,CAAO7D,aAAAA,KAAkB,QAAQ/B,WAAAA,CAAY4F,MAAAA,CAAO7D,eAAe4D,YAAAA,CAAAA;AAC9F,EAAA;;AAGA,EAAA,MAAME,YAAAA,CACJjC,OAAAA,EACAC,UAAAA,EACA8B,YAAAA,EACAG,OAA0B,MAAA,EACX;AACf,IAAA,IAAI,MAAM,IAAA,CAAKJ,SAAAA,CAAU9B,OAAAA,EAASC,UAAAA,EAAY8B,YAAAA,CAAAA,EAAe;AAE7D,IAAA,MAAMG,IAAAA,KAAS,MAAA,GAAS7D,QAAAA,EAAAA,GAAaK,UAAU,mDAAA,CAAA;AACjD,EAAA;;;;;EAOA,MAAMyD,eAAAA,CAAgBC,OAAmBC,KAAAA,EAAwD;AAC/F,IAAA,MAAMnC,OAAO,MAAM,IAAA,CAAKT,IAAAA,CAAKU,gBAAAA,CAAiBkC,MAAMpC,UAAU,CAAA;AAC9D,IAAA,IAAI,CAACC,IAAAA,EAAM,MAAM7B,QAAAA,CAAS,oBAAA,CAAA;AAG1B,IAAA,MAAM,IAAA,CAAK4D,aAAaG,KAAAA,CAAME,EAAAA,EAAID,MAAMpC,UAAAA,EAAYhE,SAAAA,CAAUoE,SAAS,QAAA,CAAA;AAEvE,IAAA,MAAMkC,KAAAA,GAAQF,KAAAA,CAAMG,YAAAA,CAAaxD,IAAAA,GAAOC,WAAAA,EAAW;AACnD,IAAA,IAAI,CAACsD,KAAAA,EAAO,MAAM5D,UAAAA,CAAW,+BAAA,CAAA;AAE7B,IAAA,MAAMsC,aAAAA,GAAgB,MAAM,IAAA,CAAKxB,IAAAA,CAAKgD,mBAAmBF,KAAAA,CAAAA;AAEzD,IAAA,IAAItB,aAAAA,IAAiBA,aAAAA,KAAkBmB,KAAAA,CAAME,EAAAA,EAAI;AAC/C,MAAA,MAAM3D,WAAW,2CAAA,CAAA;AACnB,IAAA;AAIA,IAAA,IAAIsC,aAAAA,IAAiB,KAAKtB,sBAAAA,EAAwB;AAChD,MAAA,MAAM+C,WAAW,MAAM,IAAA,CAAKjD,KAAKkD,iBAAAA,CAAkB1B,aAAAA,EAAe,KAAKzB,WAAW,CAAA;AAClF,MAAA,IAAIkD,aAAa,KAAA,EAAO;AACtB,QAAA,MAAMhE,UAAU,mDAAA,CAAA;AAClB,MAAA;AACF,IAAA;AAGA,IAAA,MAAMkE,QAAAA,GAAW,MAAM,IAAA,CAAKrD,MAAAA,CAAOsD,SAAAA,CAAU;MAC3CvB,KAAAA,EAAO;AACL/D,QAAAA,YAAAA,EAAc,IAAA,CAAKA,YAAAA;AACnB0C,QAAAA,UAAAA,EAAYoC,KAAAA,CAAMpC,UAAAA;QAClBsB,SAAAA,EAAW,IAAA;QACX1D,MAAAA,EAAQ;UAAE2D,EAAAA,EAAI;YAACtF,WAAAA,CAAY4G,OAAAA;YAAS5G,WAAAA,CAAY8B;;AAAU,SAAA;QAC1DyD,EAAAA,EAAI;aAAKR,aAAAA,GAAgB;AAAC,YAAA;AAAEA,cAAAA;AAAc;cAAK,EAAA;AAAK,UAAA;YAAEuB,YAAAA,EAAcD;AAAM;;AAC5E;KACF,CAAA;AAEA,IAAA,IAAI5B,KAAAA;AACJ,IAAA,IAAIiC,QAAAA,EAAU;AACZjC,MAAAA,KAAAA,GAAQ,MAAM,IAAA,CAAKpB,MAAAA,CAAOwD,MAAAA,CAAO;QAC/BzB,KAAAA,EAAO;AAAEgB,UAAAA,EAAAA,EAAIM,QAAAA,CAASN;AAAG,SAAA;QACzBU,IAAAA,EAAM;AACJ3G,UAAAA,IAAAA,EAAMgG,KAAAA,CAAMhG,IAAAA;AACZiC,UAAAA,OAAAA,EAAS+D,MAAM/D,OAAAA,IAAW,IAAA;AAC1BqD,UAAAA,SAAAA,EAAWU,MAAMV,SAAAA,IAAa,IAAA;UAC9B,GAAIV,aAAAA,IAAiB,CAAC2B,QAAAA,CAAS3B,aAAAA,GAAgB;AAAEA,YAAAA;AAAc,WAAA,GAAI;AACrE;OACF,CAAA;IACF,CAAA,MAAO;AACLN,MAAAA,KAAAA,GAAQ,MAAM,IAAA,CAAKpB,MAAAA,CAAO0D,MAAAA,CAAO;QAC/BD,IAAAA,EAAM;AACJxD,UAAAA,WAAAA,EAAa,IAAA,CAAKA,WAAAA;AAClBjC,UAAAA,YAAAA,EAAc,IAAA,CAAKA,YAAAA;AACnB0C,UAAAA,UAAAA,EAAYoC,KAAAA,CAAMpC,UAAAA;AAClBgB,UAAAA,aAAAA,EAAeA,aAAAA,IAAiB,IAAA;UAChCuB,YAAAA,EAAcD,KAAAA;AACdlG,UAAAA,IAAAA,EAAMgG,KAAAA,CAAMhG,IAAAA;AACZiE,UAAAA,UAAAA,EAAYtE,eAAAA,CAAgBgF,iBAAAA;AAC5BnD,UAAAA,MAAAA,EAAQ3B,WAAAA,CAAY4G,OAAAA;AACpBI,UAAAA,KAAAA,EAAOtE,aAAAA,EAAAA;AACP+C,UAAAA,SAAAA,EAAWU,MAAMV,SAAAA,IAAa,IAAA;AAC9BrD,UAAAA,OAAAA,EAAS+D,MAAM/D,OAAAA,IAAW,IAAA;AAC1B6E,UAAAA,SAAAA,EAAWf,KAAAA,CAAME,EAAAA;AACjBc,UAAAA,UAAAA,EAAYhB,KAAAA,CAAME;AACpB;OACF,CAAA;AACF,IAAA;AAEA,IAAA,MAAM,IAAA,CAAKe,cAAAA,CAAejB,KAAAA,EAAOzB,KAAAA,EAAOT,KAAKoD,IAAI,CAAA;AACjD,IAAA,OAAO3C,KAAAA;AACT,EAAA;;EAGA,MAAM4C,eAAAA,CAAgBnB,OAAmBC,KAAAA,EAAwD;AAC/F,IAAA,MAAMnC,OAAO,MAAM,IAAA,CAAKT,IAAAA,CAAKU,gBAAAA,CAAiBkC,MAAMpC,UAAU,CAAA;AAC9D,IAAA,IAAI,CAACC,IAAAA,EAAM,MAAM7B,QAAAA,CAAS,oBAAA,CAAA;AAC1B,IAAA,MAAM,IAAA,CAAK4D,aAAaG,KAAAA,CAAME,EAAAA,EAAID,MAAMpC,UAAAA,EAAYhE,SAAAA,CAAUoE,SAAS,QAAA,CAAA;AAEvE,IAAA,OAAO,IAAA,CAAKd,OAAO0D,MAAAA,CAAO;MACxBD,IAAAA,EAAM;AACJxD,QAAAA,WAAAA,EAAa,IAAA,CAAKA,WAAAA;AAClBjC,QAAAA,YAAAA,EAAc,IAAA,CAAKA,YAAAA;AACnB0C,QAAAA,UAAAA,EAAYoC,KAAAA,CAAMpC,UAAAA;QAClBgB,aAAAA,EAAe,IAAA;QACfuB,YAAAA,EAAc,IAAA;AACdnG,QAAAA,IAAAA,EAAMgG,KAAAA,CAAMhG,IAAAA;AACZiE,QAAAA,UAAAA,EAAYtE,eAAAA,CAAgB8E,WAAAA;AAC5BjD,QAAAA,MAAAA,EAAQ3B,WAAAA,CAAY8B,QAAAA;AACpBkF,QAAAA,KAAAA,EAAOtE,aAAAA,EAAAA;AACP+C,QAAAA,SAAAA,EAAWU,MAAMV,SAAAA,IAAa,IAAA;QAC9BrD,OAAAA,EAAS,IAAA;AACT6E,QAAAA,SAAAA,EAAWf,KAAAA,CAAME,EAAAA;AACjBc,QAAAA,UAAAA,EAAYhB,KAAAA,CAAME;AACpB;KACF,CAAA;AACF,EAAA;;;;;EAOA,MAAMkB,WAAAA,CAAYN,OAAed,KAAAA,EAA8C;AAC7E,IAAA,MAAMzB,KAAAA,GAAQ,MAAM,IAAA,CAAK8C,iBAAAA,CAAkBP,KAAAA,CAAAA;AAC3C,IAAA,IAAI,CAACvC,KAAAA,EAAO,MAAMtC,QAAAA,CAAS,2CAAA,CAAA;AAE3B,IAAA,IAAIsC,KAAAA,CAAML,UAAAA,KAAetE,eAAAA,CAAgB8E,WAAAA,EAAa;AAEpD,MAAA,OAAOH,KAAAA;AACT,IAAA;AAEA,IAAA,MAAM+C,YAAY,CAAC,CAAC/C,MAAMM,aAAAA,IAAiBN,KAAAA,CAAMM,kBAAkBmB,KAAAA,CAAME,EAAAA;AACzE,IAAA,MAAMqB,YAAAA,GAAe5E,WAAAA,CAAY4B,KAAAA,CAAM6B,YAAAA,EAAcJ,MAAMG,KAAK,CAAA;AAChE,IAAA,IAAI,CAACmB,SAAAA,IAAa,CAACC,YAAAA,EAAc;AAC/B,MAAA,MAAMjF,UAAU,iDAAA,CAAA;AAClB,IAAA;AAEA,IAAA,IAAIiC,KAAAA,CAAM9C,MAAAA,KAAW3B,WAAAA,CAAY8B,QAAAA,EAAU;AAEzC,MAAA,IAAI,CAAC2C,MAAMM,aAAAA,EAAe;AACxB,QAAA,OAAO,IAAA,CAAK1B,OAAOwD,MAAAA,CAAO;UAAEzB,KAAAA,EAAO;AAAEgB,YAAAA,EAAAA,EAAI3B,KAAAA,CAAM2B;AAAG,WAAA;UAAGU,IAAAA,EAAM;AAAE/B,YAAAA,aAAAA,EAAemB,KAAAA,CAAME;AAAG;SAAE,CAAA;AACzF,MAAA;AACA,MAAA,OAAO3B,KAAAA;AACT,IAAA;AAEA,IAAA,MAAMiD,GAAAA,uBAAU/B,IAAAA,EAAAA;AAChB,IAAA,MAAMgC,GAAAA,GAAM,MAAM,IAAA,CAAKtE,MAAAA,CAAOuE,UAAAA,CAAW;MACvCxC,KAAAA,EAAO;AAAEgB,QAAAA,EAAAA,EAAI3B,KAAAA,CAAM2B,EAAAA;AAAIzE,QAAAA,MAAAA,EAAQ3B,WAAAA,CAAY4G;AAAQ,OAAA;MACnDE,IAAAA,EAAM;AAAEnF,QAAAA,MAAAA,EAAQ3B,WAAAA,CAAY8B,QAAAA;QAAU+F,UAAAA,EAAYH,GAAAA;AAAKI,QAAAA,UAAAA,EAAY5B,KAAAA,CAAME,EAAAA;AAAIrB,QAAAA,aAAAA,EAAemB,KAAAA,CAAME;AAAG;KACvG,CAAA;AACA,IAAA,IAAIuB,GAAAA,CAAII,UAAU,CAAA,EAAG;AAEnB,MAAA,MAAMC,KAAAA,GAAQ,MAAM,IAAA,CAAK3E,MAAAA,CAAOsD,SAAAA,CAAU;QAAEvB,KAAAA,EAAO;AAAEgB,UAAAA,EAAAA,EAAI3B,KAAAA,CAAM2B;AAAG;OAAE,CAAA;AACpE,MAAA,IAAI4B,OAAO,OAAOA,KAAAA;AACpB,IAAA;AACA,IAAA,MAAMC,OAAAA,GAAU,MAAM,IAAA,CAAK5E,MAAAA,CAAOsD,SAAAA,CAAU;MAAEvB,KAAAA,EAAO;AAAEgB,QAAAA,EAAAA,EAAI3B,KAAAA,CAAM2B;AAAG;KAAE,CAAA;AACtE,IAAA,IAAI,CAAC6B,OAAAA,EAAS,MAAM9F,QAAAA,EAAAA;AACpB,IAAA,OAAO8F,OAAAA;AACT,EAAA;;EAGA,MAAMC,YAAAA,CAAalB,OAAed,KAAAA,EAAqC;AACrE,IAAA,MAAMzB,KAAAA,GAAQ,MAAM,IAAA,CAAK8C,iBAAAA,CAAkBP,KAAAA,CAAAA;AAC3C,IAAA,IAAI,CAACvC,OAAO,OAAO,KAAA;AACnB,IAAA,MAAM+C,YAAY,CAAC,CAAC/C,MAAMM,aAAAA,IAAiBN,KAAAA,CAAMM,kBAAkBmB,KAAAA,CAAME,EAAAA;AACzE,IAAA,MAAMqB,YAAAA,GAAe5E,WAAAA,CAAY4B,KAAAA,CAAM6B,YAAAA,EAAcJ,MAAMG,KAAK,CAAA;AAChE,IAAA,IAAI,CAACmB,SAAAA,IAAa,CAACC,YAAAA,EAAc,MAAMjF,UAAU,iDAAA,CAAA;AACjD,IAAA,MAAM,IAAA,CAAKa,OAAOwD,MAAAA,CAAO;MACvBzB,KAAAA,EAAO;AAAEgB,QAAAA,EAAAA,EAAI3B,KAAAA,CAAM2B;AAAG,OAAA;MACtBU,IAAAA,EAAM;AAAEnF,QAAAA,MAAAA,EAAQ3B,WAAAA,CAAYmI,OAAAA;AAASC,QAAAA,SAAAA,sBAAezC,IAAAA,EAAAA;AAAQ0C,QAAAA,SAAAA,EAAWnC,KAAAA,CAAME;AAAG;KAClF,CAAA;AACA,IAAA,OAAO,IAAA;AACT,EAAA;;AAGA,EAAA,MAAMkC,kBAAkBtB,KAAAA,EAAiD;AACvE,IAAA,OAAO,IAAA,CAAKO,kBAAkBP,KAAAA,CAAAA;AAChC,EAAA;;;;;EAOA,MAAMuB,MAAAA,CAAOC,SAAiBtC,KAAAA,EAA8C;AAC1E,IAAA,MAAMzB,KAAAA,GAAQ,MAAM,IAAA,CAAKpB,MAAAA,CAAOsD,SAAAA,CAAU;MAAEvB,KAAAA,EAAO;QAAEgB,EAAAA,EAAIoC,OAAAA;AAASnH,QAAAA,YAAAA,EAAc,IAAA,CAAKA;AAAa;KAAE,CAAA;AACpG,IAAA,IAAI,CAACoD,KAAAA,IAASA,KAAAA,CAAMY,SAAAA,QAAiBlD,QAAAA,EAAAA;AACrC,IAAA,MAAM,IAAA,CAAK4D,aAAaG,KAAAA,CAAME,EAAAA,EAAI3B,MAAMV,UAAAA,EAAYhE,SAAAA,CAAUoE,SAAS,QAAA,CAAA;AACvE,IAAA,OAAO,IAAA,CAAKd,OAAOwD,MAAAA,CAAO;MACxBzB,KAAAA,EAAO;QAAEgB,EAAAA,EAAIoC;AAAQ,OAAA;MACrB1B,IAAAA,EAAM;AAAEnF,QAAAA,MAAAA,EAAQ3B,WAAAA,CAAYmI,OAAAA;AAASC,QAAAA,SAAAA,sBAAezC,IAAAA,EAAAA;AAAQ0C,QAAAA,SAAAA,EAAWnC,KAAAA,CAAME;AAAG;KAClF,CAAA;AACF,EAAA;;EAGA,MAAMqC,UAAAA,CAAWD,OAAAA,EAAiBrI,IAAAA,EAAiB+F,KAAAA,EAA8C;AAC/F,IAAA,MAAMzB,KAAAA,GAAQ,MAAM,IAAA,CAAKpB,MAAAA,CAAOsD,SAAAA,CAAU;MAAEvB,KAAAA,EAAO;QAAEgB,EAAAA,EAAIoC,OAAAA;AAASnH,QAAAA,YAAAA,EAAc,IAAA,CAAKA;AAAa;KAAE,CAAA;AACpG,IAAA,IAAI,CAACoD,KAAAA,IAASA,KAAAA,CAAMY,SAAAA,QAAiBlD,QAAAA,EAAAA;AACrC,IAAA,MAAM,IAAA,CAAK4D,aAAaG,KAAAA,CAAME,EAAAA,EAAI3B,MAAMV,UAAAA,EAAYhE,SAAAA,CAAUoE,SAAS,QAAA,CAAA;AACvE,IAAA,OAAO,IAAA,CAAKd,OAAOwD,MAAAA,CAAO;MAAEzB,KAAAA,EAAO;QAAEgB,EAAAA,EAAIoC;AAAQ,OAAA;MAAG1B,IAAAA,EAAM;AAAE3G,QAAAA;AAAK;KAAE,CAAA;AACrE,EAAA;;;;;AAOA,EAAA,MAAMuI,eAAe3E,UAAAA,EAAiD;AACpE,IAAA,OAAO,IAAA,CAAKV,OAAO8B,QAAAA,CAAS;MAC1BC,KAAAA,EAAO;AACL/D,QAAAA,YAAAA,EAAc,IAAA,CAAKA,YAAAA;AACnB0C,QAAAA,UAAAA;QACAsB,SAAAA,EAAW,IAAA;QACX1D,MAAAA,EAAQ;UAAE2D,EAAAA,EAAI;YAACtF,WAAAA,CAAY4G,OAAAA;YAAS5G,WAAAA,CAAY8B;;AAAU;AAC5D,OAAA;MACA6G,OAAAA,EAAS;QAAEC,SAAAA,EAAW;AAAO;KAC/B,CAAA;AACF,EAAA;;EAGA,MAAMC,kBAAAA,CACJ/E,SACAgF,IAAAA,EAC6B;AAC7B,IAAA,OAAO,IAAA,CAAKzF,OAAO8B,QAAAA,CAAS;MAC1BC,KAAAA,EAAO;AACL,QAAA,GAAI0D,MAAMzH,YAAAA,GAAe;AAAEA,UAAAA,YAAAA,EAAcyH,IAAAA,CAAKzH;AAAa,SAAA,GAAI,EAAC;QAChE0D,aAAAA,EAAejB,OAAAA;QACfuB,SAAAA,EAAW,IAAA;AACX1D,QAAAA,MAAAA,EAAQ3B,WAAAA,CAAY8B,QAAAA;QACpByD,EAAAA,EAAI;AAAC,UAAA;YAAEE,SAAAA,EAAW;AAAK,WAAA;AAAG,UAAA;YAAEA,SAAAA,EAAW;AAAEC,cAAAA,EAAAA,sBAAQC,IAAAA;AAAO;AAAE;;AAC5D,OAAA;MACAgD,OAAAA,EAAS;QAAEd,UAAAA,EAAY;AAAO,OAAA;AAC9BkB,MAAAA,IAAAA,EAAMD,IAAAA,EAAMC,IAAAA;AACZC,MAAAA,IAAAA,EAAMF,IAAAA,EAAME;KACd,CAAA;AACF,EAAA;;;;;AAMA,EAAA,MAAMC,0BAA0BnF,OAAAA,EAAoC;AAClE,IAAA,MAAMoF,MAAAA,GAAS,MAAM,IAAA,CAAK7F,MAAAA,CAAO8B,QAAAA,CAAS;MACxCC,KAAAA,EAAO;AACL/D,QAAAA,YAAAA,EAAc,IAAA,CAAKA,YAAAA;QACnB0D,aAAAA,EAAejB,OAAAA;QACfuB,SAAAA,EAAW,IAAA;AACX1D,QAAAA,MAAAA,EAAQ3B,WAAAA,CAAY8B,QAAAA;AACpBsC,QAAAA,UAAAA,EAAYtE,eAAAA,CAAgBgF,iBAAAA;QAC5BS,EAAAA,EAAI;AAAC,UAAA;YAAEE,SAAAA,EAAW;AAAK,WAAA;AAAG,UAAA;YAAEA,SAAAA,EAAW;AAAEC,cAAAA,EAAAA,sBAAQC,IAAAA;AAAO;AAAE;;AAC5D;KACF,CAAA;AACA,IAAA,OAAOwD,KAAAA,CAAMC,IAAAA,CAAK,IAAIC,GAAAA,CAAIH,MAAAA,CAAOI,GAAAA,CAAI,CAACC,CAAAA,KAAMA,CAAAA,CAAExF,UAAU,CAAA,CAAA,CAAA;AAC1D,EAAA;;AAGA,EAAA,MAAMyF,qBAAAA,GAA2C;AAC/C,IAAA,MAAMN,MAAAA,GAAS,MAAM,IAAA,CAAK7F,MAAAA,CAAO8B,QAAAA,CAAS;MACxCC,KAAAA,EAAO;AACL/D,QAAAA,YAAAA,EAAc,IAAA,CAAKA,YAAAA;QACnBgE,SAAAA,EAAW,IAAA;QACX1D,MAAAA,EAAQ;UAAE2D,EAAAA,EAAI;AAAIzD,YAAAA,GAAAA;;AAAiB,SAAA;AACnCuC,QAAAA,UAAAA,EAAYtE,eAAAA,CAAgB8E,WAAAA;QAC5BW,EAAAA,EAAI;AAAC,UAAA;YAAEE,SAAAA,EAAW;AAAK,WAAA;AAAG,UAAA;YAAEA,SAAAA,EAAW;AAAEC,cAAAA,EAAAA,sBAAQC,IAAAA;AAAO;AAAE;;AAC5D;KACF,CAAA;AACA,IAAA,OAAOwD,KAAAA,CAAMC,IAAAA,CAAK,IAAIC,GAAAA,CAAIH,MAAAA,CAAOI,GAAAA,CAAI,CAACC,CAAAA,KAAMA,CAAAA,CAAExF,UAAU,CAAA,CAAA,CAAA;AAC1D,EAAA;;AAGA,EAAA,MAAM0F,YAAYjB,OAAAA,EAAgC;AAChD,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAKnF,OAAOwD,MAAAA,CAAO;QACvBzB,KAAAA,EAAO;UAAEgB,EAAAA,EAAIoC;AAAQ,SAAA;QACrB1B,IAAAA,EAAM;AAAE4C,UAAAA,YAAAA,sBAAkB/D,IAAAA,EAAAA;UAAQgE,WAAAA,EAAa;YAAEC,SAAAA,EAAW;AAAE;AAAE;OAClE,CAAA;AACF,IAAA,CAAA,CAAA,OAAS5E,GAAAA,EAAK;AACZC,MAAAA,MAAAA,CAAO4E,MAAM,mCAAA,EAAqC;AAAErB,QAAAA,OAAAA;AAASxD,QAAAA;OAAI,CAAA;AACnE,IAAA;AACF,EAAA;;;;AAMA,EAAA,MAAcuC,kBAAkBP,KAAAA,EAAiD;AAC/E,IAAA,IAAI,CAACA,OAAO,OAAO,IAAA;AACnB,IAAA,MAAMvC,KAAAA,GAAQ,MAAM,IAAA,CAAKpB,MAAAA,CAAOsD,SAAAA,CAAU;MAAEvB,KAAAA,EAAO;AAAE4B,QAAAA,KAAAA;QAAO3B,SAAAA,EAAW;AAAK;KAAE,CAAA;AAC9E,IAAA,IAAI,CAACZ,OAAO,OAAO,IAAA;AACnB,IAAA,IAAIA,KAAAA,CAAM9C,MAAAA,KAAW3B,WAAAA,CAAYmI,OAAAA,EAAS,OAAO,IAAA;AACjD,IAAA,IAAI1D,KAAAA,CAAMgB,aAAahB,KAAAA,CAAMgB,SAAAA,CAAUqE,SAAO,IAAMnE,IAAAA,CAAK+B,GAAAA,EAAG,EAAI,OAAO,IAAA;AACvE,IAAA,OAAOjD,KAAAA;AACT,EAAA;EAEA,MAAc0C,cAAAA,CAAejB,KAAAA,EAAmBzB,KAAAA,EAAyBsF,YAAAA,EAAqC;AAC5G,IAAA,IAAI,CAACtF,MAAMuC,KAAAA,EAAO;AAClB,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAKzD,KAAKyG,cAAAA,CAAe;AAC7BC,QAAAA,cAAAA,EAAgBxF,KAAAA,CAAM6B,YAAAA;AACtB4D,QAAAA,eAAAA,EAAiBzF,KAAAA,CAAMM,aAAAA;AACvB1D,QAAAA,YAAAA,EAAc,IAAA,CAAKA,YAAAA;AACnB0I,QAAAA,YAAAA;AACA5J,QAAAA,IAAAA,EAAMsE,KAAAA,CAAMtE,IAAAA;AACZgK,QAAAA,SAAAA,EAAW,IAAA,CAAK5G,IAAAA,CAAK6G,cAAAA,CAAe3F,KAAAA,CAAMuC,KAAK,CAAA;AAC/C5E,QAAAA,OAAAA,EAASqC,KAAAA,CAAMrC,OAAAA;AACfiI,QAAAA,UAAAA,EAAYnE,MAAMkB,IAAAA,IAAQ,IAAA;AAC1BkD,QAAAA,cAAAA,EAAgB7F,KAAAA,CAAM2B;OACxB,CAAA;AACF,IAAA,CAAA,CAAA,OAASpB,GAAAA,EAAK;AAEZC,MAAAA,MAAAA,CAAOC,KAAK,wDAAA,EAA0D;AACpEsD,QAAAA,OAAAA,EAAS/D,KAAAA,CAAM2B,EAAAA;AACf/E,QAAAA,YAAAA,EAAc,IAAA,CAAKA,YAAAA;AACnB2D,QAAAA;OACF,CAAA;AACF,IAAA;AACF,EAAA;AACF;;;ACreO,IAAMuF,yBAAAA,GAA4B;AAGlC,IAAMC,oBAAAA,GAA+C;EAC1DxJ,OAAAA,EAAS,kBAAA;EACTyJ,IAAAA,EAAM,MAAA;EACNxJ,QAAAA,EAAU,UAAA;EACVyJ,IAAAA,EAAM,MAAA;EACNC,QAAAA,EAAU,WAAA;EACVC,SAAAA,EAAW,YAAA;EACXC,eAAAA,EAAiB,kBAAA;EACjBC,MAAAA,EAAQ,QAAA;EACRC,MAAAA,EAAQ,QAAA;EACR7J,IAAAA,EAAM,MAAA;EACNC,MAAAA,EAAQ,QAAA;EACR6J,YAAAA,EAAc,cAAA;EACdC,OAAAA,EAAS,SAAA;EACTC,SAAAA,EAAW,WAAA;EACXC,QAAAA,EAAU,UAAA;EACVC,IAAAA,EAAM;AACR;AAEO,SAASC,kBAAkBhK,YAAAA,EAAoB;AACpD,EAAA,OAAOmJ,oBAAAA,CAAqBnJ,YAAAA,CAAAA,IAAiBA,YAAAA;AAC/C;AAFgBgK,MAAAA,CAAAA,iBAAAA,EAAAA,mBAAAA,CAAAA;AAIhB,IAAMC,WAAAA,GAAyC;EAC7C,CAACvL,SAAAA,CAAU6D,MAAM,GAAG,QAAA;EACpB,CAAC7D,SAAAA,CAAUwL,SAAS,GAAG,WAAA;EACvB,CAACxL,SAAAA,CAAUyL,MAAM,GAAG,QAAA;EACpB,CAACzL,SAAAA,CAAUoE,OAAO,GAAG;AACvB,CAAA;AAEO,SAASsH,UAAUtL,IAAAA,EAAe;AACvC,EAAA,OAAOmL,YAAYnL,IAAAA,CAAAA;AACrB;AAFgBsL,MAAAA,CAAAA,SAAAA,EAAAA,WAAAA,CAAAA;AAKT,SAASC,yBAAyBC,IAAAA,EAAwB;AAC/D,EAAA,OAAO;AACLtB,IAAAA,UAAAA,EAAYsB,KAAKtB,UAAAA,IAAc,YAAA;IAC/BhJ,YAAAA,EAAcgK,iBAAAA,CAAkBM,KAAKtK,YAAY,CAAA;AACjD0I,IAAAA,YAAAA,EAAc4B,IAAAA,CAAK5B,YAAAA;IACnB0B,SAAAA,EAAWA,SAAAA,CAAUE,KAAKxL,IAAI,CAAA;AAC9BgK,IAAAA,SAAAA,EAAWwB,IAAAA,CAAKxB,SAAAA;AAChB/H,IAAAA,OAAAA,EAASuJ,KAAKvJ,OAAAA,IAAW;AAC3B,GAAA;AACF;AATgBsJ,MAAAA,CAAAA,wBAAAA,EAAAA,0BAAAA,CAAAA;AA4BT,SAASE,mBAAmBC,QAAAA,EAA4B;AAC7D,EAAA,OAAO,OAAOF,IAAAA,KAAAA;AACZ,IAAA,MAAMG,YAAiD,EAAC;AACxD,IAAA,IAAIH,IAAAA,CAAK1B,cAAAA,EAAgB6B,SAAAA,CAAUzF,KAAAA,GAAQsF,IAAAA,CAAK1B,cAAAA;AAChD,IAAA,IAAI0B,IAAAA,CAAKzB,eAAAA,EAAiB4B,SAAAA,CAAUC,MAAAA,GAASJ,IAAAA,CAAKzB,eAAAA;AAClD,IAAA,IAAI,CAAC4B,SAAAA,CAAUzF,KAAAA,IAAS,CAACyF,UAAUC,MAAAA,EAAQ;AACzC9G,MAAAA,MAAAA,CAAOC,KAAK,iDAAA,EAAmD;AAAEoF,QAAAA,cAAAA,EAAgBqB,IAAAA,CAAKrB;OAAe,CAAA;AACrG,MAAA;AACF,IAAA;AACArF,IAAAA,MAAAA,CAAO+G,KAAK,sCAAA,EAAwC;MAClDC,YAAAA,EAAc1B,yBAAAA;AACdlJ,MAAAA,YAAAA,EAAcsK,IAAAA,CAAKtK,YAAAA;AACnBiJ,MAAAA,cAAAA,EAAgBqB,IAAAA,CAAKrB;KACvB,CAAA;AACA,IAAA,MAAMuB,SAASK,gBAAAA,CAAiB;MAC9BD,YAAAA,EAAc1B,yBAAAA;AACd4B,MAAAA,SAAAA,EAAWT,yBAAyBC,IAAAA,CAAAA;AACpCG,MAAAA;KACF,CAAA;AACF,EAAA,CAAA;AACF;AApBgBF,MAAAA,CAAAA,kBAAAA,EAAAA,oBAAAA,CAAAA;;;AChET,IAAMQ,eAAAA;;AAAgC,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgHtC,SAASC,sBAAAA,CAAuBC,QAAgBC,YAAAA,EAAoB;AACzE,EAAA;;AAAqB,IAAA;;SAEdD,MAAAA,CAAAA;wCAC+BC,YAAAA,CAAAA;UAC9BD,MAAAA,CAAAA;wCAC8BC,YAAAA,CAAAA;UAC9BD,MAAAA,CAAAA;wCAC8BC,YAAAA,CAAAA;UAC9BD,MAAAA,CAAAA;wCAC8BC,YAAAA,CAAAA;UAC9BD,MAAAA,CAAAA;wCAC8BC,YAAAA,CAAAA;;;;AAGxC;AAfgBF,MAAAA,CAAAA,sBAAAA,EAAAA,wBAAAA,CAAAA;;;ACnHT,IAAMG,kBAAAA,GAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmE3B,IAAMC,8BAAAA,GAAiC","file":"chunk-XD5ZK727.js","sourcesContent":["/**\n * @burdenoff/be-sdk/sharing\n *\n * Generic, Google-Docs-style sharing for any entity: invite → email → explicit\n * accept → enforced permission, plus shared-with-vibe / public-link / private\n * modes. Ship the `ShareGrant` table per service (see {@link SHARE_GRANT_PRISMA})\n * and drive everything through {@link ShareService}.\n */\n\nexport {\n ShareVisibility,\n ShareRole,\n ShareStatus,\n ROLE_ORDER,\n ROLE_CAPABILITIES,\n RESOURCE_CAPABILITY_MAP,\n roleAtLeast,\n maxRole,\n capabilitiesFor,\n roleToLegacy,\n legacyToRole,\n normalizeStatus,\n type ShareCapabilities,\n type ShareGrantRecord,\n type ShareGrantDelegate,\n type ResourceMeta,\n type SendShareEmailArgs,\n type ShareServiceDeps,\n type ShareServiceOptions,\n type ShareActor,\n type CreateUserShareInput,\n type CreateLinkShareInput,\n type AccessVia,\n type AccessResult,\n} from './types.js';\n\nexport { ShareService, type ShareServiceConfig } from './share-service.js';\n\nexport {\n SHARE_EMAIL_TEMPLATE_SLUG,\n RESOURCE_TYPE_LABELS,\n resourceTypeLabel,\n roleLabel,\n buildShareEmailVariables,\n makeSendShareEmail,\n type ShareEmailNotifier,\n} from './email.js';\n\nexport { SHARE_GRANT_SDL, buildPerEntityShareSdl } from './sdl.js';\n\nexport { SHARE_GRANT_PRISMA, SHARE_GRANT_PARTIAL_UNIQUE_SQL } from './prisma-fragment.js';\n","/**\n * Generic Sharing — canonical domain types\n *\n * One sharing model for every entity across the platform (sessions, vibes,\n * vibedecks, files, folders, notes, …). Each service pastes the `ShareGrant`\n * Prisma model (see `prisma-fragment.ts`) into its own schema and drives all\n * share/accept/permission logic through `ShareService` (see `share-service.ts`).\n *\n * The module owns ZERO database tables — three services keep three Postgres DBs,\n * so it talks to whatever Prisma client the host generates via the structural\n * {@link ShareGrantDelegate} type and never imports a concrete `@prisma/client`.\n *\n * @example\n * ```ts\n * import { ShareService, ShareRole, ShareVisibility } from '@burdenoff/be-sdk/sharing';\n * ```\n */\n\n// ---------------------------------------------------------------------------\n// Canonical enums (string values are stable across all services)\n// ---------------------------------------------------------------------------\n\n/** Who can reach a shared resource. */\nexport enum ShareVisibility {\n /** Only the creator/owner. */\n PRIVATE = 'PRIVATE',\n /** Specific people, by email invite + EXPLICIT accept (no access before accept). */\n SHARED_WITH_USERS = 'SHARED_WITH_USERS',\n /** Everyone who has access to the parent Vibe. */\n SHARED_WITH_VIBE = 'SHARED_WITH_VIBE',\n /** Anyone with the link. */\n PUBLIC_LINK = 'PUBLIC_LINK',\n}\n\n/**\n * The canonical permission ladder (ordinal: VIEWER < COMMENTER < EDITOR < MANAGER).\n * Mapped to per-entity verbs via {@link RESOURCE_CAPABILITY_MAP}.\n */\nexport enum ShareRole {\n /** Read only. */\n VIEWER = 'VIEWER',\n /** Read + comment. */\n COMMENTER = 'COMMENTER',\n /** Read + edit/run (session INTERACT, vibedeck EXECUTE, file EDIT). */\n EDITOR = 'EDITOR',\n /** Edit + re-share + revoke. */\n MANAGER = 'MANAGER',\n}\n\n/** Lifecycle of a share grant. */\nexport enum ShareStatus {\n /** Invited; recipient has NOT accepted — grants NO access. */\n PENDING = 'PENDING',\n /** Accepted (or immediately-active for public links) — grants access. */\n ACCEPTED = 'ACCEPTED',\n /** Manually revoked. */\n REVOKED = 'REVOKED',\n /** Past its expiry. */\n EXPIRED = 'EXPIRED',\n}\n\n/** Ordinal rank used for `>=` role comparisons. */\nexport const ROLE_ORDER: Record<ShareRole, number> = {\n [ShareRole.VIEWER]: 0,\n [ShareRole.COMMENTER]: 1,\n [ShareRole.EDITOR]: 2,\n [ShareRole.MANAGER]: 3,\n};\n\n/** True when `role` is at least as powerful as `required`. */\nexport function roleAtLeast(role: ShareRole, required: ShareRole): boolean {\n return ROLE_ORDER[role] >= ROLE_ORDER[required];\n}\n\n/** Returns the more powerful of two roles. */\nexport function maxRole(a: ShareRole, b: ShareRole): ShareRole {\n return ROLE_ORDER[a] >= ROLE_ORDER[b] ? a : b;\n}\n\n// ---------------------------------------------------------------------------\n// Capabilities\n// ---------------------------------------------------------------------------\n\nexport interface ShareCapabilities {\n canView: boolean;\n canComment: boolean;\n canEdit: boolean;\n canManage: boolean;\n /** EDITOR+ may run/execute (session INTERACT, vibedeck EXECUTE). */\n canExecute: boolean;\n}\n\nexport const ROLE_CAPABILITIES: Record<ShareRole, ShareCapabilities> = {\n [ShareRole.VIEWER]: { canView: true, canComment: false, canEdit: false, canManage: false, canExecute: false },\n [ShareRole.COMMENTER]: { canView: true, canComment: true, canEdit: false, canManage: false, canExecute: false },\n [ShareRole.EDITOR]: { canView: true, canComment: true, canEdit: true, canManage: false, canExecute: true },\n [ShareRole.MANAGER]: { canView: true, canComment: true, canEdit: true, canManage: true, canExecute: true },\n};\n\n/** Resolve the capability set for a role. */\nexport function capabilitiesFor(role: ShareRole): ShareCapabilities {\n return ROLE_CAPABILITIES[role];\n}\n\n/**\n * Per-entity translation of the canonical role to the entity's legacy permission\n * verb, for resolvers/data that still speak the old vocabulary. Unmapped\n * (resourceType, role) pairs fall back to the role name itself.\n */\nexport const RESOURCE_CAPABILITY_MAP: Record<string, Partial<Record<ShareRole, string>>> = {\n session: {\n [ShareRole.VIEWER]: 'VIEW',\n [ShareRole.COMMENTER]: 'VIEW',\n [ShareRole.EDITOR]: 'INTERACT',\n [ShareRole.MANAGER]: 'INTERACT',\n },\n vibedeck: {\n [ShareRole.VIEWER]: 'VIEW',\n [ShareRole.COMMENTER]: 'VIEW',\n [ShareRole.EDITOR]: 'EXECUTE',\n [ShareRole.MANAGER]: 'EXECUTE',\n },\n file: {\n [ShareRole.VIEWER]: 'VIEW',\n [ShareRole.COMMENTER]: 'COMMENT',\n [ShareRole.EDITOR]: 'EDIT',\n [ShareRole.MANAGER]: 'EDIT',\n },\n folder: {\n [ShareRole.VIEWER]: 'VIEW',\n [ShareRole.COMMENTER]: 'COMMENT',\n [ShareRole.EDITOR]: 'EDIT',\n [ShareRole.MANAGER]: 'EDIT',\n },\n};\n\n/** Map a canonical role to a resource's legacy permission verb. */\nexport function roleToLegacy(resourceType: string, role: ShareRole): string {\n return RESOURCE_CAPABILITY_MAP[resourceType]?.[role] ?? role;\n}\n\n/**\n * Map a legacy permission verb back to the canonical role for backfills.\n * Unknown verbs default to VIEWER (least privilege).\n */\nexport function legacyToRole(resourceType: string, legacy: string): ShareRole {\n const table = RESOURCE_CAPABILITY_MAP[resourceType];\n if (table) {\n // Ascending so a verb shared by two roles maps to the MINIMAL (least-privilege)\n // role — e.g. session INTERACT (EDITOR & MANAGER both map to it) ⇒ EDITOR.\n for (const role of [ShareRole.VIEWER, ShareRole.COMMENTER, ShareRole.EDITOR, ShareRole.MANAGER]) {\n if (table[role] === legacy) return role;\n }\n }\n switch (legacy.toUpperCase()) {\n case 'MANAGER':\n case 'OWNER':\n case 'ADMIN':\n return ShareRole.MANAGER;\n case 'EDITOR':\n case 'EDIT':\n case 'INTERACT':\n case 'EXECUTE':\n case 'WRITE':\n return ShareRole.EDITOR;\n case 'COMMENTER':\n case 'COMMENT':\n return ShareRole.COMMENTER;\n default:\n return ShareRole.VIEWER;\n }\n}\n\n/**\n * Normalize a legacy status string onto the canonical ladder. Older share tables\n * used `ACTIVE`; the canonical model uses `ACCEPTED`. Everything else maps 1:1.\n */\nexport function normalizeStatus(status: string): ShareStatus {\n const upper = status.toUpperCase();\n if (upper === 'ACTIVE') return ShareStatus.ACCEPTED;\n if (upper in ShareStatus) return upper as ShareStatus;\n return ShareStatus.PENDING;\n}\n\n// ---------------------------------------------------------------------------\n// Persisted record shape (mirrors SHARE_GRANT_PRISMA)\n// ---------------------------------------------------------------------------\n\nexport interface ShareGrantRecord {\n id: string;\n workspaceId: string;\n resourceType: string;\n resourceId: string;\n granteeUserId: string | null;\n granteeEmail: string | null;\n role: ShareRole;\n visibility: ShareVisibility;\n status: ShareStatus;\n token: string | null;\n expiresAt: Date | null;\n message: string | null;\n createdBy: string;\n onBehalfOf: string;\n acceptedAt: Date | null;\n acceptedBy: string | null;\n revokedAt: Date | null;\n revokedBy: string | null;\n lastAccessAt: Date | null;\n accessCount: number;\n context: unknown;\n createdAt: Date;\n updatedAt: Date;\n deletedAt: Date | null;\n}\n\n/**\n * Structural subset of a Prisma model delegate that {@link ShareService} needs.\n * Host services pass `prisma.shareGrant` here (cast with `as unknown as\n * ShareGrantDelegate` if their generated overloads don't line up structurally).\n * be-sdk never imports a concrete Prisma client.\n */\nexport interface ShareGrantDelegate {\n findFirst(args: { where: Record<string, unknown>; orderBy?: unknown }): Promise<ShareGrantRecord | null>;\n findMany(args: {\n where: Record<string, unknown>;\n orderBy?: unknown;\n take?: number;\n skip?: number;\n }): Promise<ShareGrantRecord[]>;\n create(args: { data: Record<string, unknown> }): Promise<ShareGrantRecord>;\n update(args: { where: Record<string, unknown>; data: Record<string, unknown> }): Promise<ShareGrantRecord>;\n updateMany(args: { where: Record<string, unknown>; data: Record<string, unknown> }): Promise<{ count: number }>;\n count(args: { where: Record<string, unknown> }): Promise<number>;\n}\n\n// ---------------------------------------------------------------------------\n// Host-supplied dependency seams\n// ---------------------------------------------------------------------------\n\n/** Metadata about the resource a grant points at, resolved by the host service. */\nexport interface ResourceMeta {\n /** The owner/creator actor id (always treated as MANAGER). */\n ownerId: string;\n /** Parent vibe id, when the resource is vibe-linked (enables SHARED_WITH_VIBE). */\n vibeId: string | null;\n /** The resource's own visibility flag. */\n visibility: ShareVisibility;\n /** Human-friendly name used in the share email. */\n name: string;\n}\n\nexport interface SendShareEmailArgs {\n recipientEmail: string | null;\n recipientUserId: string | null;\n resourceType: string;\n resourceName: string;\n role: ShareRole;\n acceptUrl: string;\n message: string | null;\n sharerName: string | null;\n /** Dedupe key (the grant id) so re-sends don't duplicate emails. */\n idempotencyKey: string;\n}\n\n/**\n * Host-specific seams injected into {@link ShareService}. All async functions must\n * fail-closed semantics where noted: `canAccess` treats a thrown `loadResourceMeta`\n * / `hasVibeAccess` as DENY.\n */\nexport interface ShareServiceDeps {\n /** Resolve an email to a user id, or null if no such user exists (fail-soft). */\n resolveUserByEmail(email: string): Promise<string | null>;\n /**\n * True/false if the user is/ isn't an active workspace member; null if the\n * lookup failed (caller decides — share-create denies only on explicit false).\n */\n isWorkspaceMember(userId: string, workspaceId: string): Promise<boolean | null>;\n /** True if the actor has access to the given vibe (owner / accepted grant / member). */\n hasVibeAccess(actorId: string, vibeId: string, workspaceId: string): Promise<boolean>;\n /** Load resource metadata; return null if the resource doesn't exist. */\n loadResourceMeta(resourceId: string): Promise<ResourceMeta | null>;\n /** Fire-and-forget share email; failures must not roll back the grant. */\n sendShareEmail(args: SendShareEmailArgs): Promise<void>;\n /** Build the public accept URL for a token (frontend owns the base route). */\n buildAcceptUrl(token: string): string;\n}\n\nexport interface ShareServiceOptions {\n /** Baseline role granted by SHARED_WITH_VIBE access. Defaults to VIEWER. */\n sharedWithVibeRole?: ShareRole;\n /**\n * When true (default), sharing with a user who resolves to a NON-member of the\n * workspace is rejected. Emails that don't resolve to any user are always\n * allowed (external invite — access still gated on accept).\n */\n requireWorkspaceMember?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Method inputs / results\n// ---------------------------------------------------------------------------\n\nexport interface ShareActor {\n id: string;\n email?: string | null;\n name?: string | null;\n}\n\nexport interface CreateUserShareInput {\n resourceId: string;\n granteeEmail: string;\n role: ShareRole;\n message?: string | null;\n expiresAt?: Date | null;\n}\n\nexport interface CreateLinkShareInput {\n resourceId: string;\n role: ShareRole;\n expiresAt?: Date | null;\n}\n\nexport type AccessVia = 'owner' | 'public_link' | 'vibe' | 'user_grant' | 'none';\n\nexport interface AccessResult {\n allowed: boolean;\n effectiveRole: ShareRole | null;\n via: AccessVia;\n}\n","/**\n * ShareService — generic, framework-agnostic share/accept/permission engine.\n *\n * Construct one per request, bound to a single resourceType:\n * ```ts\n * const svc = new ShareService({\n * prisma: ctx.prisma.shareGrant as unknown as ShareGrantDelegate,\n * resourceType: 'session',\n * workspaceId: ctx.workspace.id,\n * deps: { ... },\n * });\n * ```\n *\n * The security-critical primitive is {@link ShareService.canAccess}: it is\n * default-DENY, ignores PENDING grants (no access before accept), and fails\n * CLOSED on any thrown dependency.\n */\n\nimport { randomBytes } from 'node:crypto';\n\nimport { GraphQLError } from 'graphql';\n\nimport { logger } from '../logger/index.js';\nimport {\n ShareRole,\n ShareStatus,\n ShareVisibility,\n maxRole,\n roleAtLeast,\n type AccessResult,\n type CreateLinkShareInput,\n type CreateUserShareInput,\n type ShareActor,\n type ShareGrantDelegate,\n type ShareGrantRecord,\n type ShareServiceDeps,\n type ShareServiceOptions,\n} from './types.js';\n\n// The ShareGrant table's enum is PENDING/ACCEPTED/REVOKED/EXPIRED — there is no\n// 'ACTIVE' member. Including the legacy 'ACTIVE' literal here made every\n// `status: { in: [...] }` grant lookup throw PrismaClientValidationError, which\n// resolveAccess swallows and fail-closes — silently breaking ALL accepted-grant\n// access. Legacy 'ACTIVE' rows (if any) are normalized to ACCEPTED on read via\n// normalizeStatus(); the active-status filter is exactly ACCEPTED.\nconst ACTIVE_STATUSES = [ShareStatus.ACCEPTED] as const;\n\nconst DENY: AccessResult = { allowed: false, effectiveRole: null, via: 'none' };\n\nfunction notFound(message = 'Not found'): GraphQLError {\n return new GraphQLError(message, { extensions: { code: 'NOT_FOUND' } });\n}\nfunction forbidden(message = 'Forbidden'): GraphQLError {\n return new GraphQLError(message, { extensions: { code: 'FORBIDDEN' } });\n}\nfunction badRequest(message: string): GraphQLError {\n return new GraphQLError(message, { extensions: { code: 'BAD_REQUEST' } });\n}\n\nfunction generateToken(): string {\n // 32 bytes hex = 64 chars, matches token VarChar(64) column.\n return randomBytes(32).toString('hex');\n}\n\nfunction emailsMatch(a: string | null | undefined, b: string | null | undefined): boolean {\n return !!a && !!b && a.trim().toLowerCase() === b.trim().toLowerCase();\n}\n\ninterface RoleCandidate {\n role: ShareRole;\n via: AccessResult['via'];\n}\n\n/** Highest-role candidate, or null when there are none. */\nfunction pickHighestRole(candidates: RoleCandidate[]): RoleCandidate | null {\n let best: RoleCandidate | null = null;\n for (const c of candidates) {\n if (!best || (maxRole(best.role, c.role) === c.role && c.role !== best.role)) best = c;\n }\n return best;\n}\n\nexport interface ShareServiceConfig {\n prisma: ShareGrantDelegate;\n resourceType: string;\n workspaceId: string;\n deps: ShareServiceDeps;\n options?: ShareServiceOptions;\n}\n\nexport class ShareService {\n private readonly prisma: ShareGrantDelegate;\n private readonly resourceType: string;\n private readonly workspaceId: string;\n private readonly deps: ShareServiceDeps;\n private readonly sharedWithVibeRole: ShareRole;\n private readonly requireWorkspaceMember: boolean;\n\n constructor(config: ShareServiceConfig) {\n this.prisma = config.prisma;\n this.resourceType = config.resourceType;\n this.workspaceId = config.workspaceId;\n this.deps = config.deps;\n this.sharedWithVibeRole = config.options?.sharedWithVibeRole ?? ShareRole.VIEWER;\n this.requireWorkspaceMember = config.options?.requireWorkspaceMember ?? true;\n }\n\n // -------------------------------------------------------------------------\n // Access decisions\n // -------------------------------------------------------------------------\n\n /**\n * Resolve the EFFECTIVE access of `actorId` on `resourceId`.\n *\n * Default-DENY. Considers (highest wins): owner ⇒ MANAGER, an active\n * PUBLIC_LINK grant ⇒ its role, SHARED_WITH_VIBE + hasVibeAccess ⇒ baseline,\n * an ACCEPTED (never PENDING) non-expired SHARED_WITH_USERS grant ⇒ its role.\n * Fails CLOSED if a dependency throws.\n */\n async resolveAccess(actorId: string, resourceId: string): Promise<AccessResult> {\n try {\n const meta = await this.deps.loadResourceMeta(resourceId);\n if (!meta) return DENY;\n\n // Owner is always MANAGER.\n if (actorId && meta.ownerId === actorId) {\n return { allowed: true, effectiveRole: ShareRole.MANAGER, via: 'owner' };\n }\n\n const candidates: RoleCandidate[] = [];\n\n // SHARED_WITH_VIBE: everyone with parent-vibe access.\n if (meta.visibility === ShareVisibility.SHARED_WITH_VIBE && meta.vibeId && actorId) {\n if (await this.deps.hasVibeAccess(actorId, meta.vibeId, this.workspaceId)) {\n candidates.push({ role: this.sharedWithVibeRole, via: 'vibe' });\n }\n }\n\n // Grant-based: active PUBLIC_LINK (anyone) or an ACCEPTED user grant (this actor).\n for (const grant of await this.queryActiveAccessGrants(actorId, resourceId)) {\n const isPublic = grant.visibility === ShareVisibility.PUBLIC_LINK;\n const isMyUserGrant = grant.visibility === ShareVisibility.SHARED_WITH_USERS && grant.granteeUserId === actorId;\n if (isPublic) candidates.push({ role: grant.role, via: 'public_link' });\n else if (isMyUserGrant) candidates.push({ role: grant.role, via: 'user_grant' });\n }\n\n const best = pickHighestRole(candidates);\n if (!best) return DENY;\n return { allowed: true, effectiveRole: best.role, via: best.via };\n } catch (err) {\n // Fail CLOSED — never expose a resource because a dependency errored.\n logger.warn('[ShareService] resolveAccess failed; denying', {\n resourceType: this.resourceType,\n resourceId,\n err,\n });\n return DENY;\n }\n }\n\n /** Active (non-expired) PUBLIC_LINK grants + this actor's SHARED_WITH_USERS grants. */\n private async queryActiveAccessGrants(actorId: string, resourceId: string): Promise<ShareGrantRecord[]> {\n return this.prisma.findMany({\n where: {\n resourceType: this.resourceType,\n resourceId,\n deletedAt: null,\n status: { in: [...ACTIVE_STATUSES] },\n OR: [\n { visibility: ShareVisibility.PUBLIC_LINK },\n ...(actorId ? [{ granteeUserId: actorId, visibility: ShareVisibility.SHARED_WITH_USERS }] : []),\n ],\n AND: [{ OR: [{ expiresAt: null }, { expiresAt: { gt: new Date() } }] }],\n },\n });\n }\n\n /** True if `actorId` may act on `resourceId` at >= `requiredRole`. */\n async canAccess(actorId: string, resourceId: string, requiredRole: ShareRole): Promise<boolean> {\n const result = await this.resolveAccess(actorId, resourceId);\n return result.allowed && result.effectiveRole !== null && roleAtLeast(result.effectiveRole, requiredRole);\n }\n\n /** Assert >= requiredRole; throws NOT_FOUND (read) / FORBIDDEN (mutate) otherwise. */\n async assertAccess(\n actorId: string,\n resourceId: string,\n requiredRole: ShareRole,\n mode: 'read' | 'mutate' = 'read'\n ): Promise<void> {\n if (await this.canAccess(actorId, resourceId, requiredRole)) return;\n // Reads must not leak existence → NOT_FOUND; mutations → FORBIDDEN.\n throw mode === 'read' ? notFound() : forbidden('You do not have permission to perform this action');\n }\n\n // -------------------------------------------------------------------------\n // Share creation\n // -------------------------------------------------------------------------\n\n /** Invite a specific person by email (PENDING + token + email). */\n async createUserShare(actor: ShareActor, input: CreateUserShareInput): Promise<ShareGrantRecord> {\n const meta = await this.deps.loadResourceMeta(input.resourceId);\n if (!meta) throw notFound('Resource not found');\n\n // Only owner/MANAGER may share.\n await this.assertAccess(actor.id, input.resourceId, ShareRole.MANAGER, 'mutate');\n\n const email = input.granteeEmail.trim().toLowerCase();\n if (!email) throw badRequest('A recipient email is required');\n\n const granteeUserId = await this.deps.resolveUserByEmail(email);\n\n if (granteeUserId && granteeUserId === actor.id) {\n throw badRequest('You cannot share a resource with yourself');\n }\n\n // Workspace-member guard: deny only on an explicit non-member (null = lookup\n // failed → allow, fail-open on transient errors; access still gated on accept).\n if (granteeUserId && this.requireWorkspaceMember) {\n const isMember = await this.deps.isWorkspaceMember(granteeUserId, this.workspaceId);\n if (isMember === false) {\n throw forbidden('You can only share with members of this workspace');\n }\n }\n\n // Idempotent: reuse an existing active grant for the same recipient.\n const existing = await this.prisma.findFirst({\n where: {\n resourceType: this.resourceType,\n resourceId: input.resourceId,\n deletedAt: null,\n status: { in: [ShareStatus.PENDING, ShareStatus.ACCEPTED] },\n OR: [...(granteeUserId ? [{ granteeUserId }] : []), { granteeEmail: email }],\n },\n });\n\n let grant: ShareGrantRecord;\n if (existing) {\n grant = await this.prisma.update({\n where: { id: existing.id },\n data: {\n role: input.role,\n message: input.message ?? null,\n expiresAt: input.expiresAt ?? null,\n ...(granteeUserId && !existing.granteeUserId ? { granteeUserId } : {}),\n },\n });\n } else {\n grant = await this.prisma.create({\n data: {\n workspaceId: this.workspaceId,\n resourceType: this.resourceType,\n resourceId: input.resourceId,\n granteeUserId: granteeUserId ?? null,\n granteeEmail: email,\n role: input.role,\n visibility: ShareVisibility.SHARED_WITH_USERS,\n status: ShareStatus.PENDING,\n token: generateToken(),\n expiresAt: input.expiresAt ?? null,\n message: input.message ?? null,\n createdBy: actor.id,\n onBehalfOf: actor.id,\n },\n });\n }\n\n await this.fireShareEmail(actor, grant, meta.name);\n return grant;\n }\n\n /** Create an immediately-active public link (anyone with the URL). */\n async createLinkShare(actor: ShareActor, input: CreateLinkShareInput): Promise<ShareGrantRecord> {\n const meta = await this.deps.loadResourceMeta(input.resourceId);\n if (!meta) throw notFound('Resource not found');\n await this.assertAccess(actor.id, input.resourceId, ShareRole.MANAGER, 'mutate');\n\n return this.prisma.create({\n data: {\n workspaceId: this.workspaceId,\n resourceType: this.resourceType,\n resourceId: input.resourceId,\n granteeUserId: null,\n granteeEmail: null,\n role: input.role,\n visibility: ShareVisibility.PUBLIC_LINK,\n status: ShareStatus.ACCEPTED, // links are active on creation\n token: generateToken(),\n expiresAt: input.expiresAt ?? null,\n message: null,\n createdBy: actor.id,\n onBehalfOf: actor.id,\n },\n });\n }\n\n // -------------------------------------------------------------------------\n // Accept / decline\n // -------------------------------------------------------------------------\n\n /** Explicitly accept a SHARED_WITH_USERS invite. Idempotent. */\n async acceptShare(token: string, actor: ShareActor): Promise<ShareGrantRecord> {\n const grant = await this.findActiveByToken(token);\n if (!grant) throw notFound('This share link is invalid or has expired');\n\n if (grant.visibility === ShareVisibility.PUBLIC_LINK) {\n // Nothing to accept for a public link.\n return grant;\n }\n\n const idMatches = !!grant.granteeUserId && grant.granteeUserId === actor.id;\n const emailMatches = emailsMatch(grant.granteeEmail, actor.email);\n if (!idMatches && !emailMatches) {\n throw forbidden('This invitation was sent to a different account');\n }\n\n if (grant.status === ShareStatus.ACCEPTED) {\n // Idempotent — backfill granteeUserId if it was an email-only invite.\n if (!grant.granteeUserId) {\n return this.prisma.update({ where: { id: grant.id }, data: { granteeUserId: actor.id } });\n }\n return grant;\n }\n\n const now = new Date();\n const res = await this.prisma.updateMany({\n where: { id: grant.id, status: ShareStatus.PENDING },\n data: { status: ShareStatus.ACCEPTED, acceptedAt: now, acceptedBy: actor.id, granteeUserId: actor.id },\n });\n if (res.count === 0) {\n // Lost a race or already terminal — return current state.\n const fresh = await this.prisma.findFirst({ where: { id: grant.id } });\n if (fresh) return fresh;\n }\n const updated = await this.prisma.findFirst({ where: { id: grant.id } });\n if (!updated) throw notFound();\n return updated;\n }\n\n /** Decline an invite (marks it REVOKED). */\n async declineShare(token: string, actor: ShareActor): Promise<boolean> {\n const grant = await this.findActiveByToken(token);\n if (!grant) return false;\n const idMatches = !!grant.granteeUserId && grant.granteeUserId === actor.id;\n const emailMatches = emailsMatch(grant.granteeEmail, actor.email);\n if (!idMatches && !emailMatches) throw forbidden('This invitation was sent to a different account');\n await this.prisma.update({\n where: { id: grant.id },\n data: { status: ShareStatus.REVOKED, revokedAt: new Date(), revokedBy: actor.id },\n });\n return true;\n }\n\n /** Public preview of a grant by token (safe fields only — never the resource body). */\n async shareGrantByToken(token: string): Promise<ShareGrantRecord | null> {\n return this.findActiveByToken(token);\n }\n\n // -------------------------------------------------------------------------\n // Management\n // -------------------------------------------------------------------------\n\n /** Revoke a grant or link. Owner/MANAGER only. */\n async revoke(grantId: string, actor: ShareActor): Promise<ShareGrantRecord> {\n const grant = await this.prisma.findFirst({ where: { id: grantId, resourceType: this.resourceType } });\n if (!grant || grant.deletedAt) throw notFound();\n await this.assertAccess(actor.id, grant.resourceId, ShareRole.MANAGER, 'mutate');\n return this.prisma.update({\n where: { id: grantId },\n data: { status: ShareStatus.REVOKED, revokedAt: new Date(), revokedBy: actor.id },\n });\n }\n\n /** Change the role on a grant. Owner/MANAGER only. */\n async updateRole(grantId: string, role: ShareRole, actor: ShareActor): Promise<ShareGrantRecord> {\n const grant = await this.prisma.findFirst({ where: { id: grantId, resourceType: this.resourceType } });\n if (!grant || grant.deletedAt) throw notFound();\n await this.assertAccess(actor.id, grant.resourceId, ShareRole.MANAGER, 'mutate');\n return this.prisma.update({ where: { id: grantId }, data: { role } });\n }\n\n // -------------------------------------------------------------------------\n // Reads\n // -------------------------------------------------------------------------\n\n /** All active grants on a resource (caller must be owner/MANAGER — gate in resolver). */\n async resourceShares(resourceId: string): Promise<ShareGrantRecord[]> {\n return this.prisma.findMany({\n where: {\n resourceType: this.resourceType,\n resourceId,\n deletedAt: null,\n status: { in: [ShareStatus.PENDING, ShareStatus.ACCEPTED] },\n },\n orderBy: { createdAt: 'desc' },\n });\n }\n\n /** Grants where the actor is the (accepted-or-pending) grantee. */\n async sharesSharedWithMe(\n actorId: string,\n opts?: { resourceType?: string; take?: number; skip?: number }\n ): Promise<ShareGrantRecord[]> {\n return this.prisma.findMany({\n where: {\n ...(opts?.resourceType ? { resourceType: opts.resourceType } : {}),\n granteeUserId: actorId,\n deletedAt: null,\n status: ShareStatus.ACCEPTED,\n OR: [{ expiresAt: null }, { expiresAt: { gt: new Date() } }],\n },\n orderBy: { acceptedAt: 'desc' },\n take: opts?.take,\n skip: opts?.skip,\n });\n }\n\n /**\n * Resource ids the actor can see via an ACCEPTED user grant — for narrowing\n * list resolvers (`WHERE id IN (...)`).\n */\n async listAccessibleResourceIds(actorId: string): Promise<string[]> {\n const grants = await this.prisma.findMany({\n where: {\n resourceType: this.resourceType,\n granteeUserId: actorId,\n deletedAt: null,\n status: ShareStatus.ACCEPTED,\n visibility: ShareVisibility.SHARED_WITH_USERS,\n OR: [{ expiresAt: null }, { expiresAt: { gt: new Date() } }],\n },\n });\n return Array.from(new Set(grants.map((g) => g.resourceId)));\n }\n\n /** Resource ids with an active public link — for list narrowing. */\n async listPublicResourceIds(): Promise<string[]> {\n const grants = await this.prisma.findMany({\n where: {\n resourceType: this.resourceType,\n deletedAt: null,\n status: { in: [...ACTIVE_STATUSES] },\n visibility: ShareVisibility.PUBLIC_LINK,\n OR: [{ expiresAt: null }, { expiresAt: { gt: new Date() } }],\n },\n });\n return Array.from(new Set(grants.map((g) => g.resourceId)));\n }\n\n /** Increment access analytics (best-effort). */\n async touchAccess(grantId: string): Promise<void> {\n try {\n await this.prisma.update({\n where: { id: grantId },\n data: { lastAccessAt: new Date(), accessCount: { increment: 1 } },\n });\n } catch (err) {\n logger.debug('[ShareService] touchAccess failed', { grantId, err });\n }\n }\n\n // -------------------------------------------------------------------------\n // Internals\n // -------------------------------------------------------------------------\n\n private async findActiveByToken(token: string): Promise<ShareGrantRecord | null> {\n if (!token) return null;\n const grant = await this.prisma.findFirst({ where: { token, deletedAt: null } });\n if (!grant) return null;\n if (grant.status === ShareStatus.REVOKED) return null;\n if (grant.expiresAt && grant.expiresAt.getTime() <= Date.now()) return null;\n return grant;\n }\n\n private async fireShareEmail(actor: ShareActor, grant: ShareGrantRecord, resourceName: string): Promise<void> {\n if (!grant.token) return;\n try {\n await this.deps.sendShareEmail({\n recipientEmail: grant.granteeEmail,\n recipientUserId: grant.granteeUserId,\n resourceType: this.resourceType,\n resourceName,\n role: grant.role,\n acceptUrl: this.deps.buildAcceptUrl(grant.token),\n message: grant.message,\n sharerName: actor.name ?? null,\n idempotencyKey: grant.id,\n });\n } catch (err) {\n // Email is best-effort — the grant is the source of truth.\n logger.warn('[ShareService] share email failed; grant still created', {\n grantId: grant.id,\n resourceType: this.resourceType,\n err,\n });\n }\n }\n}\n","/**\n * Share-email helpers.\n *\n * The `resource-shared` template must be registered in global-notification-svc.\n * Services wire `ShareServiceDeps.sendShareEmail` via {@link makeSendShareEmail},\n * passing an object that speaks `sendWithTemplate` (e.g. `sdk.tenantNotifications`).\n */\n\nimport { logger } from '../logger/index.js';\nimport { ShareRole, type SendShareEmailArgs } from './types.js';\n\n/** notification-svc template slug for \"X shared <entity> with you\" emails. */\nexport const SHARE_EMAIL_TEMPLATE_SLUG = 'resource-shared';\n\n/** Human-friendly labels per resourceType for the email body. */\nexport const RESOURCE_TYPE_LABELS: Record<string, string> = {\n session: 'terminal session',\n vibe: 'Vibe',\n vibedeck: 'VibeDeck',\n note: 'note',\n aiprompt: 'AI prompt',\n aicontext: 'AI context',\n instructionfile: 'instruction file',\n tunnel: 'tunnel',\n action: 'action',\n file: 'file',\n folder: 'folder',\n conversation: 'conversation',\n catalog: 'catalog',\n component: 'component',\n template: 'template',\n docs: 'docs site',\n};\n\nexport function resourceTypeLabel(resourceType: string): string {\n return RESOURCE_TYPE_LABELS[resourceType] ?? resourceType;\n}\n\nconst ROLE_LABELS: Record<ShareRole, string> = {\n [ShareRole.VIEWER]: 'Viewer',\n [ShareRole.COMMENTER]: 'Commenter',\n [ShareRole.EDITOR]: 'Editor',\n [ShareRole.MANAGER]: 'Manager',\n};\n\nexport function roleLabel(role: ShareRole): string {\n return ROLE_LABELS[role];\n}\n\n/** Build the variable bag the `resource-shared` template renders. */\nexport function buildShareEmailVariables(args: SendShareEmailArgs): Record<string, unknown> {\n return {\n sharerName: args.sharerName ?? 'A teammate',\n resourceType: resourceTypeLabel(args.resourceType),\n resourceName: args.resourceName,\n roleLabel: roleLabel(args.role),\n acceptUrl: args.acceptUrl,\n message: args.message ?? '',\n };\n}\n\n/**\n * Minimal structural view of a notifications module that can send a templated\n * email. `sdk.tenantNotifications` satisfies this. platform defaults to EMAIL\n * inside the module, so it isn't part of this contract.\n */\nexport interface ShareEmailNotifier {\n sendWithTemplate(input: {\n templateSlug: string;\n variables: Record<string, unknown>;\n recipient: { email?: string; userId?: string; name?: string };\n }): Promise<string>;\n}\n\n/**\n * Build a `ShareServiceDeps.sendShareEmail` implementation backed by a\n * notifications module. Skips (no-throw) when there's no addressable recipient.\n */\nexport function makeSendShareEmail(notifier: ShareEmailNotifier): (args: SendShareEmailArgs) => Promise<void> {\n return async (args: SendShareEmailArgs): Promise<void> => {\n const recipient: { email?: string; userId?: string } = {};\n if (args.recipientEmail) recipient.email = args.recipientEmail;\n if (args.recipientUserId) recipient.userId = args.recipientUserId;\n if (!recipient.email && !recipient.userId) {\n logger.warn('[ShareEmail] no addressable recipient; skipping', { idempotencyKey: args.idempotencyKey });\n return;\n }\n logger.info('[ShareEmail] Sending resource-shared', {\n templateSlug: SHARE_EMAIL_TEMPLATE_SLUG,\n resourceType: args.resourceType,\n idempotencyKey: args.idempotencyKey,\n });\n await notifier.sendWithTemplate({\n templateSlug: SHARE_EMAIL_TEMPLATE_SLUG,\n variables: buildShareEmailVariables(args),\n recipient,\n });\n };\n}\n","/**\n * Reusable GraphQL SDL for the generic sharing feature.\n *\n * {@link SHARE_GRANT_SDL} carries the shared types/enums/inputs + the uniform\n * token/self fields and is declared ONCE per subgraph (in a `shared` module).\n * {@link buildPerEntityShareSdl} generates the thin per-entity wrappers that\n * each carry a STATIC `@rbac` directive (the gateway requires a literal\n * action/resource per field — a single generic `shareResource` field cannot be\n * RBAC-protected correctly).\n *\n * Both reference `@rbac` / `@key`, which the host subgraph already declares via\n * its federation/`@link` setup. DateTime is assumed available (be-sdk graphql).\n */\n\nexport const SHARE_GRANT_SDL = /* GraphQL */ `\n enum ShareRole {\n VIEWER\n COMMENTER\n EDITOR\n MANAGER\n }\n\n enum ShareGrantVisibility {\n PRIVATE\n SHARED_WITH_USERS\n SHARED_WITH_VIBE\n PUBLIC_LINK\n }\n\n enum ShareGrantStatus {\n PENDING\n ACCEPTED\n REVOKED\n EXPIRED\n }\n\n type ShareCapabilities {\n canView: Boolean!\n canComment: Boolean!\n canEdit: Boolean!\n canManage: Boolean!\n canExecute: Boolean!\n }\n\n type ShareGrant @key(fields: \"id\") {\n id: ID!\n resourceType: String!\n resourceId: ID!\n granteeUserId: ID\n granteeEmail: String\n role: ShareRole!\n visibility: ShareGrantVisibility!\n status: ShareGrantStatus!\n expiresAt: DateTime\n message: String\n createdBy: ID!\n acceptedAt: DateTime\n createdAt: DateTime!\n \"Public accept/link URL (present for invites and public links).\"\n shareUrl: String\n \"Capabilities implied by this grant's role.\"\n capabilities: ShareCapabilities!\n }\n\n type ShareGrantList {\n items: [ShareGrant!]!\n total: Int!\n }\n\n \"Safe, pre-login preview of a share invitation.\"\n type ShareGrantPreview {\n id: ID!\n resourceType: String!\n resourceName: String\n role: ShareRole!\n visibility: ShareGrantVisibility!\n status: ShareGrantStatus!\n sharerName: String\n expiresAt: DateTime\n }\n\n input ShareEntityInput {\n resourceId: ID!\n email: String!\n role: ShareRole!\n message: String\n expiresAt: DateTime\n }\n\n input UpdateShareRoleInput {\n resourceId: ID!\n shareId: ID!\n role: ShareRole!\n }\n\n input RevokeShareInput {\n resourceId: ID!\n shareId: ID!\n }\n\n input CreateShareLinkInput {\n resourceId: ID!\n role: ShareRole!\n expiresAt: DateTime\n }\n\n extend type Query {\n \"Pre-login preview of a share invite by token.\"\n shareGrantByToken(token: String!): ShareGrantPreview @rbac(public: true)\n \"Grants where the current user is the accepted grantee.\"\n sharesSharedWithMe(resourceType: String, pagination: PaginationInput): ShareGrantList! @rbac(scopeType: \"self\")\n }\n\n extend type Mutation {\n \"Accept a share invitation (recipient identified by the opaque token + email/id).\"\n acceptShare(token: String!): ShareGrant! @rbac(public: true)\n \"Decline a share invitation.\"\n declineShare(token: String!): Boolean! @rbac(public: true)\n }\n`;\n\n/**\n * Per-entity wrapper SDL. `entity` is the GraphQL-safe PascalCase name used in\n * the field name (e.g. `Session` → `shareSession`); `rbacResource` is the\n * resource string the gateway checks (e.g. `session`, `ai-prompt`).\n */\nexport function buildPerEntityShareSdl(entity: string, rbacResource: string): string {\n return /* GraphQL */ `\nextend type Mutation {\n share${entity}(input: ShareEntityInput!): ShareGrant!\n @rbac(action: \"share\", resource: \"${rbacResource}\", resourceIdArg: \"input.resourceId\", scopeType: \"wspace\")\n revoke${entity}Share(input: RevokeShareInput!): ShareGrant!\n @rbac(action: \"share\", resource: \"${rbacResource}\", resourceIdArg: \"input.resourceId\", scopeType: \"wspace\")\n update${entity}ShareRole(input: UpdateShareRoleInput!): ShareGrant!\n @rbac(action: \"share\", resource: \"${rbacResource}\", resourceIdArg: \"input.resourceId\", scopeType: \"wspace\")\n create${entity}ShareLink(input: CreateShareLinkInput!): ShareGrant!\n @rbac(action: \"share\", resource: \"${rbacResource}\", resourceIdArg: \"input.resourceId\", scopeType: \"wspace\")\n revoke${entity}ShareLink(input: RevokeShareInput!): ShareGrant!\n @rbac(action: \"share\", resource: \"${rbacResource}\", resourceIdArg: \"input.resourceId\", scopeType: \"wspace\")\n}\n`;\n}\n","/**\n * Canonical `ShareGrant` Prisma model + indexes, shipped as a copy-paste string.\n *\n * Each service pastes {@link SHARE_GRANT_PRISMA} into its own `prisma/schema/`\n * and runs `gendb`. Enum names are deliberately `ShareRole` /\n * `ShareGrantVisibility` / `ShareGrantStatus` so they never collide with the\n * legacy per-service `ShareStatus` / `VibeVisibility` enums. The Prisma FIELD\n * names stay camelCase (what {@link ShareService} reads/writes); `@map` keeps the\n * DB columns snake_case so {@link SHARE_GRANT_PARTIAL_UNIQUE_SQL} reads cleanly.\n */\n\nexport const SHARE_GRANT_PRISMA = `\nenum ShareRole {\n VIEWER\n COMMENTER\n EDITOR\n MANAGER\n}\n\nenum ShareGrantVisibility {\n PRIVATE\n SHARED_WITH_USERS\n SHARED_WITH_VIBE\n PUBLIC_LINK\n}\n\nenum ShareGrantStatus {\n PENDING\n ACCEPTED\n REVOKED\n EXPIRED\n}\n\n/// Generic resource share grant. \\`resourceType\\` discriminates the entity; one\n/// row per (resource, recipient) or per public link. See @burdenoff/be-sdk/sharing.\nmodel ShareGrant {\n id String @id @default(uuid())\n workspaceId String @map(\"workspace_id\") @db.VarChar(255)\n resourceType String @map(\"resource_type\") @db.VarChar(64)\n resourceId String @map(\"resource_id\") @db.VarChar(255)\n granteeUserId String? @map(\"grantee_user_id\") @db.VarChar(255)\n granteeEmail String? @map(\"grantee_email\") @db.VarChar(320)\n role ShareRole @default(VIEWER)\n visibility ShareGrantVisibility @default(SHARED_WITH_USERS)\n status ShareGrantStatus @default(PENDING)\n token String? @unique @db.VarChar(64)\n expiresAt DateTime? @map(\"expires_at\")\n message String? @db.Text\n createdBy String @map(\"created_by\") @db.VarChar(255)\n onBehalfOf String @map(\"on_behalf_of\") @db.VarChar(255)\n acceptedAt DateTime? @map(\"accepted_at\")\n acceptedBy String? @map(\"accepted_by\") @db.VarChar(255)\n revokedAt DateTime? @map(\"revoked_at\")\n revokedBy String? @map(\"revoked_by\") @db.VarChar(255)\n lastAccessAt DateTime? @map(\"last_access_at\")\n accessCount Int @default(0) @map(\"access_count\")\n context Json?\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n deletedAt DateTime? @map(\"deleted_at\")\n\n @@index([workspaceId])\n @@index([resourceType, resourceId])\n @@index([granteeUserId])\n @@index([granteeEmail])\n @@index([status])\n @@index([expiresAt])\n @@index([resourceType, resourceId, status])\n @@map(\"share_grants\")\n}\n`;\n\n/**\n * Partial-unique index that Prisma's `@@unique` cannot express (it has no WHERE\n * predicate). Add this as a raw SQL step in the same migration that creates the\n * table. The table is brand new, so a plain (non-CONCURRENT) create is safe and\n * transaction-friendly.\n */\nexport const SHARE_GRANT_PARTIAL_UNIQUE_SQL = `\nCREATE UNIQUE INDEX IF NOT EXISTS share_grants_active_user_uq\n ON share_grants (resource_type, resource_id, grantee_user_id)\n WHERE status IN ('PENDING', 'ACCEPTED') AND deleted_at IS NULL AND grantee_user_id IS NOT NULL;\n`;\n"]}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { prisma_exports as Prisma } from './chunk-54BMP5OJ.js';
|
|
2
2
|
export { RESOURCE_CAP_DEFAULTS, ResourceCapExceededError, ResourceCapsModule, getResourceCaps } from './chunk-VDDOGIWY.js';
|
|
3
|
-
|
|
3
|
+
import './chunk-GTEMQXCA.js';
|
|
4
|
+
export { sharing_exports as Sharing } from './chunk-XD5ZK727.js';
|
|
4
5
|
export { TemporalClient, TemporalClientFactory, TemporalModule, TemporalWorker, TemporalWorkerFactory, TemporalWorkerManager } from './chunk-5SD7DU3L.js';
|
|
5
6
|
import { ActivityModule, UsageModule, TrackerModule } from './chunk-PPIDJP2W.js';
|
|
6
7
|
export { ActivityModule, TrackerModule, UsageModule } from './chunk-PPIDJP2W.js';
|
|
@@ -12,8 +13,7 @@ export { middleware_exports as Middleware } from './chunk-2HANKZZM.js';
|
|
|
12
13
|
import { TenantNotificationsModule, NotificationsModule } from './chunk-RMDKB5O7.js';
|
|
13
14
|
export { tenant_notifications_exports as Notifications, NotificationsModule } from './chunk-RMDKB5O7.js';
|
|
14
15
|
export { observability_exports as Observability } from './chunk-5LXDPGDH.js';
|
|
15
|
-
export {
|
|
16
|
-
import './chunk-GTEMQXCA.js';
|
|
16
|
+
export { platform_exports as Platform } from './chunk-PHKK7725.js';
|
|
17
17
|
export { export_exports as Export } from './chunk-SVONGBQR.js';
|
|
18
18
|
export { feature_flags_exports as FeatureFlags } from './chunk-VWCN5PMD.js';
|
|
19
19
|
import { GraphModule } from './chunk-TGTJ653K.js';
|
package/dist/sharing/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { RESOURCE_CAPABILITY_MAP, RESOURCE_TYPE_LABELS, ROLE_CAPABILITIES, ROLE_ORDER, SHARE_EMAIL_TEMPLATE_SLUG, SHARE_GRANT_PARTIAL_UNIQUE_SQL, SHARE_GRANT_PRISMA, SHARE_GRANT_SDL, ShareRole, ShareService, ShareStatus, ShareVisibility, buildPerEntityShareSdl, buildShareEmailVariables, capabilitiesFor, legacyToRole, makeSendShareEmail, maxRole, normalizeStatus, resourceTypeLabel, roleAtLeast, roleLabel, roleToLegacy } from '../chunk-
|
|
1
|
+
export { RESOURCE_CAPABILITY_MAP, RESOURCE_TYPE_LABELS, ROLE_CAPABILITIES, ROLE_ORDER, SHARE_EMAIL_TEMPLATE_SLUG, SHARE_GRANT_PARTIAL_UNIQUE_SQL, SHARE_GRANT_PRISMA, SHARE_GRANT_SDL, ShareRole, ShareService, ShareStatus, ShareVisibility, buildPerEntityShareSdl, buildShareEmailVariables, capabilitiesFor, legacyToRole, makeSendShareEmail, maxRole, normalizeStatus, resourceTypeLabel, roleAtLeast, roleLabel, roleToLegacy } from '../chunk-XD5ZK727.js';
|
|
2
2
|
import '../chunk-CBZNP6RF.js';
|
|
3
3
|
import '../chunk-XE4OXN2W.js';
|
|
4
4
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@burdenoff/be-sdk",
|
|
3
|
-
"version": "2026.601.
|
|
3
|
+
"version": "2026.601.2",
|
|
4
4
|
"description": "Backend SDK for Burdenoff products providing unified access to notifications, RBAC, activity tracking, usage monitoring, and more",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/sharing/index.ts","../src/sharing/types.ts","../src/sharing/share-service.ts","../src/sharing/email.ts","../src/sharing/sdl.ts","../src/sharing/prisma-fragment.ts"],"names":["ShareVisibility","ShareRole","ShareStatus","ROLE_ORDER","roleAtLeast","role","required","maxRole","a","b","ROLE_CAPABILITIES","canView","canComment","canEdit","canManage","canExecute","capabilitiesFor","RESOURCE_CAPABILITY_MAP","session","vibedeck","file","folder","roleToLegacy","resourceType","legacyToRole","legacy","table","toUpperCase","normalizeStatus","status","upper","ACTIVE_STATUSES","ACCEPTED","DENY","allowed","effectiveRole","via","notFound","message","GraphQLError","extensions","code","forbidden","badRequest","generateToken","randomBytes","toString","emailsMatch","trim","toLowerCase","pickHighestRole","candidates","best","c","ShareService","prisma","workspaceId","deps","sharedWithVibeRole","requireWorkspaceMember","config","options","VIEWER","resolveAccess","actorId","resourceId","meta","loadResourceMeta","ownerId","MANAGER","visibility","SHARED_WITH_VIBE","vibeId","hasVibeAccess","push","grant","queryActiveAccessGrants","isPublic","PUBLIC_LINK","isMyUserGrant","SHARED_WITH_USERS","granteeUserId","err","logger","warn","findMany","where","deletedAt","in","OR","AND","expiresAt","gt","Date","canAccess","requiredRole","result","assertAccess","mode","createUserShare","actor","input","id","email","granteeEmail","resolveUserByEmail","isMember","isWorkspaceMember","existing","findFirst","PENDING","update","data","create","token","createdBy","onBehalfOf","fireShareEmail","name","createLinkShare","acceptShare","findActiveByToken","idMatches","emailMatches","now","res","updateMany","acceptedAt","acceptedBy","count","fresh","updated","declineShare","REVOKED","revokedAt","revokedBy","shareGrantByToken","revoke","grantId","updateRole","resourceShares","orderBy","createdAt","sharesSharedWithMe","opts","take","skip","listAccessibleResourceIds","grants","Array","from","Set","map","g","listPublicResourceIds","touchAccess","lastAccessAt","accessCount","increment","debug","getTime","resourceName","sendShareEmail","recipientEmail","recipientUserId","acceptUrl","buildAcceptUrl","sharerName","idempotencyKey","SHARE_EMAIL_TEMPLATE_SLUG","RESOURCE_TYPE_LABELS","vibe","note","aiprompt","aicontext","instructionfile","tunnel","action","conversation","catalog","component","template","docs","resourceTypeLabel","ROLE_LABELS","COMMENTER","EDITOR","roleLabel","buildShareEmailVariables","args","makeSendShareEmail","notifier","recipient","userId","info","templateSlug","sendWithTemplate","variables","SHARE_GRANT_SDL","buildPerEntityShareSdl","entity","rbacResource","SHARE_GRANT_PRISMA","SHARE_GRANT_PARTIAL_UNIQUE_SQL"],"mappings":"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","file":"chunk-DVAZQEOL.js","sourcesContent":["/**\n * @burdenoff/be-sdk/sharing\n *\n * Generic, Google-Docs-style sharing for any entity: invite → email → explicit\n * accept → enforced permission, plus shared-with-vibe / public-link / private\n * modes. Ship the `ShareGrant` table per service (see {@link SHARE_GRANT_PRISMA})\n * and drive everything through {@link ShareService}.\n */\n\nexport {\n ShareVisibility,\n ShareRole,\n ShareStatus,\n ROLE_ORDER,\n ROLE_CAPABILITIES,\n RESOURCE_CAPABILITY_MAP,\n roleAtLeast,\n maxRole,\n capabilitiesFor,\n roleToLegacy,\n legacyToRole,\n normalizeStatus,\n type ShareCapabilities,\n type ShareGrantRecord,\n type ShareGrantDelegate,\n type ResourceMeta,\n type SendShareEmailArgs,\n type ShareServiceDeps,\n type ShareServiceOptions,\n type ShareActor,\n type CreateUserShareInput,\n type CreateLinkShareInput,\n type AccessVia,\n type AccessResult,\n} from './types.js';\n\nexport { ShareService, type ShareServiceConfig } from './share-service.js';\n\nexport {\n SHARE_EMAIL_TEMPLATE_SLUG,\n RESOURCE_TYPE_LABELS,\n resourceTypeLabel,\n roleLabel,\n buildShareEmailVariables,\n makeSendShareEmail,\n type ShareEmailNotifier,\n} from './email.js';\n\nexport { SHARE_GRANT_SDL, buildPerEntityShareSdl } from './sdl.js';\n\nexport { SHARE_GRANT_PRISMA, SHARE_GRANT_PARTIAL_UNIQUE_SQL } from './prisma-fragment.js';\n","/**\n * Generic Sharing — canonical domain types\n *\n * One sharing model for every entity across the platform (sessions, vibes,\n * vibedecks, files, folders, notes, …). Each service pastes the `ShareGrant`\n * Prisma model (see `prisma-fragment.ts`) into its own schema and drives all\n * share/accept/permission logic through `ShareService` (see `share-service.ts`).\n *\n * The module owns ZERO database tables — three services keep three Postgres DBs,\n * so it talks to whatever Prisma client the host generates via the structural\n * {@link ShareGrantDelegate} type and never imports a concrete `@prisma/client`.\n *\n * @example\n * ```ts\n * import { ShareService, ShareRole, ShareVisibility } from '@burdenoff/be-sdk/sharing';\n * ```\n */\n\n// ---------------------------------------------------------------------------\n// Canonical enums (string values are stable across all services)\n// ---------------------------------------------------------------------------\n\n/** Who can reach a shared resource. */\nexport enum ShareVisibility {\n /** Only the creator/owner. */\n PRIVATE = 'PRIVATE',\n /** Specific people, by email invite + EXPLICIT accept (no access before accept). */\n SHARED_WITH_USERS = 'SHARED_WITH_USERS',\n /** Everyone who has access to the parent Vibe. */\n SHARED_WITH_VIBE = 'SHARED_WITH_VIBE',\n /** Anyone with the link. */\n PUBLIC_LINK = 'PUBLIC_LINK',\n}\n\n/**\n * The canonical permission ladder (ordinal: VIEWER < COMMENTER < EDITOR < MANAGER).\n * Mapped to per-entity verbs via {@link RESOURCE_CAPABILITY_MAP}.\n */\nexport enum ShareRole {\n /** Read only. */\n VIEWER = 'VIEWER',\n /** Read + comment. */\n COMMENTER = 'COMMENTER',\n /** Read + edit/run (session INTERACT, vibedeck EXECUTE, file EDIT). */\n EDITOR = 'EDITOR',\n /** Edit + re-share + revoke. */\n MANAGER = 'MANAGER',\n}\n\n/** Lifecycle of a share grant. */\nexport enum ShareStatus {\n /** Invited; recipient has NOT accepted — grants NO access. */\n PENDING = 'PENDING',\n /** Accepted (or immediately-active for public links) — grants access. */\n ACCEPTED = 'ACCEPTED',\n /** Manually revoked. */\n REVOKED = 'REVOKED',\n /** Past its expiry. */\n EXPIRED = 'EXPIRED',\n}\n\n/** Ordinal rank used for `>=` role comparisons. */\nexport const ROLE_ORDER: Record<ShareRole, number> = {\n [ShareRole.VIEWER]: 0,\n [ShareRole.COMMENTER]: 1,\n [ShareRole.EDITOR]: 2,\n [ShareRole.MANAGER]: 3,\n};\n\n/** True when `role` is at least as powerful as `required`. */\nexport function roleAtLeast(role: ShareRole, required: ShareRole): boolean {\n return ROLE_ORDER[role] >= ROLE_ORDER[required];\n}\n\n/** Returns the more powerful of two roles. */\nexport function maxRole(a: ShareRole, b: ShareRole): ShareRole {\n return ROLE_ORDER[a] >= ROLE_ORDER[b] ? a : b;\n}\n\n// ---------------------------------------------------------------------------\n// Capabilities\n// ---------------------------------------------------------------------------\n\nexport interface ShareCapabilities {\n canView: boolean;\n canComment: boolean;\n canEdit: boolean;\n canManage: boolean;\n /** EDITOR+ may run/execute (session INTERACT, vibedeck EXECUTE). */\n canExecute: boolean;\n}\n\nexport const ROLE_CAPABILITIES: Record<ShareRole, ShareCapabilities> = {\n [ShareRole.VIEWER]: { canView: true, canComment: false, canEdit: false, canManage: false, canExecute: false },\n [ShareRole.COMMENTER]: { canView: true, canComment: true, canEdit: false, canManage: false, canExecute: false },\n [ShareRole.EDITOR]: { canView: true, canComment: true, canEdit: true, canManage: false, canExecute: true },\n [ShareRole.MANAGER]: { canView: true, canComment: true, canEdit: true, canManage: true, canExecute: true },\n};\n\n/** Resolve the capability set for a role. */\nexport function capabilitiesFor(role: ShareRole): ShareCapabilities {\n return ROLE_CAPABILITIES[role];\n}\n\n/**\n * Per-entity translation of the canonical role to the entity's legacy permission\n * verb, for resolvers/data that still speak the old vocabulary. Unmapped\n * (resourceType, role) pairs fall back to the role name itself.\n */\nexport const RESOURCE_CAPABILITY_MAP: Record<string, Partial<Record<ShareRole, string>>> = {\n session: {\n [ShareRole.VIEWER]: 'VIEW',\n [ShareRole.COMMENTER]: 'VIEW',\n [ShareRole.EDITOR]: 'INTERACT',\n [ShareRole.MANAGER]: 'INTERACT',\n },\n vibedeck: {\n [ShareRole.VIEWER]: 'VIEW',\n [ShareRole.COMMENTER]: 'VIEW',\n [ShareRole.EDITOR]: 'EXECUTE',\n [ShareRole.MANAGER]: 'EXECUTE',\n },\n file: {\n [ShareRole.VIEWER]: 'VIEW',\n [ShareRole.COMMENTER]: 'COMMENT',\n [ShareRole.EDITOR]: 'EDIT',\n [ShareRole.MANAGER]: 'EDIT',\n },\n folder: {\n [ShareRole.VIEWER]: 'VIEW',\n [ShareRole.COMMENTER]: 'COMMENT',\n [ShareRole.EDITOR]: 'EDIT',\n [ShareRole.MANAGER]: 'EDIT',\n },\n};\n\n/** Map a canonical role to a resource's legacy permission verb. */\nexport function roleToLegacy(resourceType: string, role: ShareRole): string {\n return RESOURCE_CAPABILITY_MAP[resourceType]?.[role] ?? role;\n}\n\n/**\n * Map a legacy permission verb back to the canonical role for backfills.\n * Unknown verbs default to VIEWER (least privilege).\n */\nexport function legacyToRole(resourceType: string, legacy: string): ShareRole {\n const table = RESOURCE_CAPABILITY_MAP[resourceType];\n if (table) {\n // Ascending so a verb shared by two roles maps to the MINIMAL (least-privilege)\n // role — e.g. session INTERACT (EDITOR & MANAGER both map to it) ⇒ EDITOR.\n for (const role of [ShareRole.VIEWER, ShareRole.COMMENTER, ShareRole.EDITOR, ShareRole.MANAGER]) {\n if (table[role] === legacy) return role;\n }\n }\n switch (legacy.toUpperCase()) {\n case 'MANAGER':\n case 'OWNER':\n case 'ADMIN':\n return ShareRole.MANAGER;\n case 'EDITOR':\n case 'EDIT':\n case 'INTERACT':\n case 'EXECUTE':\n case 'WRITE':\n return ShareRole.EDITOR;\n case 'COMMENTER':\n case 'COMMENT':\n return ShareRole.COMMENTER;\n default:\n return ShareRole.VIEWER;\n }\n}\n\n/**\n * Normalize a legacy status string onto the canonical ladder. Older share tables\n * used `ACTIVE`; the canonical model uses `ACCEPTED`. Everything else maps 1:1.\n */\nexport function normalizeStatus(status: string): ShareStatus {\n const upper = status.toUpperCase();\n if (upper === 'ACTIVE') return ShareStatus.ACCEPTED;\n if (upper in ShareStatus) return upper as ShareStatus;\n return ShareStatus.PENDING;\n}\n\n// ---------------------------------------------------------------------------\n// Persisted record shape (mirrors SHARE_GRANT_PRISMA)\n// ---------------------------------------------------------------------------\n\nexport interface ShareGrantRecord {\n id: string;\n workspaceId: string;\n resourceType: string;\n resourceId: string;\n granteeUserId: string | null;\n granteeEmail: string | null;\n role: ShareRole;\n visibility: ShareVisibility;\n status: ShareStatus;\n token: string | null;\n expiresAt: Date | null;\n message: string | null;\n createdBy: string;\n onBehalfOf: string;\n acceptedAt: Date | null;\n acceptedBy: string | null;\n revokedAt: Date | null;\n revokedBy: string | null;\n lastAccessAt: Date | null;\n accessCount: number;\n context: unknown;\n createdAt: Date;\n updatedAt: Date;\n deletedAt: Date | null;\n}\n\n/**\n * Structural subset of a Prisma model delegate that {@link ShareService} needs.\n * Host services pass `prisma.shareGrant` here (cast with `as unknown as\n * ShareGrantDelegate` if their generated overloads don't line up structurally).\n * be-sdk never imports a concrete Prisma client.\n */\nexport interface ShareGrantDelegate {\n findFirst(args: { where: Record<string, unknown>; orderBy?: unknown }): Promise<ShareGrantRecord | null>;\n findMany(args: {\n where: Record<string, unknown>;\n orderBy?: unknown;\n take?: number;\n skip?: number;\n }): Promise<ShareGrantRecord[]>;\n create(args: { data: Record<string, unknown> }): Promise<ShareGrantRecord>;\n update(args: { where: Record<string, unknown>; data: Record<string, unknown> }): Promise<ShareGrantRecord>;\n updateMany(args: { where: Record<string, unknown>; data: Record<string, unknown> }): Promise<{ count: number }>;\n count(args: { where: Record<string, unknown> }): Promise<number>;\n}\n\n// ---------------------------------------------------------------------------\n// Host-supplied dependency seams\n// ---------------------------------------------------------------------------\n\n/** Metadata about the resource a grant points at, resolved by the host service. */\nexport interface ResourceMeta {\n /** The owner/creator actor id (always treated as MANAGER). */\n ownerId: string;\n /** Parent vibe id, when the resource is vibe-linked (enables SHARED_WITH_VIBE). */\n vibeId: string | null;\n /** The resource's own visibility flag. */\n visibility: ShareVisibility;\n /** Human-friendly name used in the share email. */\n name: string;\n}\n\nexport interface SendShareEmailArgs {\n recipientEmail: string | null;\n recipientUserId: string | null;\n resourceType: string;\n resourceName: string;\n role: ShareRole;\n acceptUrl: string;\n message: string | null;\n sharerName: string | null;\n /** Dedupe key (the grant id) so re-sends don't duplicate emails. */\n idempotencyKey: string;\n}\n\n/**\n * Host-specific seams injected into {@link ShareService}. All async functions must\n * fail-closed semantics where noted: `canAccess` treats a thrown `loadResourceMeta`\n * / `hasVibeAccess` as DENY.\n */\nexport interface ShareServiceDeps {\n /** Resolve an email to a user id, or null if no such user exists (fail-soft). */\n resolveUserByEmail(email: string): Promise<string | null>;\n /**\n * True/false if the user is/ isn't an active workspace member; null if the\n * lookup failed (caller decides — share-create denies only on explicit false).\n */\n isWorkspaceMember(userId: string, workspaceId: string): Promise<boolean | null>;\n /** True if the actor has access to the given vibe (owner / accepted grant / member). */\n hasVibeAccess(actorId: string, vibeId: string, workspaceId: string): Promise<boolean>;\n /** Load resource metadata; return null if the resource doesn't exist. */\n loadResourceMeta(resourceId: string): Promise<ResourceMeta | null>;\n /** Fire-and-forget share email; failures must not roll back the grant. */\n sendShareEmail(args: SendShareEmailArgs): Promise<void>;\n /** Build the public accept URL for a token (frontend owns the base route). */\n buildAcceptUrl(token: string): string;\n}\n\nexport interface ShareServiceOptions {\n /** Baseline role granted by SHARED_WITH_VIBE access. Defaults to VIEWER. */\n sharedWithVibeRole?: ShareRole;\n /**\n * When true (default), sharing with a user who resolves to a NON-member of the\n * workspace is rejected. Emails that don't resolve to any user are always\n * allowed (external invite — access still gated on accept).\n */\n requireWorkspaceMember?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Method inputs / results\n// ---------------------------------------------------------------------------\n\nexport interface ShareActor {\n id: string;\n email?: string | null;\n name?: string | null;\n}\n\nexport interface CreateUserShareInput {\n resourceId: string;\n granteeEmail: string;\n role: ShareRole;\n message?: string | null;\n expiresAt?: Date | null;\n}\n\nexport interface CreateLinkShareInput {\n resourceId: string;\n role: ShareRole;\n expiresAt?: Date | null;\n}\n\nexport type AccessVia = 'owner' | 'public_link' | 'vibe' | 'user_grant' | 'none';\n\nexport interface AccessResult {\n allowed: boolean;\n effectiveRole: ShareRole | null;\n via: AccessVia;\n}\n","/**\n * ShareService — generic, framework-agnostic share/accept/permission engine.\n *\n * Construct one per request, bound to a single resourceType:\n * ```ts\n * const svc = new ShareService({\n * prisma: ctx.prisma.shareGrant as unknown as ShareGrantDelegate,\n * resourceType: 'session',\n * workspaceId: ctx.workspace.id,\n * deps: { ... },\n * });\n * ```\n *\n * The security-critical primitive is {@link ShareService.canAccess}: it is\n * default-DENY, ignores PENDING grants (no access before accept), and fails\n * CLOSED on any thrown dependency.\n */\n\nimport { randomBytes } from 'node:crypto';\n\nimport { GraphQLError } from 'graphql';\n\nimport { logger } from '../logger/index.js';\nimport {\n ShareRole,\n ShareStatus,\n ShareVisibility,\n maxRole,\n roleAtLeast,\n type AccessResult,\n type CreateLinkShareInput,\n type CreateUserShareInput,\n type ShareActor,\n type ShareGrantDelegate,\n type ShareGrantRecord,\n type ShareServiceDeps,\n type ShareServiceOptions,\n} from './types.js';\n\nconst ACTIVE_STATUSES = [ShareStatus.ACCEPTED, 'ACTIVE'] as const;\n\nconst DENY: AccessResult = { allowed: false, effectiveRole: null, via: 'none' };\n\nfunction notFound(message = 'Not found'): GraphQLError {\n return new GraphQLError(message, { extensions: { code: 'NOT_FOUND' } });\n}\nfunction forbidden(message = 'Forbidden'): GraphQLError {\n return new GraphQLError(message, { extensions: { code: 'FORBIDDEN' } });\n}\nfunction badRequest(message: string): GraphQLError {\n return new GraphQLError(message, { extensions: { code: 'BAD_REQUEST' } });\n}\n\nfunction generateToken(): string {\n // 32 bytes hex = 64 chars, matches token VarChar(64) column.\n return randomBytes(32).toString('hex');\n}\n\nfunction emailsMatch(a: string | null | undefined, b: string | null | undefined): boolean {\n return !!a && !!b && a.trim().toLowerCase() === b.trim().toLowerCase();\n}\n\ninterface RoleCandidate {\n role: ShareRole;\n via: AccessResult['via'];\n}\n\n/** Highest-role candidate, or null when there are none. */\nfunction pickHighestRole(candidates: RoleCandidate[]): RoleCandidate | null {\n let best: RoleCandidate | null = null;\n for (const c of candidates) {\n if (!best || (maxRole(best.role, c.role) === c.role && c.role !== best.role)) best = c;\n }\n return best;\n}\n\nexport interface ShareServiceConfig {\n prisma: ShareGrantDelegate;\n resourceType: string;\n workspaceId: string;\n deps: ShareServiceDeps;\n options?: ShareServiceOptions;\n}\n\nexport class ShareService {\n private readonly prisma: ShareGrantDelegate;\n private readonly resourceType: string;\n private readonly workspaceId: string;\n private readonly deps: ShareServiceDeps;\n private readonly sharedWithVibeRole: ShareRole;\n private readonly requireWorkspaceMember: boolean;\n\n constructor(config: ShareServiceConfig) {\n this.prisma = config.prisma;\n this.resourceType = config.resourceType;\n this.workspaceId = config.workspaceId;\n this.deps = config.deps;\n this.sharedWithVibeRole = config.options?.sharedWithVibeRole ?? ShareRole.VIEWER;\n this.requireWorkspaceMember = config.options?.requireWorkspaceMember ?? true;\n }\n\n // -------------------------------------------------------------------------\n // Access decisions\n // -------------------------------------------------------------------------\n\n /**\n * Resolve the EFFECTIVE access of `actorId` on `resourceId`.\n *\n * Default-DENY. Considers (highest wins): owner ⇒ MANAGER, an active\n * PUBLIC_LINK grant ⇒ its role, SHARED_WITH_VIBE + hasVibeAccess ⇒ baseline,\n * an ACCEPTED (never PENDING) non-expired SHARED_WITH_USERS grant ⇒ its role.\n * Fails CLOSED if a dependency throws.\n */\n async resolveAccess(actorId: string, resourceId: string): Promise<AccessResult> {\n try {\n const meta = await this.deps.loadResourceMeta(resourceId);\n if (!meta) return DENY;\n\n // Owner is always MANAGER.\n if (actorId && meta.ownerId === actorId) {\n return { allowed: true, effectiveRole: ShareRole.MANAGER, via: 'owner' };\n }\n\n const candidates: RoleCandidate[] = [];\n\n // SHARED_WITH_VIBE: everyone with parent-vibe access.\n if (meta.visibility === ShareVisibility.SHARED_WITH_VIBE && meta.vibeId && actorId) {\n if (await this.deps.hasVibeAccess(actorId, meta.vibeId, this.workspaceId)) {\n candidates.push({ role: this.sharedWithVibeRole, via: 'vibe' });\n }\n }\n\n // Grant-based: active PUBLIC_LINK (anyone) or an ACCEPTED user grant (this actor).\n for (const grant of await this.queryActiveAccessGrants(actorId, resourceId)) {\n const isPublic = grant.visibility === ShareVisibility.PUBLIC_LINK;\n const isMyUserGrant = grant.visibility === ShareVisibility.SHARED_WITH_USERS && grant.granteeUserId === actorId;\n if (isPublic) candidates.push({ role: grant.role, via: 'public_link' });\n else if (isMyUserGrant) candidates.push({ role: grant.role, via: 'user_grant' });\n }\n\n const best = pickHighestRole(candidates);\n if (!best) return DENY;\n return { allowed: true, effectiveRole: best.role, via: best.via };\n } catch (err) {\n // Fail CLOSED — never expose a resource because a dependency errored.\n logger.warn('[ShareService] resolveAccess failed; denying', {\n resourceType: this.resourceType,\n resourceId,\n err,\n });\n return DENY;\n }\n }\n\n /** Active (non-expired) PUBLIC_LINK grants + this actor's SHARED_WITH_USERS grants. */\n private async queryActiveAccessGrants(actorId: string, resourceId: string): Promise<ShareGrantRecord[]> {\n return this.prisma.findMany({\n where: {\n resourceType: this.resourceType,\n resourceId,\n deletedAt: null,\n status: { in: [...ACTIVE_STATUSES] },\n OR: [\n { visibility: ShareVisibility.PUBLIC_LINK },\n ...(actorId ? [{ granteeUserId: actorId, visibility: ShareVisibility.SHARED_WITH_USERS }] : []),\n ],\n AND: [{ OR: [{ expiresAt: null }, { expiresAt: { gt: new Date() } }] }],\n },\n });\n }\n\n /** True if `actorId` may act on `resourceId` at >= `requiredRole`. */\n async canAccess(actorId: string, resourceId: string, requiredRole: ShareRole): Promise<boolean> {\n const result = await this.resolveAccess(actorId, resourceId);\n return result.allowed && result.effectiveRole !== null && roleAtLeast(result.effectiveRole, requiredRole);\n }\n\n /** Assert >= requiredRole; throws NOT_FOUND (read) / FORBIDDEN (mutate) otherwise. */\n async assertAccess(\n actorId: string,\n resourceId: string,\n requiredRole: ShareRole,\n mode: 'read' | 'mutate' = 'read'\n ): Promise<void> {\n if (await this.canAccess(actorId, resourceId, requiredRole)) return;\n // Reads must not leak existence → NOT_FOUND; mutations → FORBIDDEN.\n throw mode === 'read' ? notFound() : forbidden('You do not have permission to perform this action');\n }\n\n // -------------------------------------------------------------------------\n // Share creation\n // -------------------------------------------------------------------------\n\n /** Invite a specific person by email (PENDING + token + email). */\n async createUserShare(actor: ShareActor, input: CreateUserShareInput): Promise<ShareGrantRecord> {\n const meta = await this.deps.loadResourceMeta(input.resourceId);\n if (!meta) throw notFound('Resource not found');\n\n // Only owner/MANAGER may share.\n await this.assertAccess(actor.id, input.resourceId, ShareRole.MANAGER, 'mutate');\n\n const email = input.granteeEmail.trim().toLowerCase();\n if (!email) throw badRequest('A recipient email is required');\n\n const granteeUserId = await this.deps.resolveUserByEmail(email);\n\n if (granteeUserId && granteeUserId === actor.id) {\n throw badRequest('You cannot share a resource with yourself');\n }\n\n // Workspace-member guard: deny only on an explicit non-member (null = lookup\n // failed → allow, fail-open on transient errors; access still gated on accept).\n if (granteeUserId && this.requireWorkspaceMember) {\n const isMember = await this.deps.isWorkspaceMember(granteeUserId, this.workspaceId);\n if (isMember === false) {\n throw forbidden('You can only share with members of this workspace');\n }\n }\n\n // Idempotent: reuse an existing active grant for the same recipient.\n const existing = await this.prisma.findFirst({\n where: {\n resourceType: this.resourceType,\n resourceId: input.resourceId,\n deletedAt: null,\n status: { in: [ShareStatus.PENDING, ShareStatus.ACCEPTED] },\n OR: [...(granteeUserId ? [{ granteeUserId }] : []), { granteeEmail: email }],\n },\n });\n\n let grant: ShareGrantRecord;\n if (existing) {\n grant = await this.prisma.update({\n where: { id: existing.id },\n data: {\n role: input.role,\n message: input.message ?? null,\n expiresAt: input.expiresAt ?? null,\n ...(granteeUserId && !existing.granteeUserId ? { granteeUserId } : {}),\n },\n });\n } else {\n grant = await this.prisma.create({\n data: {\n workspaceId: this.workspaceId,\n resourceType: this.resourceType,\n resourceId: input.resourceId,\n granteeUserId: granteeUserId ?? null,\n granteeEmail: email,\n role: input.role,\n visibility: ShareVisibility.SHARED_WITH_USERS,\n status: ShareStatus.PENDING,\n token: generateToken(),\n expiresAt: input.expiresAt ?? null,\n message: input.message ?? null,\n createdBy: actor.id,\n onBehalfOf: actor.id,\n },\n });\n }\n\n await this.fireShareEmail(actor, grant, meta.name);\n return grant;\n }\n\n /** Create an immediately-active public link (anyone with the URL). */\n async createLinkShare(actor: ShareActor, input: CreateLinkShareInput): Promise<ShareGrantRecord> {\n const meta = await this.deps.loadResourceMeta(input.resourceId);\n if (!meta) throw notFound('Resource not found');\n await this.assertAccess(actor.id, input.resourceId, ShareRole.MANAGER, 'mutate');\n\n return this.prisma.create({\n data: {\n workspaceId: this.workspaceId,\n resourceType: this.resourceType,\n resourceId: input.resourceId,\n granteeUserId: null,\n granteeEmail: null,\n role: input.role,\n visibility: ShareVisibility.PUBLIC_LINK,\n status: ShareStatus.ACCEPTED, // links are active on creation\n token: generateToken(),\n expiresAt: input.expiresAt ?? null,\n message: null,\n createdBy: actor.id,\n onBehalfOf: actor.id,\n },\n });\n }\n\n // -------------------------------------------------------------------------\n // Accept / decline\n // -------------------------------------------------------------------------\n\n /** Explicitly accept a SHARED_WITH_USERS invite. Idempotent. */\n async acceptShare(token: string, actor: ShareActor): Promise<ShareGrantRecord> {\n const grant = await this.findActiveByToken(token);\n if (!grant) throw notFound('This share link is invalid or has expired');\n\n if (grant.visibility === ShareVisibility.PUBLIC_LINK) {\n // Nothing to accept for a public link.\n return grant;\n }\n\n const idMatches = !!grant.granteeUserId && grant.granteeUserId === actor.id;\n const emailMatches = emailsMatch(grant.granteeEmail, actor.email);\n if (!idMatches && !emailMatches) {\n throw forbidden('This invitation was sent to a different account');\n }\n\n if (grant.status === ShareStatus.ACCEPTED) {\n // Idempotent — backfill granteeUserId if it was an email-only invite.\n if (!grant.granteeUserId) {\n return this.prisma.update({ where: { id: grant.id }, data: { granteeUserId: actor.id } });\n }\n return grant;\n }\n\n const now = new Date();\n const res = await this.prisma.updateMany({\n where: { id: grant.id, status: ShareStatus.PENDING },\n data: { status: ShareStatus.ACCEPTED, acceptedAt: now, acceptedBy: actor.id, granteeUserId: actor.id },\n });\n if (res.count === 0) {\n // Lost a race or already terminal — return current state.\n const fresh = await this.prisma.findFirst({ where: { id: grant.id } });\n if (fresh) return fresh;\n }\n const updated = await this.prisma.findFirst({ where: { id: grant.id } });\n if (!updated) throw notFound();\n return updated;\n }\n\n /** Decline an invite (marks it REVOKED). */\n async declineShare(token: string, actor: ShareActor): Promise<boolean> {\n const grant = await this.findActiveByToken(token);\n if (!grant) return false;\n const idMatches = !!grant.granteeUserId && grant.granteeUserId === actor.id;\n const emailMatches = emailsMatch(grant.granteeEmail, actor.email);\n if (!idMatches && !emailMatches) throw forbidden('This invitation was sent to a different account');\n await this.prisma.update({\n where: { id: grant.id },\n data: { status: ShareStatus.REVOKED, revokedAt: new Date(), revokedBy: actor.id },\n });\n return true;\n }\n\n /** Public preview of a grant by token (safe fields only — never the resource body). */\n async shareGrantByToken(token: string): Promise<ShareGrantRecord | null> {\n return this.findActiveByToken(token);\n }\n\n // -------------------------------------------------------------------------\n // Management\n // -------------------------------------------------------------------------\n\n /** Revoke a grant or link. Owner/MANAGER only. */\n async revoke(grantId: string, actor: ShareActor): Promise<ShareGrantRecord> {\n const grant = await this.prisma.findFirst({ where: { id: grantId, resourceType: this.resourceType } });\n if (!grant || grant.deletedAt) throw notFound();\n await this.assertAccess(actor.id, grant.resourceId, ShareRole.MANAGER, 'mutate');\n return this.prisma.update({\n where: { id: grantId },\n data: { status: ShareStatus.REVOKED, revokedAt: new Date(), revokedBy: actor.id },\n });\n }\n\n /** Change the role on a grant. Owner/MANAGER only. */\n async updateRole(grantId: string, role: ShareRole, actor: ShareActor): Promise<ShareGrantRecord> {\n const grant = await this.prisma.findFirst({ where: { id: grantId, resourceType: this.resourceType } });\n if (!grant || grant.deletedAt) throw notFound();\n await this.assertAccess(actor.id, grant.resourceId, ShareRole.MANAGER, 'mutate');\n return this.prisma.update({ where: { id: grantId }, data: { role } });\n }\n\n // -------------------------------------------------------------------------\n // Reads\n // -------------------------------------------------------------------------\n\n /** All active grants on a resource (caller must be owner/MANAGER — gate in resolver). */\n async resourceShares(resourceId: string): Promise<ShareGrantRecord[]> {\n return this.prisma.findMany({\n where: {\n resourceType: this.resourceType,\n resourceId,\n deletedAt: null,\n status: { in: [ShareStatus.PENDING, ShareStatus.ACCEPTED] },\n },\n orderBy: { createdAt: 'desc' },\n });\n }\n\n /** Grants where the actor is the (accepted-or-pending) grantee. */\n async sharesSharedWithMe(\n actorId: string,\n opts?: { resourceType?: string; take?: number; skip?: number }\n ): Promise<ShareGrantRecord[]> {\n return this.prisma.findMany({\n where: {\n ...(opts?.resourceType ? { resourceType: opts.resourceType } : {}),\n granteeUserId: actorId,\n deletedAt: null,\n status: ShareStatus.ACCEPTED,\n OR: [{ expiresAt: null }, { expiresAt: { gt: new Date() } }],\n },\n orderBy: { acceptedAt: 'desc' },\n take: opts?.take,\n skip: opts?.skip,\n });\n }\n\n /**\n * Resource ids the actor can see via an ACCEPTED user grant — for narrowing\n * list resolvers (`WHERE id IN (...)`).\n */\n async listAccessibleResourceIds(actorId: string): Promise<string[]> {\n const grants = await this.prisma.findMany({\n where: {\n resourceType: this.resourceType,\n granteeUserId: actorId,\n deletedAt: null,\n status: ShareStatus.ACCEPTED,\n visibility: ShareVisibility.SHARED_WITH_USERS,\n OR: [{ expiresAt: null }, { expiresAt: { gt: new Date() } }],\n },\n });\n return Array.from(new Set(grants.map((g) => g.resourceId)));\n }\n\n /** Resource ids with an active public link — for list narrowing. */\n async listPublicResourceIds(): Promise<string[]> {\n const grants = await this.prisma.findMany({\n where: {\n resourceType: this.resourceType,\n deletedAt: null,\n status: { in: [...ACTIVE_STATUSES] },\n visibility: ShareVisibility.PUBLIC_LINK,\n OR: [{ expiresAt: null }, { expiresAt: { gt: new Date() } }],\n },\n });\n return Array.from(new Set(grants.map((g) => g.resourceId)));\n }\n\n /** Increment access analytics (best-effort). */\n async touchAccess(grantId: string): Promise<void> {\n try {\n await this.prisma.update({\n where: { id: grantId },\n data: { lastAccessAt: new Date(), accessCount: { increment: 1 } },\n });\n } catch (err) {\n logger.debug('[ShareService] touchAccess failed', { grantId, err });\n }\n }\n\n // -------------------------------------------------------------------------\n // Internals\n // -------------------------------------------------------------------------\n\n private async findActiveByToken(token: string): Promise<ShareGrantRecord | null> {\n if (!token) return null;\n const grant = await this.prisma.findFirst({ where: { token, deletedAt: null } });\n if (!grant) return null;\n if (grant.status === ShareStatus.REVOKED) return null;\n if (grant.expiresAt && grant.expiresAt.getTime() <= Date.now()) return null;\n return grant;\n }\n\n private async fireShareEmail(actor: ShareActor, grant: ShareGrantRecord, resourceName: string): Promise<void> {\n if (!grant.token) return;\n try {\n await this.deps.sendShareEmail({\n recipientEmail: grant.granteeEmail,\n recipientUserId: grant.granteeUserId,\n resourceType: this.resourceType,\n resourceName,\n role: grant.role,\n acceptUrl: this.deps.buildAcceptUrl(grant.token),\n message: grant.message,\n sharerName: actor.name ?? null,\n idempotencyKey: grant.id,\n });\n } catch (err) {\n // Email is best-effort — the grant is the source of truth.\n logger.warn('[ShareService] share email failed; grant still created', {\n grantId: grant.id,\n resourceType: this.resourceType,\n err,\n });\n }\n }\n}\n","/**\n * Share-email helpers.\n *\n * The `resource-shared` template must be registered in global-notification-svc.\n * Services wire `ShareServiceDeps.sendShareEmail` via {@link makeSendShareEmail},\n * passing an object that speaks `sendWithTemplate` (e.g. `sdk.tenantNotifications`).\n */\n\nimport { logger } from '../logger/index.js';\nimport { ShareRole, type SendShareEmailArgs } from './types.js';\n\n/** notification-svc template slug for \"X shared <entity> with you\" emails. */\nexport const SHARE_EMAIL_TEMPLATE_SLUG = 'resource-shared';\n\n/** Human-friendly labels per resourceType for the email body. */\nexport const RESOURCE_TYPE_LABELS: Record<string, string> = {\n session: 'terminal session',\n vibe: 'Vibe',\n vibedeck: 'VibeDeck',\n note: 'note',\n aiprompt: 'AI prompt',\n aicontext: 'AI context',\n instructionfile: 'instruction file',\n tunnel: 'tunnel',\n action: 'action',\n file: 'file',\n folder: 'folder',\n conversation: 'conversation',\n catalog: 'catalog',\n component: 'component',\n template: 'template',\n docs: 'docs site',\n};\n\nexport function resourceTypeLabel(resourceType: string): string {\n return RESOURCE_TYPE_LABELS[resourceType] ?? resourceType;\n}\n\nconst ROLE_LABELS: Record<ShareRole, string> = {\n [ShareRole.VIEWER]: 'Viewer',\n [ShareRole.COMMENTER]: 'Commenter',\n [ShareRole.EDITOR]: 'Editor',\n [ShareRole.MANAGER]: 'Manager',\n};\n\nexport function roleLabel(role: ShareRole): string {\n return ROLE_LABELS[role];\n}\n\n/** Build the variable bag the `resource-shared` template renders. */\nexport function buildShareEmailVariables(args: SendShareEmailArgs): Record<string, unknown> {\n return {\n sharerName: args.sharerName ?? 'A teammate',\n resourceType: resourceTypeLabel(args.resourceType),\n resourceName: args.resourceName,\n roleLabel: roleLabel(args.role),\n acceptUrl: args.acceptUrl,\n message: args.message ?? '',\n };\n}\n\n/**\n * Minimal structural view of a notifications module that can send a templated\n * email. `sdk.tenantNotifications` satisfies this. platform defaults to EMAIL\n * inside the module, so it isn't part of this contract.\n */\nexport interface ShareEmailNotifier {\n sendWithTemplate(input: {\n templateSlug: string;\n variables: Record<string, unknown>;\n recipient: { email?: string; userId?: string; name?: string };\n }): Promise<string>;\n}\n\n/**\n * Build a `ShareServiceDeps.sendShareEmail` implementation backed by a\n * notifications module. Skips (no-throw) when there's no addressable recipient.\n */\nexport function makeSendShareEmail(notifier: ShareEmailNotifier): (args: SendShareEmailArgs) => Promise<void> {\n return async (args: SendShareEmailArgs): Promise<void> => {\n const recipient: { email?: string; userId?: string } = {};\n if (args.recipientEmail) recipient.email = args.recipientEmail;\n if (args.recipientUserId) recipient.userId = args.recipientUserId;\n if (!recipient.email && !recipient.userId) {\n logger.warn('[ShareEmail] no addressable recipient; skipping', { idempotencyKey: args.idempotencyKey });\n return;\n }\n logger.info('[ShareEmail] Sending resource-shared', {\n templateSlug: SHARE_EMAIL_TEMPLATE_SLUG,\n resourceType: args.resourceType,\n idempotencyKey: args.idempotencyKey,\n });\n await notifier.sendWithTemplate({\n templateSlug: SHARE_EMAIL_TEMPLATE_SLUG,\n variables: buildShareEmailVariables(args),\n recipient,\n });\n };\n}\n","/**\n * Reusable GraphQL SDL for the generic sharing feature.\n *\n * {@link SHARE_GRANT_SDL} carries the shared types/enums/inputs + the uniform\n * token/self fields and is declared ONCE per subgraph (in a `shared` module).\n * {@link buildPerEntityShareSdl} generates the thin per-entity wrappers that\n * each carry a STATIC `@rbac` directive (the gateway requires a literal\n * action/resource per field — a single generic `shareResource` field cannot be\n * RBAC-protected correctly).\n *\n * Both reference `@rbac` / `@key`, which the host subgraph already declares via\n * its federation/`@link` setup. DateTime is assumed available (be-sdk graphql).\n */\n\nexport const SHARE_GRANT_SDL = /* GraphQL */ `\n enum ShareRole {\n VIEWER\n COMMENTER\n EDITOR\n MANAGER\n }\n\n enum ShareGrantVisibility {\n PRIVATE\n SHARED_WITH_USERS\n SHARED_WITH_VIBE\n PUBLIC_LINK\n }\n\n enum ShareGrantStatus {\n PENDING\n ACCEPTED\n REVOKED\n EXPIRED\n }\n\n type ShareCapabilities {\n canView: Boolean!\n canComment: Boolean!\n canEdit: Boolean!\n canManage: Boolean!\n canExecute: Boolean!\n }\n\n type ShareGrant @key(fields: \"id\") {\n id: ID!\n resourceType: String!\n resourceId: ID!\n granteeUserId: ID\n granteeEmail: String\n role: ShareRole!\n visibility: ShareGrantVisibility!\n status: ShareGrantStatus!\n expiresAt: DateTime\n message: String\n createdBy: ID!\n acceptedAt: DateTime\n createdAt: DateTime!\n \"Public accept/link URL (present for invites and public links).\"\n shareUrl: String\n \"Capabilities implied by this grant's role.\"\n capabilities: ShareCapabilities!\n }\n\n type ShareGrantList {\n items: [ShareGrant!]!\n total: Int!\n }\n\n \"Safe, pre-login preview of a share invitation.\"\n type ShareGrantPreview {\n id: ID!\n resourceType: String!\n resourceName: String\n role: ShareRole!\n visibility: ShareGrantVisibility!\n status: ShareGrantStatus!\n sharerName: String\n expiresAt: DateTime\n }\n\n input ShareEntityInput {\n resourceId: ID!\n email: String!\n role: ShareRole!\n message: String\n expiresAt: DateTime\n }\n\n input UpdateShareRoleInput {\n resourceId: ID!\n shareId: ID!\n role: ShareRole!\n }\n\n input RevokeShareInput {\n resourceId: ID!\n shareId: ID!\n }\n\n input CreateShareLinkInput {\n resourceId: ID!\n role: ShareRole!\n expiresAt: DateTime\n }\n\n extend type Query {\n \"Pre-login preview of a share invite by token.\"\n shareGrantByToken(token: String!): ShareGrantPreview @rbac(public: true)\n \"Grants where the current user is the accepted grantee.\"\n sharesSharedWithMe(resourceType: String, pagination: PaginationInput): ShareGrantList! @rbac(scopeType: \"self\")\n }\n\n extend type Mutation {\n \"Accept a share invitation (recipient identified by the opaque token + email/id).\"\n acceptShare(token: String!): ShareGrant! @rbac(public: true)\n \"Decline a share invitation.\"\n declineShare(token: String!): Boolean! @rbac(public: true)\n }\n`;\n\n/**\n * Per-entity wrapper SDL. `entity` is the GraphQL-safe PascalCase name used in\n * the field name (e.g. `Session` → `shareSession`); `rbacResource` is the\n * resource string the gateway checks (e.g. `session`, `ai-prompt`).\n */\nexport function buildPerEntityShareSdl(entity: string, rbacResource: string): string {\n return /* GraphQL */ `\nextend type Mutation {\n share${entity}(input: ShareEntityInput!): ShareGrant!\n @rbac(action: \"share\", resource: \"${rbacResource}\", resourceIdArg: \"input.resourceId\", scopeType: \"wspace\")\n revoke${entity}Share(input: RevokeShareInput!): ShareGrant!\n @rbac(action: \"share\", resource: \"${rbacResource}\", resourceIdArg: \"input.resourceId\", scopeType: \"wspace\")\n update${entity}ShareRole(input: UpdateShareRoleInput!): ShareGrant!\n @rbac(action: \"share\", resource: \"${rbacResource}\", resourceIdArg: \"input.resourceId\", scopeType: \"wspace\")\n create${entity}ShareLink(input: CreateShareLinkInput!): ShareGrant!\n @rbac(action: \"share\", resource: \"${rbacResource}\", resourceIdArg: \"input.resourceId\", scopeType: \"wspace\")\n revoke${entity}ShareLink(input: RevokeShareInput!): ShareGrant!\n @rbac(action: \"share\", resource: \"${rbacResource}\", resourceIdArg: \"input.resourceId\", scopeType: \"wspace\")\n}\n`;\n}\n","/**\n * Canonical `ShareGrant` Prisma model + indexes, shipped as a copy-paste string.\n *\n * Each service pastes {@link SHARE_GRANT_PRISMA} into its own `prisma/schema/`\n * and runs `gendb`. Enum names are deliberately `ShareRole` /\n * `ShareGrantVisibility` / `ShareGrantStatus` so they never collide with the\n * legacy per-service `ShareStatus` / `VibeVisibility` enums. The Prisma FIELD\n * names stay camelCase (what {@link ShareService} reads/writes); `@map` keeps the\n * DB columns snake_case so {@link SHARE_GRANT_PARTIAL_UNIQUE_SQL} reads cleanly.\n */\n\nexport const SHARE_GRANT_PRISMA = `\nenum ShareRole {\n VIEWER\n COMMENTER\n EDITOR\n MANAGER\n}\n\nenum ShareGrantVisibility {\n PRIVATE\n SHARED_WITH_USERS\n SHARED_WITH_VIBE\n PUBLIC_LINK\n}\n\nenum ShareGrantStatus {\n PENDING\n ACCEPTED\n REVOKED\n EXPIRED\n}\n\n/// Generic resource share grant. \\`resourceType\\` discriminates the entity; one\n/// row per (resource, recipient) or per public link. See @burdenoff/be-sdk/sharing.\nmodel ShareGrant {\n id String @id @default(uuid())\n workspaceId String @map(\"workspace_id\") @db.VarChar(255)\n resourceType String @map(\"resource_type\") @db.VarChar(64)\n resourceId String @map(\"resource_id\") @db.VarChar(255)\n granteeUserId String? @map(\"grantee_user_id\") @db.VarChar(255)\n granteeEmail String? @map(\"grantee_email\") @db.VarChar(320)\n role ShareRole @default(VIEWER)\n visibility ShareGrantVisibility @default(SHARED_WITH_USERS)\n status ShareGrantStatus @default(PENDING)\n token String? @unique @db.VarChar(64)\n expiresAt DateTime? @map(\"expires_at\")\n message String? @db.Text\n createdBy String @map(\"created_by\") @db.VarChar(255)\n onBehalfOf String @map(\"on_behalf_of\") @db.VarChar(255)\n acceptedAt DateTime? @map(\"accepted_at\")\n acceptedBy String? @map(\"accepted_by\") @db.VarChar(255)\n revokedAt DateTime? @map(\"revoked_at\")\n revokedBy String? @map(\"revoked_by\") @db.VarChar(255)\n lastAccessAt DateTime? @map(\"last_access_at\")\n accessCount Int @default(0) @map(\"access_count\")\n context Json?\n createdAt DateTime @default(now()) @map(\"created_at\")\n updatedAt DateTime @updatedAt @map(\"updated_at\")\n deletedAt DateTime? @map(\"deleted_at\")\n\n @@index([workspaceId])\n @@index([resourceType, resourceId])\n @@index([granteeUserId])\n @@index([granteeEmail])\n @@index([status])\n @@index([expiresAt])\n @@index([resourceType, resourceId, status])\n @@map(\"share_grants\")\n}\n`;\n\n/**\n * Partial-unique index that Prisma's `@@unique` cannot express (it has no WHERE\n * predicate). Add this as a raw SQL step in the same migration that creates the\n * table. The table is brand new, so a plain (non-CONCURRENT) create is safe and\n * transaction-friendly.\n */\nexport const SHARE_GRANT_PARTIAL_UNIQUE_SQL = `\nCREATE UNIQUE INDEX IF NOT EXISTS share_grants_active_user_uq\n ON share_grants (resource_type, resource_id, grantee_user_id)\n WHERE status IN ('PENDING', 'ACCEPTED') AND deleted_at IS NULL AND grantee_user_id IS NOT NULL;\n`;\n"]}
|