nucleus-core-ts 0.9.960 → 0.9.962
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js
CHANGED
|
@@ -528,7 +528,12 @@ ${strMDSAlgs}`)}if(attestationStatementAlg!==void 0&&authenticatorGetInfo?.algor
|
|
|
528
528
|
<p>Redirecting...</p>
|
|
529
529
|
</body>
|
|
530
530
|
</html>
|
|
531
|
-
`},createPaymentRoutes=(config)=>{let{provider,basePath,defaultCurrency,defaultLocale,successRedirectUrl,failedRedirectUrl,errorRedirectUrl,savedMethodsEnabled,threeDSecureEnabled,subMerchantsEnabled,transactionsTable,methodsTable,webhookLogsTable,subMerchantsTable,commissionSplitsTable,productsTable,pricesTable,customersTable,subscriptionsTable,invoicesTable,db,logger:logger2}=config,txTable=transactionsTable,pmTable=methodsTable,whTable=webhookLogsTable,smTable=subMerchantsTable,csTable=commissionSplitsTable,prodTable=productsTable,priceTable=pricesTable,cusTable=customersTable,subTable=subscriptionsTable,invTable=invoicesTable,database=db,app=new Elysia47({prefix:basePath}),customerBelongsToCaller=async(request,customerId)=>{if(hasGodminRole(request))return!0;let uid=request.headers.get("x-user-id");if(!uid||!customerId)return!1;let[c]=await database.select().from(cusTable).where(eq59(cusTable.id,String(customerId)));return!!c&&String(c.user_id)===String(uid)},callerCustomerIds=async(uid)=>{return(await database.select().from(cusTable).where(eq59(cusTable.user_id,uid))).map((r2)=>String(r2.id))};if(app.post("/initialize",async(ctx)=>{if(!threeDSecureEnabled)return ctx.set.status=400,{success:!1,error:"3D Secure is not enabled"};let userId=ctx.request.headers.get("x-user-id"),body=ctx.body;try{let[transaction]=await database.insert(txTable).values({userId:userId??null,orderId:body.orderId??body.conversationId??null,provider:provider.name,amount:Number(body.paidPrice??body.price??0),currency:body.currency??defaultCurrency,status:"pending",statusCode:1000,statusMessage:"3DS initialization started",isThreeDSecure:!0,installment:body.installment??1,ipAddress:ctx.request.headers.get("x-forwarded-for")??ctx.request.headers.get("x-real-ip")??null,metadata:body.metadata??{}}).returning(),result=await provider.initialize3DS({locale:body.locale??defaultLocale,conversationId:transaction.id,price:body.price,paidPrice:body.paidPrice,currency:body.currency??defaultCurrency,installment:body.installment,paymentChannel:body.paymentChannel,basketId:body.basketId,paymentGroup:body.paymentGroup,paymentCard:body.paymentCard,buyer:body.buyer,shippingAddress:body.shippingAddress,billingAddress:body.billingAddress,basketItems:body.basketItems,callbackUrl:body.callbackUrl??config.callbackUrl??`${basePath}/callback`});if(!result.success)return await database.update(txTable).set({status:"failed",statusCode:1003,statusMessage:result.errorMessage??"Initialization failed",providerResponse:result.rawResponse??{},failedAt:new Date}).where(eq59(txTable.id,transaction.id)),ctx.set.status=400,{success:!1,error:result.errorMessage??"Payment initialization failed",errorCode:result.errorCode};return await database.update(txTable).set({status:"processing",statusCode:1001,statusMessage:"3DS initialized, awaiting bank verification",providerPaymentId:result.paymentId,providerResponse:result.rawResponse??{}}).where(eq59(txTable.id,transaction.id)),{success:!0,transactionId:transaction.id,threeDSHtmlContent:result.threeDSHtmlContent,paymentId:result.paymentId}}catch(error3){return logger2.error("[Payment] initialize3DS error",{error:error3 instanceof Error?error3.message:String(error3)}),ctx.set.status=500,{success:!1,error:"Internal payment error"}}}),app.post("/callback",async(ctx)=>{let requestOrigin=new URL(ctx.request.url).origin,htmlHeaders={"Content-Type":"text/html; charset=utf-8","Access-Control-Allow-Origin":requestOrigin,"Access-Control-Allow-Methods":"POST, OPTIONS"};try{let formData=await ctx.request.formData(),rawData={};formData.forEach((value2,key2)=>{rawData[key2]=String(value2)});let parsed=provider.parseCallback(rawData);if(await database.insert(whTable).values({provider:provider.name,eventType:"three_ds_callback",providerPaymentId:parsed.paymentId,rawPayload:rawData,processed:!1,idempotencyKey:`${provider.name}:${parsed.paymentId}:${parsed.mdStatus}`,ipAddress:ctx.request.headers.get("x-forwarded-for")??ctx.request.headers.get("x-real-ip")??null}).onConflictDoNothing(),!parsed.success){if(logger2.warn("[Payment] 3DS callback failed",{mdStatus:parsed.mdStatus,paymentId:parsed.paymentId}),parsed.conversationId)await database.update(txTable).set({status:"failed",statusCode:1003,statusMessage:`3DS verification failed: mdStatus=${parsed.mdStatus}`,failedAt:new Date}).where(eq59(txTable.id,parsed.conversationId)).catch(()=>{});return new Response(generateRedirectHtml(`${requestOrigin}${failedRedirectUrl}`,"Payment Failed"),{headers:htmlHeaders})}let completion=await provider.complete3DS({locale:defaultLocale,conversationId:parsed.conversationId,paymentId:parsed.paymentId});if(!completion.success){if(logger2.error("[Payment] 3DS completion failed",{paymentId:parsed.paymentId,errorCode:completion.errorCode,errorMessage:completion.errorMessage}),parsed.conversationId)await database.update(txTable).set({status:"failed",statusCode:1003,statusMessage:`3DS completion failed: ${completion.errorMessage}`,providerResponse:completion.rawResponse??{},failedAt:new Date}).where(eq59(txTable.id,parsed.conversationId)).catch(()=>{});return new Response(generateRedirectHtml(`${requestOrigin}${failedRedirectUrl}`,"Payment Failed"),{headers:htmlHeaders})}if(parsed.conversationId)await database.update(txTable).set({status:"completed",statusCode:1001,statusMessage:"Payment completed successfully",providerPaymentId:completion.paymentId??parsed.paymentId,providerTransactionId:completion.signature,amount:completion.paidPrice??0,currency:completion.currency??defaultCurrency,paymentMethod:completion.cardAssociation,cardLastFour:completion.lastFourDigits,cardType:completion.cardType,cardAssociation:completion.cardAssociation,installment:completion.installment??1,providerResponse:completion.rawResponse??{},completedAt:new Date}).where(and21(eq59(txTable.id,parsed.conversationId),eq59(txTable.status,"pending"))).catch(()=>{});await database.update(whTable).set({processed:!0,processingResult:{completion}}).where(eq59(whTable.idempotencyKey,`${provider.name}:${parsed.paymentId}:${parsed.mdStatus}`)).catch(()=>{}),logger2.info("[Payment] 3DS payment completed",{paymentId:completion.paymentId,amount:completion.paidPrice,currency:completion.currency});let queryParams=new URLSearchParams;if(parsed.conversationId)queryParams.append("transactionId",parsed.conversationId);if(completion.paymentId)queryParams.append("paymentId",completion.paymentId);if(completion.paidPrice)queryParams.append("amount",String(completion.paidPrice));let redirectUrl=`${requestOrigin}${successRedirectUrl}?${queryParams.toString()}`;return new Response(generateRedirectHtml(redirectUrl,"Payment Successful"),{headers:htmlHeaders})}catch(error3){return logger2.error("[Payment] callback error",{error:error3 instanceof Error?error3.message:String(error3)}),new Response(generateRedirectHtml(`${requestOrigin}${errorRedirectUrl}`,"Payment Error"),{headers:htmlHeaders})}}),app.get("/transactions",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{return{success:!0,data:{items:await database.select().from(txTable).where(eq59(txTable.userId,userId)).orderBy(txTable.createdAt)}}}catch(error3){return logger2.error("[Payment] list transactions error",{error:error3 instanceof Error?error3.message:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to list transactions"}}}),app.get("/transactions/:id",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let[transaction]=await database.select().from(txTable).where(and21(eq59(txTable.id,ctx.params.id),eq59(txTable.userId,userId))).limit(1);if(!transaction)return ctx.set.status=404,{success:!1,error:"Transaction not found"};return{success:!0,data:transaction}}catch{return ctx.set.status=500,{success:!1,error:"Failed to get transaction"}}}),app.post("/bin-query",async(ctx)=>{let body=ctx.body,binNumber=body.binNumber??body.cardNumber;if(!binNumber||typeof binNumber!=="string")return ctx.set.status=400,{success:!1,error:"binNumber is required"};try{let result=await provider.queryBin({locale:body.locale??defaultLocale,binNumber,price:body.price});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"BIN query failed",errorCode:result.errorCode};return{success:!0,data:result}}catch{return ctx.set.status=500,{success:!1,error:"BIN query failed"}}}),app.post("/payment-detail",async(ctx)=>{let body=ctx.body;if(!body.paymentId)return ctx.set.status=400,{success:!1,error:"paymentId is required"};try{let result=await provider.getPaymentDetail({locale:body.locale??defaultLocale,paymentId:body.paymentId,conversationId:body.conversationId,paymentConversationId:body.paymentConversationId});return{success:result.success,data:result}}catch{return ctx.set.status=500,{success:!1,error:"Payment detail query failed"}}}),app.post("/refund",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};let body=ctx.body;if(!body.paymentTransactionId||!body.price)return ctx.set.status=400,{success:!1,error:"paymentTransactionId and price are required"};let refundAmt=validateAmount(body.price,"price");if(!refundAmt.ok)return ctx.set.status=400,{success:!1,error:refundAmt.error};if(!hasGodminRole(ctx.request)){if(!body.transactionId)return ctx.set.status=400,{success:!1,error:"transactionId is required"};let[tx]=await database.select().from(txTable).where(eq59(txTable.id,body.transactionId)).limit(1);if(!tx)return ctx.set.status=404,{success:!1,error:"Transaction not found"};if(String(tx.userId)!==String(userId))return ctx.set.status=403,{success:!1,error:"You can only refund your own transactions"};let ownedProviderId=tx.providerTransactionId??tx.providerPaymentId;if(ownedProviderId&&String(body.paymentTransactionId)!==String(ownedProviderId))return ctx.set.status=403,{success:!1,error:"paymentTransactionId does not match this transaction"};let refundable=Number(tx.amount??0)-Number(tx.refundedAmount??0);if(!(Number(body.price)>0)||Number(body.price)>refundable)return ctx.set.status=400,{success:!1,error:`Refund amount exceeds the refundable balance (${refundable})`}}try{let result=await provider.refund({locale:body.locale??defaultLocale,conversationId:body.conversationId,paymentTransactionId:body.paymentTransactionId,price:String(body.price),currency:body.currency??defaultCurrency,ip:ctx.request.headers.get("x-forwarded-for")??ctx.request.headers.get("x-real-ip")??void 0});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Refund failed",errorCode:result.errorCode};if(body.transactionId){let price=Number(body.price);await database.update(txTable).set({status:sql11`CASE WHEN COALESCE(${txTable.refundedAmount}, 0) + ${price} >= ${txTable.amount} THEN 'refunded' ELSE 'partially_refunded' END`,refundedAmount:sql11`COALESCE(${txTable.refundedAmount}, 0) + ${price}`,refundedAt:new Date,statusMessage:"Payment refunded"}).where(eq59(txTable.id,body.transactionId)).catch(()=>{})}return logger2.info("[Payment] Refund processed",{paymentId:result.paymentId,price:result.price}),{success:!0,data:result}}catch{return ctx.set.status=500,{success:!1,error:"Refund failed"}}}),savedMethodsEnabled)app.post("/cards/save",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};let body=ctx.body;if(!body.email||!body.card)return ctx.set.status=400,{success:!1,error:"email and card are required"};try{let result=await provider.saveCard({locale:body.locale??defaultLocale,email:body.email,externalId:userId,card:body.card});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to save card",errorCode:result.errorCode};let[saved]=await database.insert(pmTable).values({userId,provider:provider.name,type:"card",alias:result.cardAlias??body.card.cardAlias,cardLastFour:result.lastFourDigits,cardType:result.cardType,cardAssociation:result.cardAssociation,cardFamily:result.cardFamily,cardBankName:result.cardBankName,providerCardUserKey:result.cardUserKey,providerCardToken:result.cardToken,binNumber:result.binNumber}).returning();return logger2.info("[Payment] Card saved",{userId,cardAlias:result.cardAlias}),{success:!0,data:saved}}catch{return ctx.set.status=500,{success:!1,error:"Failed to save card"}}}),app.get("/cards",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{return{success:!0,data:{items:await database.select().from(pmTable).where(and21(eq59(pmTable.userId,userId),eq59(pmTable.isActive,!0))).orderBy(pmTable.createdAt)}}}catch{return ctx.set.status=500,{success:!1,error:"Failed to list cards"}}}),app.delete("/cards/:id",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let[card]=await database.select().from(pmTable).where(and21(eq59(pmTable.id,ctx.params.id),eq59(pmTable.userId,userId))).limit(1);if(!card)return ctx.set.status=404,{success:!1,error:"Card not found"};if(card.providerCardUserKey&&card.providerCardToken){let deleteResult=await provider.deleteCard({locale:defaultLocale,cardUserKey:card.providerCardUserKey,cardToken:card.providerCardToken});if(!deleteResult.success)logger2.warn("[Payment] Provider card delete failed (proceeding with local delete)",{errorCode:deleteResult.errorCode,errorMessage:deleteResult.errorMessage})}return await database.update(pmTable).set({isActive:!1}).where(eq59(pmTable.id,ctx.params.id)),logger2.info("[Payment] Card deleted",{userId,cardId:ctx.params.id}),{success:!0}}catch{return ctx.set.status=500,{success:!1,error:"Failed to delete card"}}}),app.post("/cards/sync",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};let body=ctx.body,cardUserKey=body.cardUserKey;if(!cardUserKey)return ctx.set.status=400,{success:!1,error:"cardUserKey is required"};try{let result=await provider.listCards({locale:body.locale??defaultLocale,cardUserKey});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to list cards from provider"};return{success:!0,data:{cardUserKey:result.cardUserKey,cards:result.cards}}}catch{return ctx.set.status=500,{success:!1,error:"Failed to sync cards"}}});if(app.post("/products",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};if(!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden: operator privileges required"};let body=ctx.body;if(!body.name)return ctx.set.status=400,{success:!1,error:"name is required"};try{let providerResult=await provider.createProduct({name:body.name,description:body.description,type:body.type,images:body.images,unitLabel:body.unitLabel,url:body.url,metadata:body.metadata});if(!providerResult.success)return ctx.set.status=400,{success:!1,error:providerResult.errorMessage??"Failed to create product at provider",errorCode:providerResult.errorCode};let[saved]=await database.insert(prodTable).values({provider:provider.name,providerProductId:providerResult.providerProductId,name:body.name,description:body.description??null,type:body.type??"service",status:"active",images:body.images?JSON.stringify(body.images):"[]",unitLabel:body.unitLabel??null,url:body.url??null,metadata:body.metadata?JSON.stringify(body.metadata):"{}"}).returning();return logger2.info("[Payment] Product created",{id:saved.id,providerProductId:providerResult.providerProductId}),{success:!0,data:saved}}catch(error3){return logger2.error("[Payment] create product error",{error:error3 instanceof Error?error3.message:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to create product"}}}),app.put("/products/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};if(!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden: operator privileges required"};let body=ctx.body;try{let[existing]=await database.select().from(prodTable).where(eq59(prodTable.id,ctx.params.id)).limit(1);if(!existing)return ctx.set.status=404,{success:!1,error:"Product not found"};if(existing.providerProductId){let providerResult=await provider.updateProduct({providerProductId:existing.providerProductId,name:body.name,description:body.description,images:body.images,unitLabel:body.unitLabel,url:body.url,active:body.status==="active"?!0:body.status==="archived"?!1:void 0,metadata:body.metadata});if(!providerResult.success)logger2.warn("[Payment] Provider product update failed",{errorCode:providerResult.errorCode})}let updateData={};if(body.name)updateData.name=body.name;if(body.description!==void 0)updateData.description=body.description;if(body.type)updateData.type=body.type;if(body.status)updateData.status=body.status;if(body.images)updateData.images=JSON.stringify(body.images);if(body.unitLabel!==void 0)updateData.unitLabel=body.unitLabel;if(body.url!==void 0)updateData.url=body.url;if(body.metadata)updateData.metadata=JSON.stringify(body.metadata);let[updated]=await database.update(prodTable).set(updateData).where(eq59(prodTable.id,ctx.params.id)).returning();return{success:!0,data:updated}}catch{return ctx.set.status=500,{success:!1,error:"Failed to update product"}}}),app.get("/products",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let status=new URL(ctx.request.url).searchParams.get("status"),query=database.select().from(prodTable).where(eq59(prodTable.isActive,!0));if(status)query=database.select().from(prodTable).where(and21(eq59(prodTable.isActive,!0),eq59(prodTable.status,status)));return{success:!0,data:{items:await query.orderBy(prodTable.createdAt)}}}catch{return ctx.set.status=500,{success:!1,error:"Failed to list products"}}}),app.get("/products/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let[item]=await database.select().from(prodTable).where(eq59(prodTable.id,ctx.params.id)).limit(1);if(!item)return ctx.set.status=404,{success:!1,error:"Product not found"};let prices=await database.select().from(priceTable).where(and21(eq59(priceTable.productId,ctx.params.id),eq59(priceTable.isActive,!0))).orderBy(priceTable.createdAt);return{success:!0,data:{...item,prices}}}catch{return ctx.set.status=500,{success:!1,error:"Failed to get product"}}}),app.delete("/products/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};if(!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden: operator privileges required"};try{let[existing]=await database.select().from(prodTable).where(eq59(prodTable.id,ctx.params.id)).limit(1);if(!existing)return ctx.set.status=404,{success:!1,error:"Product not found"};if(existing.providerProductId)await provider.archiveProduct({providerProductId:existing.providerProductId});let[updated]=await database.update(prodTable).set({status:"archived"}).where(eq59(prodTable.id,ctx.params.id)).returning();return{success:!0,data:updated}}catch{return ctx.set.status=500,{success:!1,error:"Failed to archive product"}}}),app.post("/prices",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};if(!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden: operator privileges required"};let body=ctx.body;if(!body.productId||body.unitAmount===void 0||!body.currency)return ctx.set.status=400,{success:!1,error:"productId, unitAmount, and currency are required"};try{let[product]=await database.select().from(prodTable).where(eq59(prodTable.id,body.productId)).limit(1);if(!product)return ctx.set.status=404,{success:!1,error:"Product not found"};let providerResult=await provider.createPrice({providerProductId:product.providerProductId,currency:body.currency,unitAmount:body.unitAmount,type:body.type,billingScheme:body.billingScheme,nickname:body.nickname,recurring:body.recurring,transformQuantity:body.transformQuantity,unitAmountDecimal:body.unitAmountDecimal,metadata:body.metadata});if(!providerResult.success)return ctx.set.status=400,{success:!1,error:providerResult.errorMessage??"Failed to create price at provider",errorCode:providerResult.errorCode};let[saved]=await database.insert(priceTable).values({productId:body.productId,provider:provider.name,providerPriceId:providerResult.providerPriceId,currency:body.currency,unitAmount:body.unitAmount,unitAmountDecimal:body.unitAmountDecimal??null,type:body.type??"one_time",billingScheme:body.billingScheme??"per_unit",nickname:body.nickname??null,recurringInterval:body.recurring?.interval??null,recurringIntervalCount:body.recurring?.intervalCount??1,recurringUsageType:body.recurring?.usageType??"licensed",recurringAggregateUsage:body.recurring?.aggregateUsage??null,transformQuantityDivideBy:body.transformQuantity?.divideBy??null,transformQuantityRound:body.transformQuantity?.round??null,status:"active",metadata:body.metadata?JSON.stringify(body.metadata):"{}"}).returning();return logger2.info("[Payment] Price created",{id:saved.id,providerPriceId:providerResult.providerPriceId}),{success:!0,data:saved}}catch(error3){return logger2.error("[Payment] create price error",{error:error3 instanceof Error?error3.message:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to create price"}}}),app.put("/prices/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};if(!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden: operator privileges required"};let body=ctx.body;try{let[existing]=await database.select().from(priceTable).where(eq59(priceTable.id,ctx.params.id)).limit(1);if(!existing)return ctx.set.status=404,{success:!1,error:"Price not found"};if(existing.providerPriceId){let providerResult=await provider.updatePrice({providerPriceId:existing.providerPriceId,nickname:body.nickname,active:body.status==="active"?!0:body.status==="archived"?!1:void 0,metadata:body.metadata});if(!providerResult.success)logger2.warn("[Payment] Provider price update failed",{errorCode:providerResult.errorCode})}let updateData={};if(body.nickname!==void 0)updateData.nickname=body.nickname;if(body.status)updateData.status=body.status;if(body.metadata)updateData.metadata=JSON.stringify(body.metadata);let[updated]=await database.update(priceTable).set(updateData).where(eq59(priceTable.id,ctx.params.id)).returning();return{success:!0,data:updated}}catch{return ctx.set.status=500,{success:!1,error:"Failed to update price"}}}),app.get("/prices",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let url=new URL(ctx.request.url),productId=url.searchParams.get("productId"),status=url.searchParams.get("status"),query=database.select().from(priceTable).where(eq59(priceTable.isActive,!0));if(productId&&status)query=database.select().from(priceTable).where(and21(eq59(priceTable.productId,productId),eq59(priceTable.status,status),eq59(priceTable.isActive,!0)));else if(productId)query=database.select().from(priceTable).where(and21(eq59(priceTable.productId,productId),eq59(priceTable.isActive,!0)));else if(status)query=database.select().from(priceTable).where(and21(eq59(priceTable.status,status),eq59(priceTable.isActive,!0)));return{success:!0,data:{items:await query.orderBy(priceTable.createdAt)}}}catch{return ctx.set.status=500,{success:!1,error:"Failed to list prices"}}}),app.get("/prices/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let[item]=await database.select().from(priceTable).where(eq59(priceTable.id,ctx.params.id)).limit(1);if(!item)return ctx.set.status=404,{success:!1,error:"Price not found"};return{success:!0,data:item}}catch{return ctx.set.status=500,{success:!1,error:"Failed to get price"}}}),app.delete("/prices/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};if(!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden: operator privileges required"};try{let[existing]=await database.select().from(priceTable).where(eq59(priceTable.id,ctx.params.id)).limit(1);if(!existing)return ctx.set.status=404,{success:!1,error:"Price not found"};if(existing.providerPriceId)await provider.archivePrice({providerPriceId:existing.providerPriceId});let[updated]=await database.update(priceTable).set({status:"archived"}).where(eq59(priceTable.id,ctx.params.id)).returning();return{success:!0,data:updated}}catch{return ctx.set.status=500,{success:!1,error:"Failed to archive price"}}}),app.post("/customers",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let body=ctx.body,result=await provider.createCustomer({email:body.email,name:body.name,phone:body.phone,description:body.description,metadata:body.metadata,address:body.address?{line1:body.address?.line1,line2:body.address?.line2,city:body.address?.city,state:body.address?.state,postalCode:body.address?.postalCode,country:body.address?.country}:void 0,taxId:body.taxId});if(!result.success)return ctx.set.status=400,result;let[row]=await database.insert(cusTable).values({user_id:userId,provider:provider.name,provider_customer_id:result.providerCustomerId,email:body.email,name:body.name??null,phone:body.phone??null,description:body.description??null,address:body.address??{},tax_id_type:body.taxId?.type??null,tax_id_value:body.taxId?.value??null,metadata:body.metadata??{}}).returning();return{success:!0,customer:row,providerCustomerId:result.providerCustomerId}}catch(error3){return logger2.error("[Payment] Create customer error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to create customer"}}}),app.put("/customers/:id",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,body=ctx.body,[existing]=await database.select().from(cusTable).where(eq59(cusTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Customer not found"};if(String(existing.user_id)!==String(userId)&&!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden"};let result=await provider.updateCustomer({providerCustomerId:existing.provider_customer_id,email:body.email,name:body.name,phone:body.phone,description:body.description,metadata:body.metadata,address:body.address?{line1:body.address?.line1,line2:body.address?.line2,city:body.address?.city,state:body.address?.state,postalCode:body.address?.postalCode,country:body.address?.country}:void 0});if(!result.success)return ctx.set.status=400,result;let updates={};if(body.email)updates.email=body.email;if(body.name!==void 0)updates.name=body.name;if(body.phone!==void 0)updates.phone=body.phone;if(body.description!==void 0)updates.description=body.description;if(body.address)updates.address=body.address;if(body.metadata)updates.metadata=body.metadata;let[updated]=await database.update(cusTable).set(updates).where(eq59(cusTable.id,id)).returning();return{success:!0,customer:updated}}catch(error3){return logger2.error("[Payment] Update customer error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to update customer"}}}),app.get("/customers",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{return{success:!0,customers:await database.select().from(cusTable).where(eq59(cusTable.user_id,userId))}}catch(error3){return logger2.error("[Payment] List customers error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to list customers"}}}),app.get("/customers/:id",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,[customer]=await database.select().from(cusTable).where(eq59(cusTable.id,id));if(!customer)return ctx.set.status=404,{success:!1,error:"Customer not found"};if(String(customer.user_id)!==String(userId)&&!hasGodminRole(ctx.request))return ctx.set.status=404,{success:!1,error:"Customer not found"};return{success:!0,customer}}catch(error3){return logger2.error("[Payment] Get customer error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to get customer"}}}),app.delete("/customers/:id",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,[existing]=await database.select().from(cusTable).where(eq59(cusTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Customer not found"};if(String(existing.user_id)!==String(userId)&&!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden"};return await provider.deleteCustomer({providerCustomerId:existing.provider_customer_id}),await database.delete(cusTable).where(eq59(cusTable.id,id)),{success:!0}}catch(error3){return logger2.error("[Payment] Delete customer error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to delete customer"}}}),app.post("/subscriptions",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let body=ctx.body,customerId=body.customerId,[customer]=await database.select().from(cusTable).where(eq59(cusTable.id,customerId));if(!customer)return ctx.set.status=404,{success:!1,error:"Customer not found"};if(String(customer.user_id)!==String(userId)&&!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden"};let items=body.items,result=await provider.createSubscription({providerCustomerId:customer.provider_customer_id,items,trialPeriodDays:body.trialPeriodDays,collectionMethod:body.collectionMethod,daysUntilDue:body.daysUntilDue,cancelAtPeriodEnd:body.cancelAtPeriodEnd,metadata:body.metadata,defaultPaymentMethod:body.defaultPaymentMethod});if(!result.success)return ctx.set.status=400,result;let[row]=await database.insert(subTable).values({customer_id:customerId,provider:provider.name,provider_subscription_id:result.providerSubscriptionId,status:result.status??"incomplete",collection_method:body.collectionMethod??"charge_automatically",current_period_start:result.currentPeriodStart?new Date(result.currentPeriodStart):null,current_period_end:result.currentPeriodEnd?new Date(result.currentPeriodEnd):null,cancel_at_period_end:body.cancelAtPeriodEnd??!1,items,metadata:body.metadata??{}}).returning();return{success:!0,subscription:row,clientSecret:result.clientSecret}}catch(error3){return logger2.error("[Payment] Create subscription error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to create subscription"}}}),app.put("/subscriptions/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,body=ctx.body,[existing]=await database.select().from(subTable).where(eq59(subTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Subscription not found"};if(!await customerBelongsToCaller(ctx.request,existing.customer_id))return ctx.set.status=403,{success:!1,error:"Forbidden"};let result=await provider.updateSubscription({providerSubscriptionId:existing.provider_subscription_id,items:body.items,cancelAtPeriodEnd:body.cancelAtPeriodEnd,metadata:body.metadata,collectionMethod:body.collectionMethod,daysUntilDue:body.daysUntilDue,defaultPaymentMethod:body.defaultPaymentMethod,prorationBehavior:body.prorationBehavior});if(!result.success)return ctx.set.status=400,result;let updates={};if(result.status)updates.status=result.status;if(body.cancelAtPeriodEnd!==void 0)updates.cancel_at_period_end=body.cancelAtPeriodEnd;if(body.items)updates.items=body.items;if(body.metadata)updates.metadata=body.metadata;if(body.collectionMethod)updates.collection_method=body.collectionMethod;let[updated]=await database.update(subTable).set(updates).where(eq59(subTable.id,id)).returning();return{success:!0,subscription:updated}}catch(error3){return logger2.error("[Payment] Update subscription error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to update subscription"}}}),app.post("/subscriptions/:id/cancel",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,body=ctx.body??{},[existing]=await database.select().from(subTable).where(eq59(subTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Subscription not found"};if(!await customerBelongsToCaller(ctx.request,existing.customer_id))return ctx.set.status=403,{success:!1,error:"Forbidden"};let result=await provider.cancelSubscription({providerSubscriptionId:existing.provider_subscription_id,cancelAtPeriodEnd:body.cancelAtPeriodEnd,invoiceNow:body.invoiceNow,prorate:body.prorate});if(!result.success)return ctx.set.status=400,result;let updates={status:result.status??"canceled",canceled_at:new Date};if(body.cancelAtPeriodEnd)updates.cancel_at_period_end=!0;let[updated]=await database.update(subTable).set(updates).where(eq59(subTable.id,id)).returning();return{success:!0,subscription:updated}}catch(error3){return logger2.error("[Payment] Cancel subscription error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to cancel subscription"}}}),app.get("/subscriptions",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let query=ctx.query,conditions=[];if(query.customerId)conditions.push(eq59(subTable.customer_id,query.customerId));if(query.status)conditions.push(eq59(subTable.status,query.status));if(!hasGodminRole(ctx.request)){let ids=await callerCustomerIds(userId);if(ids.length===0)return{success:!0,subscriptions:[]};conditions.push(inArray17(subTable.customer_id,ids))}return{success:!0,subscriptions:conditions.length>0?await database.select().from(subTable).where(and21(...conditions)):await database.select().from(subTable)}}catch(error3){return logger2.error("[Payment] List subscriptions error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to list subscriptions"}}}),app.get("/subscriptions/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,[subscription]=await database.select().from(subTable).where(eq59(subTable.id,id));if(!subscription)return ctx.set.status=404,{success:!1,error:"Subscription not found"};if(!await customerBelongsToCaller(ctx.request,subscription.customer_id))return ctx.set.status=403,{success:!1,error:"Forbidden"};return{success:!0,subscription}}catch(error3){return logger2.error("[Payment] Get subscription error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to get subscription"}}}),app.post("/usage-records",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let body=ctx.body,result=await provider.reportUsage({subscriptionItemId:body.subscriptionItemId,quantity:body.quantity,timestamp:body.timestamp,action:body.action});if(!result.success)return ctx.set.status=400,result;return{success:!0,usageRecord:result}}catch(error3){return logger2.error("[Payment] Report usage error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to report usage"}}}),app.get("/usage-records/:subscriptionItemId/summaries",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{subscriptionItemId}=ctx.params,query=ctx.query,result=await provider.listUsageRecordSummaries({subscriptionItemId,limit:query.limit?parseInt(query.limit,10):void 0,startingAfter:query.startingAfter});if(!result.success)return ctx.set.status=400,result;return{success:!0,summaries:result.summaries,hasMore:result.hasMore}}catch(error3){return logger2.error("[Payment] List usage summaries error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to list usage summaries"}}}),app.post("/invoices",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let body=ctx.body,customerId=body.customerId,[customer]=await database.select().from(cusTable).where(eq59(cusTable.id,customerId));if(!customer)return ctx.set.status=404,{success:!1,error:"Customer not found"};if(String(customer.user_id)!==String(userId)&&!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden"};let result=await provider.createInvoice({providerCustomerId:customer.provider_customer_id,collectionMethod:body.collectionMethod,daysUntilDue:body.daysUntilDue,description:body.description,metadata:body.metadata,autoAdvance:body.autoAdvance,items:body.items});if(!result.success)return ctx.set.status=400,result;let[row]=await database.insert(invTable).values({customer_id:customerId,subscription_id:body.subscriptionId??null,provider:provider.name,provider_invoice_id:result.providerInvoiceId,status:result.status??"draft",collection_method:body.collectionMethod??"charge_automatically",currency:body.currency??defaultCurrency,description:body.description??null,hosted_invoice_url:result.hostedInvoiceUrl??null,invoice_pdf:result.invoicePdf??null,days_until_due:body.daysUntilDue??null,lines:body.items??[],metadata:body.metadata??{}}).returning();return{success:!0,invoice:row,providerInvoiceId:result.providerInvoiceId}}catch(error3){return logger2.error("[Payment] Create invoice error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to create invoice"}}}),app.post("/invoices/:id/finalize",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,body=ctx.body??{},[existing]=await database.select().from(invTable).where(eq59(invTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Invoice not found"};if(!await customerBelongsToCaller(ctx.request,existing.customer_id))return ctx.set.status=403,{success:!1,error:"Forbidden"};let result=await provider.finalizeInvoice({providerInvoiceId:existing.provider_invoice_id,autoAdvance:body.autoAdvance});if(!result.success)return ctx.set.status=400,result;let[updated]=await database.update(invTable).set({status:result.status??"open",hosted_invoice_url:result.hostedInvoiceUrl??existing.hosted_invoice_url,invoice_pdf:result.invoicePdf??existing.invoice_pdf}).where(eq59(invTable.id,id)).returning();return{success:!0,invoice:updated}}catch(error3){return logger2.error("[Payment] Finalize invoice error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to finalize invoice"}}}),app.post("/invoices/:id/send",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,[existing]=await database.select().from(invTable).where(eq59(invTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Invoice not found"};if(!await customerBelongsToCaller(ctx.request,existing.customer_id))return ctx.set.status=403,{success:!1,error:"Forbidden"};let result=await provider.sendInvoice({providerInvoiceId:existing.provider_invoice_id});if(!result.success)return ctx.set.status=400,result;return{success:!0}}catch(error3){return logger2.error("[Payment] Send invoice error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to send invoice"}}}),app.post("/invoices/:id/void",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,[existing]=await database.select().from(invTable).where(eq59(invTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Invoice not found"};if(!await customerBelongsToCaller(ctx.request,existing.customer_id))return ctx.set.status=403,{success:!1,error:"Forbidden"};let result=await provider.voidInvoice({providerInvoiceId:existing.provider_invoice_id});if(!result.success)return ctx.set.status=400,result;let[updated]=await database.update(invTable).set({status:"void",voided_at:new Date}).where(eq59(invTable.id,id)).returning();return{success:!0,invoice:updated}}catch(error3){return logger2.error("[Payment] Void invoice error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to void invoice"}}}),app.post("/invoices/:id/pay",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,body=ctx.body??{},[existing]=await database.select().from(invTable).where(eq59(invTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Invoice not found"};if(!await customerBelongsToCaller(ctx.request,existing.customer_id))return ctx.set.status=403,{success:!1,error:"Forbidden"};let result=await provider.payInvoice({providerInvoiceId:existing.provider_invoice_id,paymentMethod:body.paymentMethod});if(!result.success)return ctx.set.status=400,result;let[updated]=await database.update(invTable).set({status:result.status??"paid",amount_paid:result.amountPaid??existing.amount_paid,amount_due:result.amountDue??existing.amount_due,paid_at:new Date}).where(eq59(invTable.id,id)).returning();return{success:!0,invoice:updated}}catch(error3){return logger2.error("[Payment] Pay invoice error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to pay invoice"}}}),app.get("/invoices",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let query=ctx.query,conditions=[];if(query.customerId)conditions.push(eq59(invTable.customer_id,query.customerId));if(query.subscriptionId)conditions.push(eq59(invTable.subscription_id,query.subscriptionId));if(query.status)conditions.push(eq59(invTable.status,query.status));if(!hasGodminRole(ctx.request)){let ids=await callerCustomerIds(userId);if(ids.length===0)return{success:!0,invoices:[]};conditions.push(inArray17(invTable.customer_id,ids))}return{success:!0,invoices:conditions.length>0?await database.select().from(invTable).where(and21(...conditions)):await database.select().from(invTable)}}catch(error3){return logger2.error("[Payment] List invoices error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to list invoices"}}}),app.get("/invoices/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,[invoice]=await database.select().from(invTable).where(eq59(invTable.id,id));if(!invoice)return ctx.set.status=404,{success:!1,error:"Invoice not found"};if(!await customerBelongsToCaller(ctx.request,invoice.customer_id))return ctx.set.status=403,{success:!1,error:"Forbidden"};return{success:!0,invoice}}catch(error3){return logger2.error("[Payment] Get invoice error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to get invoice"}}}),subMerchantsEnabled)app.post("/sub-merchants",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};let body=ctx.body;if(!body.name||!body.email||!body.subMerchantType)return ctx.set.status=400,{success:!1,error:"name, email, and subMerchantType are required"};try{let externalId=body.externalId??`sm-${Date.now().toString(36)}`,result=await provider.registerSubMerchant({locale:body.locale??defaultLocale,subMerchantExternalId:externalId,subMerchantType:body.subMerchantType,name:body.name,email:body.email,gsmNumber:body.gsmNumber,address:body.address,iban:body.iban,contactName:body.contactName,contactSurname:body.contactSurname,identityNumber:body.identityNumber,taxOffice:body.taxOffice,taxNumber:body.taxNumber,legalCompanyTitle:body.legalCompanyTitle,currency:body.currency??defaultCurrency});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to register sub-merchant",errorCode:result.errorCode};let[saved]=await database.insert(smTable).values({userId:hasGodminRole(ctx.request)?body.userId??userId:userId,provider:provider.name,providerSubMerchantKey:result.subMerchantKey,externalId,type:body.subMerchantType,status:"active",name:body.name,email:body.email,gsmNumber:body.gsmNumber??null,address:body.address??null,iban:body.iban??null,contactName:body.contactName??null,contactSurname:body.contactSurname??null,identityNumber:body.identityNumber??null,taxOffice:body.taxOffice??null,taxNumber:body.taxNumber??null,legalCompanyTitle:body.legalCompanyTitle??null,currency:body.currency??defaultCurrency,commissionRate:hasGodminRole(ctx.request)?body.commissionRate??0:0}).returning();return logger2.info("[Payment] Sub-merchant registered",{externalId,providerKey:result.subMerchantKey}),{success:!0,data:saved}}catch(error3){return logger2.error("[Payment] register sub-merchant error",{error:error3 instanceof Error?error3.message:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to register sub-merchant"}}}),app.put("/sub-merchants/:id",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};let body=ctx.body;try{let[existing]=await database.select().from(smTable).where(eq59(smTable.id,ctx.params.id)).limit(1);if(!existing)return ctx.set.status=404,{success:!1,error:"Sub-merchant not found"};let smIsGodmin=hasGodminRole(ctx.request);if(String(existing.userId)!==String(userId)&&!smIsGodmin)return ctx.set.status=403,{success:!1,error:"Forbidden"};if(existing.providerSubMerchantKey){let providerResult=await provider.updateSubMerchant({locale:body.locale??defaultLocale,subMerchantKey:existing.providerSubMerchantKey,name:body.name,email:body.email,gsmNumber:body.gsmNumber,address:body.address,iban:body.iban,contactName:body.contactName,contactSurname:body.contactSurname,identityNumber:body.identityNumber,taxOffice:body.taxOffice,taxNumber:body.taxNumber,legalCompanyTitle:body.legalCompanyTitle,currency:body.currency});if(!providerResult.success)logger2.warn("[Payment] Provider sub-merchant update failed",{errorCode:providerResult.errorCode})}let updateData={};if(body.name)updateData.name=body.name;if(body.email)updateData.email=body.email;if(body.gsmNumber!==void 0)updateData.gsmNumber=body.gsmNumber;if(body.address!==void 0)updateData.address=body.address;if(body.iban!==void 0)updateData.iban=body.iban;if(body.contactName!==void 0)updateData.contactName=body.contactName;if(body.contactSurname!==void 0)updateData.contactSurname=body.contactSurname;if(body.identityNumber!==void 0)updateData.identityNumber=body.identityNumber;if(body.taxOffice!==void 0)updateData.taxOffice=body.taxOffice;if(body.taxNumber!==void 0)updateData.taxNumber=body.taxNumber;if(body.legalCompanyTitle!==void 0)updateData.legalCompanyTitle=body.legalCompanyTitle;if(body.currency!==void 0)updateData.currency=body.currency;if(body.commissionRate!==void 0&&smIsGodmin)updateData.commissionRate=body.commissionRate;if(body.status!==void 0&&smIsGodmin)updateData.status=body.status;let[updated]=await database.update(smTable).set(updateData).where(eq59(smTable.id,ctx.params.id)).returning();return{success:!0,data:updated}}catch{return ctx.set.status=500,{success:!1,error:"Failed to update sub-merchant"}}}),app.get("/sub-merchants",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let smListGodmin=hasGodminRole(ctx.request);return{success:!0,data:{items:await database.select().from(smTable).where(smListGodmin?eq59(smTable.isActive,!0):and21(eq59(smTable.isActive,!0),eq59(smTable.userId,userId))).orderBy(smTable.createdAt)}}}catch{return ctx.set.status=500,{success:!1,error:"Failed to list sub-merchants"}}}),app.get("/sub-merchants/:id",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let[item]=await database.select().from(smTable).where(eq59(smTable.id,ctx.params.id)).limit(1);if(!item)return ctx.set.status=404,{success:!1,error:"Sub-merchant not found"};if(String(item.userId)!==String(userId)&&!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden"};return{success:!0,data:item}}catch{return ctx.set.status=500,{success:!1,error:"Failed to get sub-merchant"}}}),app.post("/splits/:splitId/approve",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};if(!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden: operator privileges required"};try{let[split]=await database.select().from(csTable).where(eq59(csTable.id,ctx.params.splitId)).limit(1);if(!split)return ctx.set.status=404,{success:!1,error:"Split not found"};if(split.status!=="pending")return ctx.set.status=400,{success:!1,error:`Split already ${split.status}`};if(split.providerSplitId){let result=await provider.approveSplit({locale:defaultLocale,paymentTransactionId:split.providerSplitId});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Provider approval failed",errorCode:result.errorCode}}let[updated]=await database.update(csTable).set({status:"approved",approvedAt:new Date}).where(eq59(csTable.id,ctx.params.splitId)).returning();return logger2.info("[Payment] Split approved",{splitId:ctx.params.splitId}),{success:!0,data:updated}}catch{return ctx.set.status=500,{success:!1,error:"Failed to approve split"}}}),app.post("/splits/:splitId/disapprove",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};if(!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden: operator privileges required"};try{let[split]=await database.select().from(csTable).where(eq59(csTable.id,ctx.params.splitId)).limit(1);if(!split)return ctx.set.status=404,{success:!1,error:"Split not found"};if(split.status!=="pending")return ctx.set.status=400,{success:!1,error:`Split already ${split.status}`};if(split.providerSplitId){let result=await provider.disapproveSplit({locale:defaultLocale,paymentTransactionId:split.providerSplitId});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Provider disapproval failed",errorCode:result.errorCode}}let[updated]=await database.update(csTable).set({status:"disapproved",disapprovedAt:new Date}).where(eq59(csTable.id,ctx.params.splitId)).returning();return logger2.info("[Payment] Split disapproved",{splitId:ctx.params.splitId}),{success:!0,data:updated}}catch{return ctx.set.status=500,{success:!1,error:"Failed to disapprove split"}}}),app.get("/splits",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};if(!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden: operator privileges required"};try{let url=new URL(ctx.request.url),transactionId=url.searchParams.get("transactionId"),subMerchantId=url.searchParams.get("subMerchantId"),query=database.select().from(csTable);if(transactionId&&subMerchantId)query=query.where(and21(eq59(csTable.transactionId,transactionId),eq59(csTable.subMerchantId,subMerchantId)));else if(transactionId)query=query.where(eq59(csTable.transactionId,transactionId));else if(subMerchantId)query=query.where(eq59(csTable.subMerchantId,subMerchantId));return{success:!0,data:{items:await query.orderBy(csTable.createdAt)}}}catch{return ctx.set.status=500,{success:!1,error:"Failed to list splits"}}});return app.get("/balance",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let result=await provider.getBalance();if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to get balance"};return{success:!0,data:{available:result.available,pending:result.pending,connectReserved:result.connectReserved}}}catch{return ctx.set.status=500,{success:!1,error:"Failed to get balance"}}}),app.post("/payouts",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};if(!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden: operator privileges required"};try{let body=ctx.body,payoutAmt=validateAmount(body.amount,"amount");if(!payoutAmt.ok)return ctx.set.status=400,{success:!1,error:payoutAmt.error};if(!isValidCurrency(body.currency))return ctx.set.status=400,{success:!1,error:"currency must be a 3-letter code"};let result=await provider.createPayout({amount:payoutAmt.value,currency:body.currency??defaultCurrency,destination:body.destination,description:body.description,metadata:body.metadata,method:body.method,sourceType:body.sourceType,statementDescriptor:body.statementDescriptor});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to create payout"};return{success:!0,data:result}}catch{return ctx.set.status=500,{success:!1,error:"Failed to create payout"}}}),app.get("/payouts",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let url=new URL(ctx.request.url),result=await provider.listPayouts({status:url.searchParams.get("status")??void 0,destination:url.searchParams.get("destination")??void 0,limit:url.searchParams.get("limit")?Number(url.searchParams.get("limit")):void 0,startingAfter:url.searchParams.get("startingAfter")??void 0});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to list payouts"};return{success:!0,data:{payouts:result.payouts,hasMore:result.hasMore}}}catch{return ctx.set.status=500,{success:!1,error:"Failed to list payouts"}}}),app.get("/payouts/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let result=await provider.getPayout({providerPayoutId:ctx.params.id});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to get payout"};return{success:!0,data:result}}catch{return ctx.set.status=500,{success:!1,error:"Failed to get payout"}}}),app.post("/payouts/:id/cancel",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};if(!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden: operator privileges required"};try{let result=await provider.cancelPayout({providerPayoutId:ctx.params.id});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to cancel payout"};return{success:!0,data:result}}catch{return ctx.set.status=500,{success:!1,error:"Failed to cancel payout"}}}),app.post("/transfers",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};if(!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden: operator privileges required"};try{let body=ctx.body,transferAmt=validateAmount(body.amount,"amount");if(!transferAmt.ok)return ctx.set.status=400,{success:!1,error:transferAmt.error};if(!isValidCurrency(body.currency))return ctx.set.status=400,{success:!1,error:"currency must be a 3-letter code"};let result=await provider.createTransfer({amount:transferAmt.value,currency:body.currency??defaultCurrency,destination:body.destination,description:body.description,metadata:body.metadata,sourceTransaction:body.sourceTransaction,transferGroup:body.transferGroup});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to create transfer"};return{success:!0,data:result}}catch{return ctx.set.status=500,{success:!1,error:"Failed to create transfer"}}}),app.get("/transfers",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let url=new URL(ctx.request.url),result=await provider.listTransfers({destination:url.searchParams.get("destination")??void 0,transferGroup:url.searchParams.get("transferGroup")??void 0,limit:url.searchParams.get("limit")?Number(url.searchParams.get("limit")):void 0,startingAfter:url.searchParams.get("startingAfter")??void 0});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to list transfers"};return{success:!0,data:{transfers:result.transfers,hasMore:result.hasMore}}}catch{return ctx.set.status=500,{success:!1,error:"Failed to list transfers"}}}),app.options("/callback",()=>{return new Response(null,{headers:{"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET,POST,OPTIONS","Access-Control-Allow-Headers":"Content-Type"}})}),registerStripeWebhookRoute(app,{provider,webhookSecret:config.webhookSecret,db:database,webhookLogsTable:whTable,transactionsTable:txTable,getPayoutService:config.getPayoutService,logger:logger2}),app};var init_payment=__esm(()=>{init_adminGuard();init_webhook()});var requireUser=(ctx)=>ctx.request.headers.get("x-user-id"),isAdmin=(ctx)=>decodeHeaderList(ctx.request.headers.get("x-user-roles")).some((r2)=>isGodminRole(r2)),canReadOwnerLedger=(ctx,ownerType,ownerId)=>{if(isAdmin(ctx))return!0;let userId=ctx.request.headers.get("x-user-id");return!!userId&&ownerType==="user"&&!!ownerId&&ownerId===userId},failResponse=(ctx,status,message)=>{return ctx.set.status=status,{success:!1,message,data:null}};var init_types22=__esm(()=>{init_Authorization()});import{Elysia as Elysia48,t as t40}from"elysia";function createPayoutRoutes(config){let base=`${config.basePath}/marketplace`,app=new Elysia48;return app.post(`${base}/payout-requests`,async(ctx)=>{let svc=config.getPayoutService();if(!svc)return failResponse(ctx,503,"Marketplace not available");let userId=requireUser(ctx);if(!userId)return failResponse(ctx,401,"Authentication required");let body=ctx.body;if(!canReadOwnerLedger(ctx,body.recipientOwnerType,body.recipientOwnerId))return failResponse(ctx,403,"Forbidden: cannot request a payout for another owner's balance");try{return{success:!0,message:"Payout requested",data:await svc.requestPayout({...body,requestedBy:userId})}}catch(err){return failResponse(ctx,400,err instanceof Error?err.message:"Failed")}},{body:t40.Object({recipientOwnerId:t40.String(),recipientOwnerType:t40.Optional(t40.String()),amount:t40.Number(),currency:t40.Optional(t40.String()),destination:t40.Optional(t40.String()),requestedBy:t40.Optional(t40.String())}),detail:{tags:["Payments Marketplace"],summary:"Request a payout"}}),app.get(`${base}/payout-requests`,async(ctx)=>{let svc=config.getPayoutService();if(!svc)return failResponse(ctx,503,"Marketplace not available");let userId=requireUser(ctx);if(!userId)return failResponse(ctx,401,"Authentication required");let url=new URL(ctx.request.url),requestedOwnerId=url.searchParams.get("recipientOwnerId")??void 0,recipientOwnerId=isAdmin(ctx)?requestedOwnerId:userId,items=await svc.listPayoutRequests({recipientOwnerId,status:url.searchParams.get("status")??void 0});return{success:!0,message:`Found ${items.length} payout requests`,data:{items}}}),app.get(`${base}/payout-requests/:id`,async(ctx)=>{let svc=config.getPayoutService();if(!svc)return failResponse(ctx,503,"Marketplace not available");if(!requireUser(ctx))return failResponse(ctx,401,"Authentication required");let record3=await svc.getPayoutRequest(ctx.params.id);if(!record3)return failResponse(ctx,404,"Payout request not found");let r2=record3;if(!canReadOwnerLedger(ctx,r2.recipientOwnerType,r2.recipientOwnerId))return failResponse(ctx,404,"Payout request not found");return{success:!0,message:"Payout request",data:record3}}),app.post(`${base}/payout-requests/:id/approve`,async(ctx)=>{let svc=config.getPayoutService();if(!svc)return failResponse(ctx,503,"Marketplace not available");let userId=requireUser(ctx);if(!userId)return failResponse(ctx,401,"Authentication required");if(!isAdmin(ctx))return failResponse(ctx,403,"Forbidden: operator privileges required");try{let record3=await svc.approvePayout(ctx.params.id,{deciderId:userId});if(!record3)return failResponse(ctx,404,"Payout request not found");return{success:!0,message:"Payout approved",data:record3}}catch(err){return failResponse(ctx,400,err instanceof Error?err.message:"Failed")}}),app.post(`${base}/payout-requests/:id/reject`,async(ctx)=>{let svc=config.getPayoutService();if(!svc)return failResponse(ctx,503,"Marketplace not available");let userId=requireUser(ctx);if(!userId)return failResponse(ctx,401,"Authentication required");if(!isAdmin(ctx))return failResponse(ctx,403,"Forbidden: operator privileges required");let record3=await svc.rejectPayout(ctx.params.id,userId);if(!record3)return failResponse(ctx,404,"Payout request not found");return{success:!0,message:"Payout rejected",data:record3}}),app.post(`${base}/disputes`,async(ctx)=>{let svc=config.getPayoutService();if(!svc)return failResponse(ctx,503,"Marketplace not available");if(!requireUser(ctx))return failResponse(ctx,401,"Authentication required");if(!isAdmin(ctx))return failResponse(ctx,403,"Forbidden: operator privileges required");let body=ctx.body;return{success:!0,message:"Dispute opened",data:await svc.openDispute(body)}},{body:t40.Object({provider:t40.String(),transactionId:t40.Optional(t40.String()),providerDisputeId:t40.Optional(t40.String()),ownerType:t40.Optional(t40.String()),ownerId:t40.Optional(t40.String()),amount:t40.Optional(t40.Number()),currency:t40.Optional(t40.String()),reason:t40.Optional(t40.String())}),detail:{tags:["Payments Marketplace"],summary:"Open a dispute"}}),app.get(`${base}/disputes`,async(ctx)=>{let svc=config.getPayoutService();if(!svc)return failResponse(ctx,503,"Marketplace not available");let userId=requireUser(ctx);if(!userId)return failResponse(ctx,401,"Authentication required");let url=new URL(ctx.request.url),requestedOwnerId=url.searchParams.get("ownerId")??void 0,ownerId=isAdmin(ctx)?requestedOwnerId:userId,items=await svc.listDisputes({ownerId,status:url.searchParams.get("status")??void 0});return{success:!0,message:`Found ${items.length} disputes`,data:{items}}}),app.post(`${base}/disputes/:id/resolve`,async(ctx)=>{let svc=config.getPayoutService();if(!svc)return failResponse(ctx,503,"Marketplace not available");if(!requireUser(ctx))return failResponse(ctx,401,"Authentication required");if(!isAdmin(ctx))return failResponse(ctx,403,"Forbidden: operator privileges required");let body=ctx.body,record3=await svc.resolveDispute(ctx.params.id,body.outcome);if(!record3)return failResponse(ctx,404,"Dispute not found");return{success:!0,message:"Dispute resolved",data:record3}},{body:t40.Object({outcome:t40.Union([t40.Literal("won"),t40.Literal("lost"),t40.Literal("accepted"),t40.Literal("cancelled")])}),detail:{tags:["Payments Marketplace"],summary:"Resolve a dispute"}}),app}var init_payouts=__esm(()=>{init_types22()});import{Elysia as Elysia49,t as t41}from"elysia";function createSplitRoutes(config){let base=`${config.basePath}/marketplace`,app=new Elysia49;return app.post(`${base}/splits`,async(ctx)=>{let svc=config.getMarketplaceService();if(!svc)return failResponse(ctx,503,"Marketplace not available");if(!requireUser(ctx))return failResponse(ctx,401,"Authentication required");if(!isAdmin(ctx))return failResponse(ctx,403,"Forbidden: operator privileges required");let body=ctx.body;try{return{success:!0,message:"Split recorded",data:await svc.recordSplit(body)}}catch(err){return failResponse(ctx,400,err instanceof Error?err.message:"Failed")}},{body:t41.Object({recipientOwnerId:t41.String(),recipientOwnerType:t41.Optional(t41.String()),provider:t41.String(),grossAmount:t41.Number(),providerFeeAmount:t41.Optional(t41.Number()),platformFeeAmount:t41.Number(),currency:t41.Optional(t41.String()),transactionId:t41.Optional(t41.String()),sourceType:t41.Optional(t41.String()),sourceId:t41.Optional(t41.String()),settlementDelayDays:t41.Optional(t41.Number()),reserveRate:t41.Optional(t41.Number()),isNewSeller:t41.Optional(t41.Boolean())}),detail:{tags:["Payments Marketplace"],summary:"Record a payment split"}}),app.get(`${base}/splits`,async(ctx)=>{let svc=config.getMarketplaceService();if(!svc)return failResponse(ctx,503,"Marketplace not available");let userId=requireUser(ctx);if(!userId)return failResponse(ctx,401,"Authentication required");let url=new URL(ctx.request.url),requestedOwnerId=url.searchParams.get("recipientOwnerId")??void 0,recipientOwnerId=isAdmin(ctx)?requestedOwnerId:userId,items=await svc.listSplits({recipientOwnerId,status:url.searchParams.get("status")??void 0});return{success:!0,message:`Found ${items.length} splits`,data:{items}}}),app.get(`${base}/balance/:ownerId`,async(ctx)=>{let svc=config.getMarketplaceService();if(!svc)return failResponse(ctx,503,"Marketplace not available");if(!requireUser(ctx))return failResponse(ctx,401,"Authentication required");let url=new URL(ctx.request.url),ownerType=url.searchParams.get("ownerType")??"seller",ownerId=ctx.params.ownerId;if(!canReadOwnerLedger(ctx,ownerType,ownerId))return failResponse(ctx,403,"Forbidden: cannot read another owner's balance");return{success:!0,message:"Balance",data:await svc.getBalance(ownerType,ownerId,url.searchParams.get("currency")??void 0)}}),app.post(`${base}/reserves/:id/release`,async(ctx)=>{let svc=config.getMarketplaceService();if(!svc)return failResponse(ctx,503,"Marketplace not available");if(!requireUser(ctx))return failResponse(ctx,401,"Authentication required");if(!isAdmin(ctx))return failResponse(ctx,403,"Forbidden: operator privileges required");if(!await svc.releaseReserve(ctx.params.id))return failResponse(ctx,400,"Reserve not found or not held");return{success:!0,message:"Reserve released",data:{released:!0}}}),app.get(`${base}/settlement-policy`,async(ctx)=>{let svc=config.getMarketplaceService();if(!svc)return failResponse(ctx,503,"Marketplace not available");if(!requireUser(ctx))return failResponse(ctx,401,"Authentication required");let url=new URL(ctx.request.url),ownerType=url.searchParams.get("ownerType")??"tenant",ownerId=url.searchParams.get("ownerId")??"";if(!canReadOwnerLedger(ctx,ownerType,ownerId))return failResponse(ctx,403,"Forbidden: cannot read this settlement policy");return{success:!0,message:"Settlement policy",data:await svc.getSettlementPolicy(ownerType,ownerId)}}),app.post(`${base}/settlement-policy`,async(ctx)=>{let svc=config.getMarketplaceService();if(!svc)return failResponse(ctx,503,"Marketplace not available");if(!requireUser(ctx))return failResponse(ctx,401,"Authentication required");if(!isAdmin(ctx))return failResponse(ctx,403,"Forbidden: operator privileges required");let body=ctx.body;return{success:!0,message:"Settlement policy saved",data:await svc.upsertSettlementPolicy(body)}},{body:t41.Object({ownerType:t41.String(),ownerId:t41.String(),defaultDelayDays:t41.Optional(t41.Number()),newSellerDelayDays:t41.Optional(t41.Number()),reserveRate:t41.Optional(t41.Number()),reserveDays:t41.Optional(t41.Number()),minimumPayoutAmount:t41.Optional(t41.Number()),currency:t41.Optional(t41.String()),earlyPayoutEnabled:t41.Optional(t41.Boolean())}),detail:{tags:["Payments Marketplace"],summary:"Upsert settlement policy"}}),app}var init_splits=__esm(()=>{init_types22()});var exports_marketplace={};__export(exports_marketplace,{createMarketplaceRoutes:()=>createMarketplaceRoutes});function createMarketplaceRoutes(app,config){return app.use(createSplitRoutes(config)),app.use(createPayoutRoutes(config)),app}var init_marketplace=__esm(()=>{init_payouts();init_splits()});var exports_schemaReconcile={};__export(exports_schemaReconcile,{undeclaredTables:()=>undeclaredTables,reconcileMissingColumns:()=>reconcileMissingColumns,readActualSchema:()=>readActualSchema,planRepair:()=>planRepair,findDrift:()=>findDrift,expectedFromTables:()=>expectedFromTables,describeRepair:()=>describeRepair,createMissingTables:()=>createMissingTables,addColumnStatement:()=>addColumnStatement});import{getTableColumns,sql as sql12}from"drizzle-orm";function findDrift(expected,actual){let missingTables=[],missingColumns=[];for(let table of expected){let have=actual[table.name];if(!have){missingTables.push(table.name);continue}for(let column of table.columns)if(!have.has(column.name))missingColumns.push({table:table.name,column})}return{missingTables,missingColumns}}function addColumnStatement(schema3,table,column){if(column.notNull&&!column.hasDefault)return null;return[`alter table "${schema3}"."${table}"`,`add column if not exists "${column.name}" ${column.sqlType}`].join(" ")}function planRepair(schema3,drift){let statements=[],unsafe3=[];for(let{table,column}of drift.missingColumns){let statement=addColumnStatement(schema3,table,column);if(statement)statements.push(statement);else unsafe3.push({table,column:column.name,why:"declared NOT NULL with no default, and the table already has rows to fill"})}return{statements,unsafe:unsafe3,missingTables:drift.missingTables,createdTables:[],undeclaredTables:[]}}function undeclaredTables(expected,actual){let declared=new Set(expected.map((t42)=>t42.name));return Object.keys(actual).filter((name2)=>!declared.has(name2)).sort()}function isAlreadyExists(error3){let code=error3?.code;if(typeof code==="string"&&ALREADY_EXISTS.has(code))return!0;let message=error3 instanceof Error?error3.message:String(error3);return/already exists/i.test(message)}async function createMissingTables(options){let{run,tables,missing,schemaObject,logger:logger2,timeoutMs=60000}=options;if(missing.length===0)return{applied:0,errors:[]};let wanted=new Set(missing),imports={};for(let[key2,table]of Object.entries(tables)){if(!table||typeof table!=="object")continue;let name2=tableNameOf(table);if(name2&&wanted.has(name2))imports[key2]=table}if(schemaObject)imports.__nucleusSchema=schemaObject;let statements;try{let{generateDrizzleJson,generateMigration}=await import("drizzle-kit/api"),realExit=process.exit;try{process.exit=(code)=>{throw Error(`drizzle-kit called process.exit(${code??0}) while generating table DDL`)},statements=await withDeadline(generateMigration(generateDrizzleJson({}),generateDrizzleJson(imports)),timeoutMs,`generating CREATE TABLE statements did not finish within ${timeoutMs}ms`)}finally{process.exit=realExit}}catch(error3){let message=error3 instanceof Error?error3.message:String(error3);return logger2.error(`[Schema] CREATE TABLE statements could not be generated: ${message}`),{applied:0,errors:[message]}}let applied=0,errors3=[];for(let statement of statements)try{await run(statement),applied+=1}catch(error3){if(isAlreadyExists(error3))continue;let message=error3 instanceof Error?error3.message:String(error3);errors3.push(message),logger2.error(`[Schema] could not apply generated DDL: ${statement} \u2014 ${message}`)}return{applied,errors:errors3}}function describeRepair(plan,applied){let lines=[];if(applied>0)lines.push(`[Schema] The push applied nothing, so ${applied} missing column(s) were added directly. `+"This is additive only \u2014 nothing was dropped or altered.");if(plan.createdTables.length>0)lines.push(`[Schema] ${plan.createdTables.length} table(s) the push did not create were created directly: ${plan.createdTables.join(", ")}. Verified present in the database afterwards, not assumed from the statements that ran.`);if(plan.missingTables.length>0){if(lines.push(`[Schema] ${plan.missingTables.length} table(s) the code expects still do not exist: ${plan.missingTables.join(", ")}. Every read of these will fail. The additive repair tried `+"and could not create them \u2014 this needs a human."),plan.undeclaredTables.length>0)lines.push(`[Schema] The push is ambiguous because the database has ${plan.undeclaredTables.length} table(s) the model does not declare: ${plan.undeclaredTables.join(", ")}. drizzle-kit cannot tell a new table from a rename of one of these, and cannot ask without a TTY. Drop the stale one, or declare it, and the push stops aborting.`)}for(let item of plan.unsafe)lines.push(`[Schema] "${item.table}"."${item.column}" could not be added: ${item.why}. Give the column a default, or add it by hand with a backfill.`);return lines}function expectedFromTables(tables){let out=[];for(let table of Object.values(tables)){if(!table||typeof table!=="object")continue;let columns;try{columns=getTableColumns(table)}catch{continue}let first=Object.values(columns)[0],name2=tableNameOf(table);if(!name2||!first)continue;out.push({name:name2,columns:Object.values(columns).map((column)=>{let c=column;return{name:c.name,sqlType:typeof c.getSQLType==="function"?c.getSQLType():"text",notNull:c.notNull===!0,hasDefault:c.hasDefault===!0}})})}return out}function tableNameOf(table){for(let key2 of Object.getOwnPropertySymbols(table))if(String(key2).includes("Name")&&!String(key2).includes("Schema")){let value2=table[key2];if(typeof value2==="string"&&value2.length>0)return value2}return null}async function readActualSchema(execute,schema3){let result=await execute(`select table_name, column_name from information_schema.columns where table_schema = '${schema3.replace(/'/g,"''")}'`),rows=Array.isArray(result)?result:result.rows??[],actual={};for(let row of rows){if(!row.table_name||!row.column_name)continue;(actual[row.table_name]??=new Set).add(row.column_name)}return actual}async function reconcileMissingColumns(options){let{db,schema:schema3,tables,logger:logger2,schemaObject}=options,run=(statement)=>db.execute(sql12.raw(statement));try{let expected=expectedFromTables(tables);if(expected.length===0)return null;let actual=await readActualSchema(run,schema3),drift=findDrift(expected,actual),plan=planRepair(schema3,drift);if(plan.undeclaredTables=undeclaredTables(expected,actual),drift.missingTables.length>0){await createMissingTables({run,tables,missing:drift.missingTables,schemaObject,logger:logger2});let after=await readActualSchema(run,schema3);plan.createdTables=drift.missingTables.filter((name2)=>after[name2]),plan.missingTables=drift.missingTables.filter((name2)=>!after[name2])}let applied=0;for(let statement of plan.statements)try{await run(statement),applied+=1}catch(error3){logger2.error(`[Schema] could not add a missing column: ${statement} \u2014 ${error3 instanceof Error?error3.message:String(error3)}`)}for(let line of describeRepair(plan,applied))if(plan.missingTables.length>0||plan.unsafe.length>0)logger2.error(line);else logger2.info(line);return{applied,plan}}catch(error3){return logger2.error(`[Schema] the additive repair could not run: ${error3 instanceof Error?error3.message:String(error3)}`),null}}var ALREADY_EXISTS;var init_schemaReconcile=__esm(()=>{ALREADY_EXISTS=new Set(["42P06","42P07","42710","42723","23505"])});function normSegment(input){return input.toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/_+/g,"_").replace(/^_|_$/g,"")}function normPath(path8){return normSegment(path8.replace(/\{[^}]+\}/g,(m2)=>m2.slice(1,-1)))}function shortHash(input){let h=5381;for(let i=0;i<input.length;i++)h=(h*33^input.charCodeAt(i))>>>0;return h.toString(36)}function capAction(action,max=100){if(action.length<=max)return action;let suffix=`_${shortHash(action)}`;return action.slice(0,Math.max(1,max-suffix.length))+suffix}function resourceFromPath(path8){let segs=path8.split("/").filter(Boolean).filter((s)=>!s.startsWith("{"));for(let s of segs){if(s==="api"||/^v\d+$/i.test(s))continue;return normSegment(s)}return normSegment(segs[0]??"root")}function matchesExclude(path8,patterns3){if(!patterns3?.length)return!1;for(let raw of patterns3){let p=raw.trim();if(!p)continue;if(p.endsWith("/*")){let prefix=p.slice(0,-2);if(path8===prefix||path8.startsWith(`${prefix}/`))return!0}else if(p.endsWith("*")){if(path8.startsWith(p.slice(0,-1)))return!0}else if(path8===p)return!0}return!1}function parseOpenApiToClaims(serviceId,doc,opts={}){let sid=normSegment(serviceId);if(!sid)throw Error("endpointDiscovery: serviceId is empty after normalization");if(RESERVED_SERVICE_IDS.has(sid))throw Error(`endpointDiscovery: serviceId "${serviceId}" collides with an HTTP-method claim prefix; pick another id`);let specs=[],seen=new Set,paths=doc.paths??{};for(let[path8,ops]of Object.entries(paths)){if(!ops||matchesExclude(path8,opts.exclude))continue;for(let method of HTTP_METHODS2){let op=ops[method];if(!op)continue;let tag=(op.tags?.[0]?normSegment(op.tags[0]):"")||resourceFromPath(path8),opToken=(op.operationId?normSegment(op.operationId):"")||`${method}_${normPath(path8)}`,action=capAction(`${sid}.${tag||"root"}.${opToken||method}`);if(seen.has(action)){action=capAction(`${action}_${shortHash(`${method} ${path8}`)}`);while(seen.has(action))action=capAction(`${action}_${shortHash(action)}`)}seen.add(action),specs.push({action,path:path8,method:method.toUpperCase(),description:op.summary||op.description||`${method.toUpperCase()} ${path8}`})}}return specs}function diffClaims(existing,specs){let specByAction=new Map(specs.map((s)=>[s.action,s])),existByAction=new Map(existing.map((e)=>[e.action,e]));return{toInsert:specs.filter((s)=>!existByAction.has(s.action)),toReactivate:specs.filter((s)=>existByAction.get(s.action)?.isActive===!1),toDeactivate:existing.filter((e)=>e.isActive&&!specByAction.has(e.action)),unchanged:specs.filter((s)=>existByAction.get(s.action)?.isActive===!0)}}async function fetchOpenApi(baseUrl,openapiPath,fetchImpl=fetch){let url=`${baseUrl.replace(/\/$/,"")}${openapiPath.startsWith("/")?"":"/"}${openapiPath}`,res=await fetchImpl(url);if(!res.ok)throw Error(`endpointDiscovery: OpenAPI fetch failed ${res.status} for ${url}`);return await res.json()}var HTTP_METHODS2,RESERVED_SERVICE_IDS;var init_EndpointDiscovery=__esm(()=>{HTTP_METHODS2=["get","post","put","patch","delete"],RESERVED_SERVICE_IDS=new Set(["get","post","put","patch","delete","toggle","bulk"])});var exports_seed={};__export(exports_seed,{seedDiscoveredClaims:()=>seedDiscoveredClaims,runEndpointDiscovery:()=>runEndpointDiscovery,getRouteManifest:()=>getRouteManifest,getRoleClaimsManifest:()=>getRoleClaimsManifest});import{eq as eq60,like as like2}from"drizzle-orm";function col16(table,name2){return table[name2]}async function seedDiscoveredClaims(db,claimsTable,serviceId,specs,logger2){let actionCol=col16(claimsTable,"action"),prefix=specs[0]?.action.split(".")[0]??serviceId.toLowerCase(),existing=(await db.select().from(claimsTable).where(like2(actionCol,`${prefix}.%`))).map((r2)=>({action:String(r2.action),isActive:r2.isActive!==!1,path:String(r2.path??""),method:String(r2.method??""),description:String(r2.description??"")})),plan=diffClaims(existing,specs);for(let s of plan.toInsert)await db.insert(claimsTable).values({action:s.action,path:s.path,method:s.method,description:s.description});for(let s of plan.toReactivate)await db.update(claimsTable).set({isActive:!0,path:s.path,method:s.method,description:s.description}).where(eq60(actionCol,s.action));for(let e of plan.toDeactivate)await db.update(claimsTable).set({isActive:!1}).where(eq60(actionCol,e.action));let summary={added:plan.toInsert.length,reactivated:plan.toReactivate.length,deactivated:plan.toDeactivate.length,unchanged:plan.unchanged.length,total:specs.length};return logger2.info(`[Discovery] Reconciled "${serviceId}"`,summary),summary}async function runEndpointDiscovery(db,schemaTables,config,logger2,fetchImpl=fetch){let claimsTable=schemaTables.claims,services=config.services??[],results=[];if(!claimsTable)return logger2.warn("[Discovery] No claims table in schema; skipping endpoint discovery"),{services:[]};for(let svc of services)try{let doc=await fetchOpenApi(svc.baseUrl,svc.openapi??"/openapi.json",fetchImpl),specs=parseOpenApiToClaims(svc.id,doc,{exclude:svc.exclude}),summary=await seedDiscoveredClaims(db,claimsTable,svc.id,specs,logger2);results.push({id:svc.id,...summary})}catch(err){let message=err instanceof Error?err.message:String(err);logger2.error(`[Discovery] Service "${svc.id}" discovery failed`,{error:message}),results.push({id:svc.id,added:0,reactivated:0,deactivated:0,unchanged:0,total:0,error:message})}return{services:results}}async function getRouteManifest(db,claimsTable,serviceId){return(await db.select().from(claimsTable).where(like2(col16(claimsTable,"action"),`${serviceId.toLowerCase()}.%`))).filter((r2)=>r2.isActive!==!1).map((r2)=>({action:String(r2.action),path:String(r2.path??""),method:String(r2.method??"")}))}async function getRoleClaimsManifest(db,schemaTables,serviceId){let{roles:rolesTable,claims:claimsTable}=schemaTables,roleClaimsTable=schemaTables.roleClaims??schemaTables.role_claims;if(!rolesTable||!claimsTable||!roleClaimsTable)return{};let sid=serviceId.toLowerCase(),claimRows=await db.select().from(claimsTable),claimIdToAction=new Map;for(let c of claimRows){if(c.isActive===!1)continue;let action=String(c.action??"");if(action===sid||action.startsWith(`${sid}.`))claimIdToAction.set(String(c.id),action)}if(claimIdToAction.size===0)return{};let roleRows=await db.select().from(rolesTable),roleIdToName=new Map;for(let r2 of roleRows)roleIdToName.set(String(r2.id),String(r2.name??""));let rcRows=await db.select().from(roleClaimsTable),out={};for(let rc of rcRows){if(rc.isActive===!1)continue;let action=claimIdToAction.get(String(rc.claimId??rc.claim_id)),roleName=roleIdToName.get(String(rc.roleId??rc.role_id));if(!action||!roleName)continue;(out[roleName]??=[]).push(action)}return out}var init_seed=__esm(()=>{init_EndpointDiscovery()});var OPS_BY_TYPE;var init_types23=__esm(()=>{OPS_BY_TYPE={int:["gt","gte","lt","lte","eq","ne"],boolean:["eq","ne"],string:["eq","ne"]}});function isRecord(v){return typeof v==="object"&&v!==null}function guardActionFromName(name2){let brace=name2.indexOf("{");return(brace>=0?name2.slice(0,brace):name2).replace(/:$/,"")}function parseGuardCatalogEntry(entry){if(!isRecord(entry))return null;let name2=typeof entry.name==="string"?entry.name.trim():"";if(!name2)return null;let valueType=entry.value;if(typeof valueType!=="string"||!VALUE_TYPES.includes(valueType))return null;let action=guardActionFromName(name2);if(!action)return null;return{action,policy:{kind:"guard",keyTemplate:name2,valueType}}}function parseGuardPolicy(raw){if(!isRecord(raw)||raw.kind!=="guard")return null;if(typeof raw.keyTemplate!=="string"||!raw.keyTemplate)return null;let vt=raw.valueType;if(typeof vt!=="string"||!VALUE_TYPES.includes(vt))return null;return{kind:"guard",keyTemplate:raw.keyTemplate,valueType:vt}}function resolveGuardKey(keyTemplate,ctx){return keyTemplate.replaceAll("{userId}",ctx.userId).replaceAll("{tenant}",ctx.tenant??"default")}function coerceThreshold(value2,type4){if(type4==="int"){if(value2==null)return null;if(typeof value2==="boolean"||typeof value2==="symbol")return null;if(typeof value2==="string"&&value2.trim()==="")return null;if(typeof value2==="object")return null;let n2=Number(value2);return Number.isFinite(n2)?n2:null}if(type4==="boolean"){if(typeof value2==="boolean")return value2;if(value2==="true"||value2===1||value2==="1")return!0;if(value2==="false"||value2===0||value2==="0")return!1;return null}return value2==null?null:String(value2)}function parseGuardCondition(scope,valueType){let raw=scope;if(typeof scope==="string")try{raw=JSON.parse(scope)}catch{return null}if(!isRecord(raw))return null;let op=raw.op;if(typeof op!=="string"||!OPS_BY_TYPE[valueType].includes(op))return null;let value2=coerceThreshold(raw.value,valueType);if(value2===null)return null;let invalidates=Array.isArray(raw.invalidates)?raw.invalidates.filter((a12)=>typeof a12==="string"&&a12.length>0):[];return{op,value:value2,invalidates}}function coerceStateValue(raw,type4){if(raw==null)return null;let v=isRecord(raw)&&"data"in raw?raw.data:raw;if(v==null)return null;if(typeof v==="object")return null;if(type4==="int"&&typeof v==="string"&&v.trim()==="")return null;return coerceThreshold(v,type4)}function guardConditionHolds(rawValue,valueType,condition){let actual=coerceStateValue(rawValue,valueType);if(actual===null)return!1;let target2=condition.value;switch(condition.op){case"gt":return actual>target2;case"gte":return actual>=target2;case"lt":return actual<target2;case"lte":return actual<=target2;case"eq":return actual===target2;case"ne":return actual!==target2;default:return!1}}function parseClaimGuardCatalog(entries){if(!entries?.length)return[];let out=[],seen=new Set;for(let e of entries){let parsed=parseGuardCatalogEntry(e);if(parsed&&!seen.has(parsed.action))seen.add(parsed.action),out.push(parsed)}return out}var VALUE_TYPES;var init_evaluate=__esm(()=>{init_types23();VALUE_TYPES=["int","boolean","string"]});async function resolveClaimGuards(db,schemaTables,userId,read,ctx={}){let claimsTable=schemaTables.claims,roleClaimsTable=schemaTables.roleClaims??schemaTables.role_claims,userRolesTable=schemaTables.userRoles??schemaTables.user_roles;if(!claimsTable||!roleClaimsTable||!userRolesTable)return EMPTY;let claimRows=await db.select().from(claimsTable),guardByClaimId=new Map;for(let c of claimRows){if(c.isActive===!1)continue;let policy=parseGuardPolicy(c.policy);if(policy)guardByClaimId.set(String(c.id),{action:String(c.action??""),policy})}if(guardByClaimId.size===0)return EMPTY;let urRows=await db.select().from(userRolesTable),roleIds=new Set(urRows.filter((r2)=>r2.isActive!==!1&&String(r2.userId??r2.user_id)===userId).map((r2)=>String(r2.roleId??r2.role_id)));if(roleIds.size===0)return EMPTY;let rcRows=await db.select().from(roleClaimsTable),guards=[],suppressed=new Set,firedGuards=[],stateCache=new Map;for(let rc of rcRows){if(rc.isActive===!1)continue;if(!roleIds.has(String(rc.roleId??rc.role_id)))continue;let guard4=guardByClaimId.get(String(rc.claimId??rc.claim_id));if(!guard4)continue;let condition=parseGuardCondition(rc.scope,guard4.policy.valueType);if(!condition)continue;let key2=resolveGuardKey(guard4.policy.keyTemplate,{userId,tenant:ctx.tenant}),value2;if(stateCache.has(key2))value2=stateCache.get(key2);else value2=await read(key2).catch(()=>null),stateCache.set(key2,value2);let holds=guardConditionHolds(value2,guard4.policy.valueType,condition),current=normalizeCurrent(value2,guard4.policy.valueType);if(guards.push({action:guard4.action,key:key2,valueType:guard4.policy.valueType,op:condition.op,threshold:condition.value,current,invalidates:condition.invalidates,holds}),holds&&condition.invalidates.length>0){for(let a12 of condition.invalidates)suppressed.add(a12);firedGuards.push({action:guard4.action,key:key2,invalidates:condition.invalidates})}}return{guards,suppressedClaims:[...suppressed],firedGuards}}function normalizeCurrent(raw,type4){if(raw==null)return null;let v=typeof raw==="object"&&raw!==null&&"data"in raw?raw.data:raw;if(v==null)return null;if(type4==="int"){let n2=Number(v);return Number.isFinite(n2)?n2:null}if(type4==="boolean")return v===!0||v==="true"||v===1||v==="1";return String(v)}var EMPTY;var init_resolve=__esm(()=>{init_evaluate();EMPTY={guards:[],suppressedClaims:[],firedGuards:[]}});import{eq as eq61}from"drizzle-orm";async function seedClaimGuards(db,schemaTables,claimGuards,logger2){let claimsTable=schemaTables.claims;if(!claimsTable)return{created:0,updated:0,deactivated:0};let actionCol=claimsTable.action,desired=parseClaimGuardCatalog(claimGuards),desiredByAction=new Map(desired.map((d)=>[d.action,d.policy])),existing=await db.select().from(claimsTable),existingGuardActions=new Set,result={created:0,updated:0,deactivated:0};for(let row of existing){if(!parseGuardPolicy(row.policy))continue;let action=String(row.action??"");existingGuardActions.add(action);let want=desiredByAction.get(action);if(!want){if(row.isActive!==!1)await db.update(claimsTable).set({isActive:!1}).where(eq61(actionCol,action)),result.deactivated++;continue}let current=row.policy;if(JSON.stringify(current)!==JSON.stringify(want)||row.isActive===!1)await db.update(claimsTable).set({policy:want,isActive:!0,path:want.keyTemplate,method:"GUARD"}).where(eq61(actionCol,action)),result.updated++}for(let{action,policy}of desired){if(existingGuardActions.has(action))continue;await db.insert(claimsTable).values({action,description:`ClaimGuard [${policy.valueType}] key=${policy.keyTemplate}`,path:policy.keyTemplate,method:"GUARD",policy,isActive:!0}),result.created++}return logger2?.info?.(`[Authorization] ClaimGuards seeded (created=${result.created}, updated=${result.updated}, deactivated=${result.deactivated})`),result}var init_seed2=__esm(()=>{init_evaluate()});var exports_ClaimGuard={};__export(exports_ClaimGuard,{seedClaimGuards:()=>seedClaimGuards,resolveGuardKey:()=>resolveGuardKey,resolveClaimGuards:()=>resolveClaimGuards,parseGuardPolicy:()=>parseGuardPolicy,parseGuardCondition:()=>parseGuardCondition,parseGuardCatalogEntry:()=>parseGuardCatalogEntry,parseClaimGuardCatalog:()=>parseClaimGuardCatalog,guardConditionHolds:()=>guardConditionHolds,guardActionFromName:()=>guardActionFromName,OPS_BY_TYPE:()=>OPS_BY_TYPE});var init_ClaimGuard=__esm(()=>{init_evaluate();init_resolve();init_seed2();init_types23()});var exports_dbStorage={};__export(exports_dbStorage,{createDbWebAuthnStorage:()=>createDbWebAuthnStorage});import{and as and22,eq as eq62,isNull as isNull4}from"drizzle-orm";function rowToRecord(row){return{id:row.id,userId:row.userId,credentialId:row.credentialId,publicKey:row.publicKey,counter:typeof row.counter==="bigint"?Number(row.counter):Number(row.counter??0),transports:parseTransports(row.transports),deviceType:parseDeviceType(row.deviceType),backedUp:row.backedUp,aaguid:row.aaguid,authenticatorAttachment:row.authenticatorAttachment==="platform"||row.authenticatorAttachment==="cross-platform"?row.authenticatorAttachment:null,nickname:row.nickname,lastUsedAt:row.lastUsedAt,revokedAt:row.revokedAt,createdAt:row.createdAt}}function col17(table,key2){return table[key2]}function createDbWebAuthnStorage(deps){let{db,resolveTable}=deps,credentialsName="webauthnCredentials",challengesName="webauthnChallenges";return{storeChallenge:async(challenge,schemaName)=>{let table=resolveTable("webauthnChallenges",schemaName);if(!table)return;await db.insert(table).values({userId:challenge.userId??null,challenge:challenge.challenge,challengeType:challenge.challengeType,expiresAt:challenge.expiresAt})},consumeChallenge:async(challenge,challengeType,schemaName)=>{let table=resolveTable("webauthnChallenges",schemaName);if(!table)return null;let row=(await db.update(table).set({consumedAt:new Date}).where(and22(eq62(col17(table,"challenge"),challenge),eq62(col17(table,"challengeType"),challengeType),isNull4(col17(table,"consumedAt")))).returning())[0];if(!row)return null;return{challenge:row.challenge,challengeType:row.challengeType,userId:row.userId,expiresAt:row.expiresAt}},listCredentialsByUser:async(userId,schemaName)=>{let table=resolveTable("webauthnCredentials",schemaName);if(!table)return[];return(await db.select().from(table).where(eq62(col17(table,"userId"),userId))).map(rowToRecord)},findCredentialById:async(credentialId,schemaName)=>{let table=resolveTable("webauthnCredentials",schemaName);if(!table)return null;let rows=await db.select().from(table).where(eq62(col17(table,"credentialId"),credentialId)).limit(1);return rows[0]?rowToRecord(rows[0]):null},insertCredential:async(record3,schemaName)=>{let table=resolveTable("webauthnCredentials",schemaName);if(!table)throw Error("webauthn_credentials table not configured");let row=(await db.insert(table).values({userId:record3.userId,credentialId:record3.credentialId,publicKey:record3.publicKey,counter:record3.counter,transports:record3.transports??null,deviceType:record3.deviceType??null,backedUp:record3.backedUp,aaguid:record3.aaguid??null,authenticatorAttachment:record3.authenticatorAttachment??null,nickname:record3.nickname??null}).returning())[0];if(!row)throw Error("Failed to insert webauthn credential");return rowToRecord(row)},updateCredentialCounter:async(credentialId,counter,schemaName)=>{let table=resolveTable("webauthnCredentials",schemaName);if(!table)return;await db.update(table).set({counter,lastUsedAt:new Date}).where(eq62(col17(table,"credentialId"),credentialId))},revokeCredential:async(credentialId,userId,schemaName)=>{let table=resolveTable("webauthnCredentials",schemaName);if(!table)return!1;return(await db.update(table).set({revokedAt:new Date}).where(and22(eq62(col17(table,"credentialId"),credentialId),eq62(col17(table,"userId"),userId))).returning()).length>0},renameCredential:async(credentialId,userId,nickname,schemaName)=>{let table=resolveTable("webauthnCredentials",schemaName);if(!table)return!1;return(await db.update(table).set({nickname}).where(and22(eq62(col17(table,"credentialId"),credentialId),eq62(col17(table,"userId"),userId))).returning()).length>0}}}var init_dbStorage=()=>{};function isValidUploadId(id){return typeof id==="string"&&/^[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$/i.test(id)}function offsetVerdict(input){let{declaredOffset,actualOffset,chunkBytes,totalSize}=input;if(!Number.isFinite(declaredOffset)||declaredOffset<0)return{ok:!1,reason:"offset_mismatch",expected:actualOffset};if(declaredOffset!==actualOffset)return{ok:!1,reason:"offset_mismatch",expected:actualOffset};if(actualOffset+chunkBytes>totalSize)return{ok:!1,reason:"too_long",expected:actualOffset};return{ok:!0}}function isComplete(actualOffset,totalSize){return actualOffset===totalSize&&totalSize>0}function sessionRefusal(input){let{session,callerId,fingerprint,now}=input;if(!session)return"not_found";if(!callerId||session.owner!==callerId)return"not_yours";if(now-session.createdAt>86400000)return"expired";if(fingerprint!=null&&fingerprint!==session.fingerprint)return"wrong_file";return null}function isExpired(session,now){return now-session.createdAt>86400000}function sessionStatus(session,offset){return{uploadId:session.id,offset,size:session.size,originalName:session.originalName,complete:isComplete(offset,session.size)}}var SESSION_TTL_MS=86400000,CHUNK_SIZE_BYTES=8388608,MAX_CHUNK_BYTES=33554432;import{randomUUID as randomUUID8}from"crypto";import{mkdir as mkdir8,open as open2,readdir as readdir3,readFile as readFile2,rm as rm2,stat as stat8,writeFile as writeFile2}from"fs/promises";import path8 from"path";function createResumableStore(basePath){let root=path8.join(basePath,UPLOAD_DIR);function pathsFor(id){if(!isValidUploadId(id))return null;let part=path8.join(root,`${id}.part`),meta=path8.join(root,`${id}.json`);if(!isPathWithinBase(root,part)||!isPathWithinBase(root,meta))return null;return{part,meta}}async function create4(input,now){await mkdir8(root,{recursive:!0});let session={...input,id:randomUUID8(),createdAt:now},paths=pathsFor(session.id);if(!paths)throw Error("Generated upload id was rejected by its own validator");return await writeFile2(paths.meta,JSON.stringify(session),"utf8"),await writeFile2(paths.part,""),session}async function read(id){let paths=pathsFor(id);if(!paths)return null;try{let raw=await readFile2(paths.meta,"utf8"),parsed=JSON.parse(raw);if(!parsed||typeof parsed.owner!=="string"||typeof parsed.size!=="number")return null;return parsed}catch{return null}}async function offsetOf(id){let paths=pathsFor(id);if(!paths)return null;try{return(await stat8(paths.part)).size}catch{return null}}async function writeAt(id,offset,chunk){let paths=pathsFor(id);if(!paths)return null;let handle=await open2(paths.part,"r+");try{await handle.write(chunk,0,chunk.byteLength,offset)}finally{await handle.close()}return(await stat8(paths.part)).size}async function readAssembled(id){let paths=pathsFor(id);if(!paths)return null;try{return await readFile2(paths.part)}catch{return null}}function partPath(id){return pathsFor(id)?.part??null}async function discardMeta(id){let paths=pathsFor(id);if(!paths)return;await rm2(paths.meta,{force:!0})}async function discard2(id){let paths=pathsFor(id);if(!paths)return;await rm2(paths.part,{force:!0}),await rm2(paths.meta,{force:!0})}async function sweep(now){let removed=0,entries;try{entries=await readdir3(root)}catch{return 0}for(let entry of entries){if(!entry.endsWith(".json"))continue;let id=entry.slice(0,-5);try{let session=await read(id);if(session&&!isExpired(session,now))continue;await discard2(id),removed+=1}catch{}}return removed}return{create:create4,read,offsetOf,writeAt,readAssembled,partPath,discard:discard2,discardMeta,sweep,root}}var UPLOAD_DIR=".uploads";var init_store3=__esm(()=>{init_helpers2()});var exports_resumable={};__export(exports_resumable,{createResumableRoutes:()=>createResumableRoutes,SESSION_TTL_MS:()=>SESSION_TTL_MS,CHUNK_SIZE_BYTES:()=>CHUNK_SIZE_BYTES});import{Elysia as Elysia50,t as t42}from"elysia";function toBytes(body){if(body instanceof Uint8Array)return body;if(body instanceof ArrayBuffer)return new Uint8Array(body);if(ArrayBuffer.isView(body))return new Uint8Array(body.buffer,body.byteOffset,body.byteLength);if(typeof body==="string")return new TextEncoder().encode(body);return new Uint8Array(0)}function createResumableRoutes(config){let{basePath,storage,logger:logger2,getUserId:getUserId3,canUpload,register}=config,store=createResumableStore(basePath),plugin=new Elysia50({prefix:"/uploads"}),openSession=async(id,request,fingerprint)=>{let userId=getUserId3(request);if(!await canUpload(request))return{ok:!1,status:403,message:"You are not allowed to upload files."};let session=isValidUploadId(id)?await store.read(id):null,refusal=sessionRefusal({session,callerId:userId,fingerprint,now:Date.now()});if(refusal)return{ok:!1,status:REFUSAL_STATUS[refusal],message:REFUSAL_MESSAGE[refusal]};return{ok:!0,session,userId}};return plugin.post("/",async({body,request,set:set2})=>{let userId=getUserId3(request);if(!userId)return set2.status=401,{success:!1,message:"Sign in to upload."};if(!await canUpload(request))return set2.status=403,{success:!1,message:"You are not allowed to upload files."};if(!Number.isFinite(body.size)||body.size<=0)return set2.status=400,{success:!1,message:"A size is required to start an upload."};if(body.size>storage.maxFileSizeBytes)return set2.status=413,{success:!1,message:`This file is larger than the ${Math.round(storage.maxFileSizeBytes/1048576)} MB limit.`};if(storage.blockedMimeTypes?.includes(body.mimeType))return set2.status=415,{success:!1,message:"This kind of file cannot be uploaded."};if(storage.allowedMimeTypes?.length&&!storage.allowedMimeTypes.includes(body.mimeType))return set2.status=415,{success:!1,message:"This kind of file cannot be uploaded."};let session=await store.create({owner:userId,originalName:body.originalName,size:body.size,mimeType:body.mimeType,type:body.type??"file",fingerprint:body.fingerprint},Date.now());return set2.status=201,{success:!0,data:sessionStatus(session,0)}},{body:t42.Object({originalName:t42.String({minLength:1,maxLength:500}),size:t42.Number(),mimeType:t42.String({maxLength:200}),type:t42.Optional(t42.String({maxLength:40})),fingerprint:t42.String({minLength:1,maxLength:200})}),detail:{tags:["Storage"],summary:"Start a resumable upload"}}),plugin.get("/:id",async({params,request,set:set2})=>{let opened=await openSession(params.id,request);if(!opened.ok)return set2.status=opened.status,{success:!1,message:opened.message};let offset=await store.offsetOf(params.id)??0;return{success:!0,data:sessionStatus(opened.session,offset)}}),plugin.patch("/:id",async({params,request,body,set:set2})=>{let fingerprint=request.headers.get("upload-fingerprint"),opened=await openSession(params.id,request,fingerprint);if(!opened.ok)return set2.status=opened.status,{success:!1,message:opened.message};let declared=Number(request.headers.get("upload-offset")),actual=await store.offsetOf(params.id)??0,chunk=toBytes(body);if(chunk.byteLength>MAX_CHUNK_BYTES)return set2.status=413,{success:!1,message:`A single piece may not exceed ${MAX_CHUNK_BYTES/1048576} MB.`,data:{offset:actual}};let verdict=offsetVerdict({declaredOffset:declared,actualOffset:actual,chunkBytes:chunk.byteLength,totalSize:opened.session.size});if(!verdict.ok)return set2.status=409,{success:!1,message:verdict.reason==="too_long"?"This piece would take the file past the size it was started with.":"This piece does not continue where the file ends.",data:{offset:verdict.expected}};let offset=await store.writeAt(params.id,actual,chunk);if(offset===null)return set2.status=500,{success:!1,message:"The piece could not be written."};return{success:!0,data:sessionStatus(opened.session,offset)}},{detail:{tags:["Storage"],summary:"Append a piece"}}),plugin.post("/:id/complete",async({params,request,set:set2})=>{let opened=await openSession(params.id,request);if(!opened.ok)return set2.status=opened.status,{success:!1,message:opened.message};let offset=await store.offsetOf(params.id)??0;if(!isComplete(offset,opened.session.size))return set2.status=409,{success:!1,message:"The file is not complete yet.",data:sessionStatus(opened.session,offset)};let partPath=store.partPath(params.id);if(!partPath)return set2.status=500,{success:!1,message:"The assembled file could not be found."};let registered=await register({partPath,size:offset,originalName:opened.session.originalName,mimeType:opened.session.mimeType,type:opened.session.type,userId:opened.userId});if(!registered)return set2.status=500,{success:!1,message:"The file could not be registered. Try completing again."};return await store.discardMeta(params.id),logger2.info(`[Storage] Resumable upload finished: ${opened.session.originalName} (${offset} bytes)`),{success:!0,data:{id:registered.id}}}),plugin.delete("/:id",async({params,request,set:set2})=>{let opened=await openSession(params.id,request);if(!opened.ok)return set2.status=opened.status,{success:!1,message:opened.message};return await store.discard(params.id),{success:!0,data:{discarded:!0}}}),{plugin,sweep:(now)=>store.sweep(now)}}var REFUSAL_STATUS,REFUSAL_MESSAGE;var init_resumable=__esm(()=>{init_store3();REFUSAL_STATUS={not_found:404,not_yours:404,expired:410,wrong_file:409},REFUSAL_MESSAGE={not_found:"No such upload.",not_yours:"No such upload.",expired:"This upload was abandoned and has been cleaned up. Start it again.",wrong_file:"This is a different file from the one this upload started with."}});var exports_authorization={};__export(exports_authorization,{createAuthorizationDiscoveryRoutes:()=>createAuthorizationDiscoveryRoutes});import{timingSafeEqual as timingSafeEqual4}from"crypto";import{Elysia as Elysia51}from"elysia";function tokensMatch2(a12,b){let ba=Buffer.from(a12),bb=Buffer.from(b);if(ba.length!==bb.length)return!1;return timingSafeEqual4(ba,bb)}function createAuthorizationDiscoveryRoutes(cfg){let{db,schemaTables,logger:logger2,discovery,readState}=cfg,token=discovery.token||process.env.NUCLEUS_DISCOVERY_TOKEN,claimsTable=schemaTables.claims,manifestAuthorized=(request)=>{if(hasGodminRole(request))return!0;if(token){let presented=request.headers.get("x-discovery-token")??"";return tokensMatch2(presented,token)}return!1},routes=new Elysia51;routes.post("/authorization/discover",async({request,set:set2})=>{if(!hasGodminRole(request))return fail6(set2,403,"Forbidden: endpoint discovery requires godmin");if(!discovery.enabled)return fail6(set2,400,"endpointDiscovery is not enabled");return{success:!0,message:"Discovery completed",data:await runEndpointDiscovery(db,schemaTables,discovery,logger2)}}),routes.get("/authorization/route-manifest",async({request,query,set:set2})=>{if(!manifestAuthorized(request))return fail6(set2,403,"Forbidden: godmin or a valid x-discovery-token required");if(!claimsTable)return fail6(set2,503,"Claims table unavailable");let service=query.service;if(service){let rows=await getRouteManifest(db,claimsTable,service);return{success:!0,data:{service,routes:rows}}}let all={};for(let svc of discovery.services??[])all[svc.id]=await getRouteManifest(db,claimsTable,svc.id);return{success:!0,data:all}}),routes.get("/authorization/role-claims-manifest",async({request,query,set:set2})=>{if(!manifestAuthorized(request))return fail6(set2,403,"Forbidden: godmin or a valid x-discovery-token required");let service=query.service;if(!service)return fail6(set2,400,"service query param required");let map=await getRoleClaimsManifest(db,schemaTables,service);return{success:!0,data:{service,roleClaims:map}}});let authorizeGuardRead=(request,query,set2)=>{let callerId=request.headers.get("x-user-id")??"",isGodmin4=hasGodminRole(request),requested=query.userId;if(requested&&requested!==callerId&&!isGodmin4)return{error:fail6(set2,403,"Forbidden: only godmin can read another user's guards")};let targetUserId=requested&&isGodmin4?requested:callerId;if(!targetUserId)return{error:fail6(set2,401,"Unauthorized: no user context")};return{userId:targetUserId}},guardsHandler=async({request,query,set:set2})=>{let auth=authorizeGuardRead(request,query,set2);if("error"in auth)return auth.error;let tenant=request.headers.get("x-tenant-id")??void 0;if(!readState)return{success:!0,data:{userId:auth.userId,guards:[]}};let{guards}=await resolveClaimGuards(db,schemaTables,auth.userId,readState,{tenant});return{success:!0,data:{userId:auth.userId,guards}}};return routes.get("/authorization/guards",guardsHandler),routes.get("/authorization/quotas",guardsHandler),routes.get("/authorization/suppressed-claims",async({request,query,set:set2})=>{let auth=authorizeGuardRead(request,query,set2);if("error"in auth)return auth.error;if(!readState)return{success:!0,data:{userId:auth.userId,suppressedClaims:[],firedGuards:[]}};let tenant=request.headers.get("x-tenant-id")??void 0,{suppressedClaims,firedGuards}=await resolveClaimGuards(db,schemaTables,auth.userId,readState,{tenant});return{success:!0,data:{userId:auth.userId,suppressedClaims,firedGuards}}}),routes}var fail6=(set2,status,message)=>{return set2.status=status,{success:!1,message,data:null}};var init_authorization=__esm(()=>{init_ClaimGuard();init_seed();init_adminGuard()});var import_reflect_metadata2=__toESM(require_Reflect(),1);import{batch,createStore}from"h-state";import{useEffectEvent}from"react";function createInitialState(endpoints){let state={};for(let key of Object.keys(endpoints))state[key]={isPending:!1,data:null,error:null,code:null};return state}function createApiHook(endpoints,factory){let{useStore}=createStore(createInitialState(endpoints),{_callEndpoint:(store)=>async(endpointKey,options)=>{if(!store[endpointKey])return;batch(()=>{store[endpointKey].isPending=!0,store[endpointKey].error=null});try{let response=await factory(endpointKey,options.payload);if(batch(()=>{if(store[endpointKey].isPending=!1,store[endpointKey].code=response.code??null,response.isSuccess&&response.data!==void 0)store[endpointKey].data=response.data,store[endpointKey].error=null;else store[endpointKey].error=response.errors??null}),response.isSuccess)options.onAfterHandle?.(response.data??response);else options.onErrorHandle?.(response.errors??{message:"Request failed"},response.code)}catch(err){batch(()=>{store[endpointKey].isPending=!1,store[endpointKey].error={message:err instanceof Error?err.message:"Unknown error"}}),options.onErrorHandle?.({message:err instanceof Error?err.message:"Unknown error"},null)}}});return function(){let store=useStore(),callEndpoint=useEffectEvent((endpointKey,options)=>{store._callEndpoint(endpointKey,options)}),actions={};for(let key of Object.keys(endpoints)){let startFn=(options)=>{callEndpoint(key,options)};actions[key]={state:store[key],start:startFn}}return actions}}var system_tables_default={$schema:"../schemas/nucleus.tables.schema.json",tables:[{table_name:"users",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"email",type:"varchar",length:255},{name:"password",type:"varchar",length:255},{name:"verified_at",type:"timestamp"},{name:"email_verification_token",type:"varchar",length:255},{name:"email_verification_token_expires_at",type:"timestamp"},{name:"email_verification_sent_at",type:"timestamp"},{name:"email_verification_attempts",type:"integer",default:0},{name:"last_login_at",type:"timestamp"},{name:"login_count",type:"integer",default:0},{name:"is_locked",type:"boolean",default:!1},{name:"locked_until",type:"timestamp"},{name:"failed_login_attempts",type:"integer",default:0},{name:"is_god",type:"boolean",default:!1},{name:"cohort_id",type:"uuid",references:{table:"user_cohorts",column:"id",onDelete:"set null"}},{name:"email_verified",type:"boolean",default:!1}],indexes:[{columns:["email"],unique:!0},{columns:["email","is_active"]},{columns:["last_login_at"]},{columns:["is_locked","locked_until"]}]},{table_name:"profiles",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id"}},{name:"first_name",type:"varchar",length:100,notNull:!0},{name:"last_name",type:"varchar",length:100,notNull:!0}],indexes:[{columns:["user_id"],unique:!0},{columns:["first_name","last_name"]}]},{table_name:"roles",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"name",type:"varchar",length:100,notNull:!0},{name:"description",type:"varchar",length:500}],indexes:[{columns:["name"],unique:!0}]},{table_name:"claims",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"action",type:"varchar",length:100,notNull:!0},{name:"description",type:"varchar",length:500},{name:"path",type:"varchar",length:200,notNull:!0},{name:"method",type:"varchar",length:10,notNull:!0},{name:"policy",type:"jsonb"}],indexes:[{columns:["action"],unique:!0},{columns:["path","method"]}]},{table_name:"user_roles",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"role_id",type:"uuid",notNull:!0,references:{table:"roles",column:"id",onDelete:"cascade"}}],indexes:[{columns:["user_id"]},{columns:["role_id"]}],constraints:{unique:[{name:"unique_user_role",columns:["user_id","role_id"]}]}},{table_name:"role_claims",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"role_id",type:"uuid",notNull:!0,references:{table:"roles",column:"id",onDelete:"cascade"}},{name:"claim_id",type:"uuid",notNull:!0,references:{table:"claims",column:"id",onDelete:"cascade"}},{name:"scope",type:"text"}],indexes:[{columns:["role_id"]},{columns:["claim_id"]},{columns:["role_id","claim_id","scope"]}]},{table_name:"files",feature_set:["storage"],add_base_columns:!0,is_form_data:!0,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"name",type:"varchar",length:255,notNull:!0},{name:"original_name",type:"varchar",length:255,notNull:!0},{name:"type",type:"varchar",length:50,enumValues:["image","document","video","audio","profile_picture"]},{name:"path",type:"varchar",length:500,notNull:!0},{name:"size",type:"bigint",mode:"number",notNull:!0},{name:"mime_type",type:"varchar",length:100,notNull:!0},{name:"extension",type:"varchar",length:10,notNull:!0},{name:"uploaded_by",type:"uuid",references:{table:"users",column:"id"}}],indexes:[{columns:["type"]},{columns:["uploaded_by"]},{columns:["size"]}]},{table_name:"addresses",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"owner_type",type:"varchar",length:50,notNull:!0,enumValues:["user","company","contact"]},{name:"owner_id",type:"uuid",notNull:!0},{name:"name",type:"varchar",length:100,notNull:!0},{name:"street",type:"varchar",length:255},{name:"city",type:"varchar",length:100},{name:"state",type:"varchar",length:50},{name:"zip",type:"varchar",length:20},{name:"country",type:"varchar",length:50,default:"US"},{name:"latitude",type:"decimal",precision:10,scale:8},{name:"longitude",type:"decimal",precision:11,scale:8},{name:"neighborhood",type:"varchar",length:100},{name:"apartment",type:"varchar",length:50},{name:"province",type:"varchar",length:100},{name:"district",type:"varchar",length:100},{name:"type",type:"varchar",length:50}],indexes:[{columns:["city","state"]},{columns:["latitude","longitude"]},{columns:["type"]},{columns:["owner_type","owner_id"]}]},{table_name:"phones",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"owner_type",type:"varchar",length:50,notNull:!0,enumValues:["user","company","contact"]},{name:"owner_id",type:"uuid",notNull:!0},{name:"name",type:"varchar",length:100,notNull:!0},{name:"type",type:"varchar",length:50,enumValues:["mobile","office","fax"]},{name:"number",type:"varchar",length:20,notNull:!0},{name:"country_code",type:"varchar",length:10,notNull:!0,default:"+1"},{name:"extension",type:"varchar",length:10}],indexes:[{columns:["number"]},{columns:["type"]},{columns:["owner_type","owner_id"]}]},{table_name:"notifications",feature_set:["notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",notNull:!0},{name:"title",type:"varchar",length:255,notNull:!0},{name:"body",type:"varchar",length:1000},{name:"entity_name",type:"varchar",length:100},{name:"entity_id",type:"uuid"},{name:"type",type:"varchar",length:50,notNull:!0,default:"system",enumValues:["verification","system","custom"]},{name:"source",type:"varchar",length:100},{name:"is_seen",type:"boolean",notNull:!0,default:!1},{name:"seen_at",type:"timestamptz"}],indexes:[{columns:["user_id","created_at"]},{columns:["is_seen"]},{columns:["type"]},{columns:["user_id","type","is_seen"]}]},{table_name:"tenants",feature_set:["multi-tenant"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:[],columns:[{name:"subdomain",type:"varchar",length:100,notNull:!0,unique:!0},{name:"schema_name",type:"varchar",length:100,notNull:!0,unique:!0},{name:"company_id",type:"uuid",notNull:!0},{name:"company_name",type:"varchar",length:255},{name:"god_admin_email",type:"varchar",length:255,notNull:!0},{name:"status",type:"varchar",length:20,notNull:!0,default:"provisioning"},{name:"plan",type:"varchar",length:50,default:"free"},{name:"domain",type:"varchar",length:255},{name:"settings",type:"jsonb",default:"{}"},{name:"trusted_sources",type:"jsonb",default:"[]"},{name:"max_users",type:"integer"},{name:"provisioned_at",type:"timestamptz"},{name:"suspended_at",type:"timestamptz"},{name:"suspended_reason",type:"text"}],indexes:[{columns:["status"]}]},{table_name:"tenant_events",feature_set:["multi-tenant"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],columns:[{name:"tenant_id",type:"uuid",notNull:!0,references:{table:"tenants",column:"id",onDelete:"cascade"}},{name:"event_type",type:"varchar",length:50,notNull:!0},{name:"event_data",type:"jsonb",default:"{}"},{name:"performed_by",type:"varchar",length:255},{name:"ip_address",type:"varchar",length:45}],indexes:[{columns:["tenant_id"]},{columns:["event_type"]}]},{table_name:"tenant_features",feature_set:["multi-tenant"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:[],columns:[{name:"tenant_id",type:"uuid",notNull:!0,references:{table:"tenants",column:"id",onDelete:"cascade"}},{name:"feature_name",type:"varchar",length:100,notNull:!0},{name:"enabled",type:"boolean",notNull:!0,default:!0},{name:"config",type:"jsonb",default:"{}"}],indexes:[{columns:["tenant_id","feature_name"],unique:!0},{columns:["feature_name"]}]},{table_name:"domain_hostnames",feature_set:["domains"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:["PUT"],group_name:"Domains",columns:[{name:"owner_type",type:"varchar",length:20,notNull:!0,default:"tenant",comment:"tenant | organization | user | external"},{name:"owner_id",type:"uuid",notNull:!0,comment:"Product-defined owner reference (e.g. band id, org id)"},{name:"tenant_id",type:"uuid",references:{table:"tenants",column:"id",onDelete:"cascade"},comment:"Tenant this hostname routes to; null for non-tenant owners"},{name:"schema_name",type:"varchar",length:100,comment:"Resolved tenant schema for routing"},{name:"hostname",type:"varchar",length:255,notNull:!0,comment:"Original hostname as entered by the user"},{name:"normalized_hostname",type:"varchar",length:255,notNull:!0,unique:!0,comment:"Lowercased, punycode, port-stripped hostname used for matching"},{name:"hostname_kind",type:"varchar",length:20,notNull:!0,default:"apex",comment:"platform_subdomain | apex | www | subdomain"},{name:"status",type:"varchar",length:20,notNull:!0,default:"pending_verification",comment:"draft | pending_verification | verifying | active | failed | disabled | archived"},{name:"routing_status",type:"varchar",length:20,notNull:!0,default:"inactive",comment:"inactive | pending | active | failed"},{name:"certificate_status",type:"varchar",length:20,notNull:!0,default:"pending",comment:"not_required | pending | active | failed"},{name:"verification_status",type:"varchar",length:20,notNull:!0,default:"pending",comment:"pending | verified | failed | expired"},{name:"provider",type:"varchar",length:30,notNull:!0,default:"manual_dns",comment:"manual_dns | cloudflare_for_saas | cloudflare_registrar"},{name:"provider_hostname_id",type:"varchar",length:255},{name:"dns_target",type:"varchar",length:255,comment:"CNAME / A target the customer must point at"},{name:"is_primary",type:"boolean",notNull:!0,default:!1},{name:"redirect_to_hostname_id",type:"uuid",comment:"When set, this hostname 301-redirects to another hostname (e.g. apex to www)"},{name:"activated_at",type:"timestamptz"},{name:"disabled_at",type:"timestamptz"},{name:"failure_reason",type:"text"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["tenant_id"]},{columns:["schema_name"]},{columns:["status"]},{columns:["owner_type","owner_id"]},{columns:["provider","provider_hostname_id"]}]},{table_name:"domain_registrations",feature_set:["domains"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:["PUT"],group_name:"Domains",columns:[{name:"owner_type",type:"varchar",length:20,notNull:!0,default:"tenant"},{name:"owner_id",type:"uuid",notNull:!0},{name:"tenant_id",type:"uuid",references:{table:"tenants",column:"id",onDelete:"set null"}},{name:"requested_domain",type:"varchar",length:255,notNull:!0},{name:"registered_domain",type:"varchar",length:255},{name:"provider",type:"varchar",length:30,notNull:!0,default:"cloudflare_registrar"},{name:"provider_registration_id",type:"varchar",length:255},{name:"registrant_owner_type",type:"varchar",length:20,notNull:!0,default:"customer",comment:"customer | platform"},{name:"registrant_contact_snapshot",type:"jsonb",default:"{}"},{name:"status",type:"varchar",length:30,notNull:!0,default:"draft",comment:"draft | availability_checked | awaiting_payment | registering | active | failed | transfer_requested | transferred_out | cancelled | expired"},{name:"price_amount",type:"numeric",precision:12,scale:2},{name:"currency",type:"varchar",length:10},{name:"renewal_date",type:"timestamptz"},{name:"auto_renew",type:"boolean",notNull:!0,default:!0},{name:"terms_version",type:"varchar",length:50},{name:"terms_accepted_at",type:"timestamptz"},{name:"failure_reason",type:"text"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["owner_type","owner_id"]},{columns:["tenant_id"]},{columns:["status"]}]},{table_name:"domain_verification_challenges",feature_set:["domains"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],group_name:"Domains",columns:[{name:"domain_hostname_id",type:"uuid",notNull:!0,references:{table:"domainHostnames",column:"id",onDelete:"cascade"}},{name:"challenge_type",type:"varchar",length:30,notNull:!0,default:"ownership_validation",comment:"hostname_validation | certificate_validation | ownership_validation"},{name:"record_type",type:"varchar",length:10,notNull:!0,default:"TXT",comment:"TXT | CNAME | A | AAAA | HTTP"},{name:"record_name",type:"varchar",length:255,notNull:!0},{name:"record_value",type:"text",notNull:!0},{name:"expected_target",type:"varchar",length:255},{name:"status",type:"varchar",length:20,notNull:!0,default:"pending",comment:"pending | verified | failed | expired"},{name:"expires_at",type:"timestamptz"},{name:"verified_at",type:"timestamptz"},{name:"failure_reason",type:"text"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["domain_hostname_id"]},{columns:["status"]}]},{table_name:"domain_provider_records",feature_set:["domains"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],group_name:"Domains",columns:[{name:"domain_hostname_id",type:"uuid",notNull:!0,references:{table:"domainHostnames",column:"id",onDelete:"cascade"}},{name:"provider",type:"varchar",length:30,notNull:!0},{name:"provider_resource_type",type:"varchar",length:30,notNull:!0,comment:"custom_hostname | certificate | validation | zone | dns_record | registration"},{name:"provider_resource_id",type:"varchar",length:255},{name:"provider_status",type:"varchar",length:50},{name:"last_synced_at",type:"timestamptz"},{name:"raw_status",type:"jsonb",default:"{}"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["domain_hostname_id"]},{columns:["provider","provider_resource_id"]}]},{table_name:"domain_events",feature_set:["domains"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],group_name:"Domains",columns:[{name:"domain_hostname_id",type:"uuid",references:{table:"domainHostnames",column:"id",onDelete:"cascade"}},{name:"domain_registration_id",type:"uuid",references:{table:"domainRegistrations",column:"id",onDelete:"cascade"}},{name:"event_type",type:"varchar",length:50,notNull:!0},{name:"actor_type",type:"varchar",length:20},{name:"actor_id",type:"varchar",length:255},{name:"message",type:"text"},{name:"ip_address",type:"varchar",length:45},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["domain_hostname_id"]},{columns:["event_type"]}]},{table_name:"verifications",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"instance_id",type:"uuid",notNull:!0,references:{table:"verificationInstances",column:"id",onDelete:"cascade"}},{name:"requirement_id",type:"uuid",notNull:!0,references:{table:"verificationRequirements",column:"id"}},{name:"verifier_id",type:"uuid",notNull:!0,references:{table:"users",column:"id"}},{name:"signature_id",type:"uuid",references:{table:"files",column:"id"}},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"entity_id",type:"uuid",notNull:!0},{name:"step_order",type:"integer",notNull:!0,default:1},{name:"decision",type:"varchar",length:50,notNull:!0,default:"pending",enumValues:["approved","rejected","pending"]},{name:"reason",type:"text"},{name:"diff",type:"jsonb"}],indexes:[{columns:["instance_id"]},{columns:["requirement_id"]},{columns:["verifier_id"]},{columns:["entity_name","entity_id"]},{columns:["entity_name","entity_id","step_order"]},{columns:["decision"]}]},{table_name:"verificationRequirements",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"instance_id",type:"uuid",notNull:!0,references:{table:"verificationInstances",column:"id",onDelete:"cascade"}},{name:"step_node_id",type:"varchar",length:100,notNull:!0},{name:"verifier_node_id",type:"varchar",length:100,notNull:!0},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"entity_id",type:"uuid",notNull:!0},{name:"verifier_type",type:"varchar",length:30,notNull:!0,enumValues:["user","role"]},{name:"verifier_user_id",type:"uuid"},{name:"verifier_role",type:"varchar",length:100},{name:"require_signature",type:"boolean",notNull:!0,default:!1},{name:"all_must_approve",type:"boolean",notNull:!0,default:!1},{name:"step_order",type:"integer",notNull:!0,default:1},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","approved","rejected"]}],indexes:[{columns:["instance_id"]},{columns:["instance_id","step_order"]},{columns:["entity_name","entity_id"]},{columns:["verifier_user_id"]},{columns:["status"]}]},{table_name:"verificationFlows",feature_set:["authentication","verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"name",type:"varchar",length:255,notNull:!0},{name:"description",type:"text"},{name:"trigger_on",type:"varchar",length:50,notNull:!0,default:"update",enumValues:["create","update","delete","manual"]},{name:"trigger_fields",type:"jsonb"},{name:"is_draft",type:"boolean",notNull:!0,default:!0},{name:"published_at",type:"timestamptz"},{name:"viewport",type:"jsonb"}],indexes:[{columns:["entity_name"]},{columns:["entity_name","trigger_on"]},{columns:["is_draft"]}]},{table_name:"verificationSteps",feature_set:["authentication","verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"node_id",type:"varchar",length:100,notNull:!0},{name:"node_type",type:"varchar",length:50,notNull:!0,default:"step",enumValues:["step","verifier","notification"]},{name:"step_order",type:"integer",notNull:!0,default:1},{name:"name",type:"varchar",length:255},{name:"description",type:"text"},{name:"position_x",type:"numeric",notNull:!0,default:0},{name:"position_y",type:"numeric",notNull:!0,default:0},{name:"width",type:"numeric"},{name:"height",type:"numeric"},{name:"style",type:"jsonb"},{name:"data",type:"jsonb"}],indexes:[{columns:["flow_id"]},{columns:["entity_name"]},{columns:["flow_id","node_id"],unique:!0},{columns:["entity_name","step_order"]}]},{table_name:"verificationEdges",feature_set:["authentication","verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"edge_id",type:"varchar",length:100,notNull:!0},{name:"source_node_id",type:"varchar",length:100,notNull:!0},{name:"target_node_id",type:"varchar",length:100,notNull:!0},{name:"source_handle",type:"varchar",length:50},{name:"target_handle",type:"varchar",length:50},{name:"edge_type",type:"varchar",length:50,default:"default",enumValues:["default","conditional","success","failure"]},{name:"label",type:"varchar",length:255},{name:"condition",type:"jsonb"},{name:"style",type:"jsonb"},{name:"animated",type:"boolean",default:!1}],indexes:[{columns:["flow_id"]},{columns:["flow_id","edge_id"],unique:!0},{columns:["source_node_id"]},{columns:["target_node_id"]}]},{table_name:"verificationNotificationRules",feature_set:["verification","notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"node_id",type:"varchar",length:100,notNull:!0},{name:"trigger",type:"varchar",length:50,notNull:!0,enumValues:["on_flow_started","on_step_reached","on_approved","on_rejected","on_flow_completed"]},{name:"title_template",type:"varchar",length:255},{name:"body_template",type:"text"},{name:"starts_at",type:"timestamptz"},{name:"expires_at",type:"timestamptz"}],indexes:[{columns:["flow_id"]},{columns:["flow_id","node_id"],unique:!0},{columns:["trigger"]}]},{table_name:"verificationNotificationRecipients",feature_set:["verification","notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"rule_id",type:"uuid",notNull:!0,references:{table:"verificationNotificationRules",column:"id",onDelete:"cascade"}},{name:"recipient_type",type:"varchar",length:30,notNull:!0,enumValues:["user","role","all_verifiers","step_verifier","entity_creator"]},{name:"recipient_user_id",type:"uuid"},{name:"recipient_role",type:"varchar",length:100}],indexes:[{columns:["rule_id"]},{columns:["recipient_type"]}]},{table_name:"verificationVerifierConfigs",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"node_id",type:"varchar",length:100,notNull:!0},{name:"verifier_type",type:"varchar",length:30,notNull:!0,enumValues:["user","role"]},{name:"verifier_user_id",type:"uuid"},{name:"verifier_role",type:"varchar",length:100},{name:"require_signature",type:"boolean",notNull:!0,default:!1},{name:"all_must_approve",type:"boolean",notNull:!0,default:!1}],indexes:[{columns:["flow_id"]},{columns:["flow_id","node_id"],unique:!0},{columns:["verifier_type"]}]},{table_name:"verificationInstances",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id"}},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"entity_id",type:"uuid",notNull:!0},{name:"started_by",type:"uuid",references:{table:"users",column:"id"}},{name:"status",type:"varchar",length:30,notNull:!0,default:"active",enumValues:["active","completed","rejected","cancelled"]},{name:"current_step_order",type:"integer",notNull:!0,default:1},{name:"started_at",type:"timestamptz",notNull:!0,defaultRaw:"now()"},{name:"completed_at",type:"timestamptz"}],indexes:[{columns:["flow_id"]},{columns:["entity_name","entity_id"]},{columns:["entity_name","entity_id","status"]},{columns:["status"]},{columns:["started_by"]}]},{table_name:"verificationNotificationChannels",feature_set:["verification","notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"rule_id",type:"uuid",notNull:!0,references:{table:"verificationNotificationRules",column:"id",onDelete:"cascade"}},{name:"channel",type:"varchar",length:30,notNull:!0,enumValues:["portal","email","sms","telegram","webhook"]}],indexes:[{columns:["rule_id"]},{columns:["rule_id","channel"],unique:!0},{columns:["channel"]}]},{table_name:"user_cohorts",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"name",type:"varchar",length:255,notNull:!0},{name:"description",type:"text"},{name:"created_by",type:"uuid",references:{table:"users",column:"id",onDelete:"set null"}},{name:"expires_at",type:"timestamptz"},{name:"user_count",type:"integer",notNull:!0,default:0},{name:"metadata",type:"jsonb",default:"{}"}]},{table_name:"user_sessions",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,group_name:"Authentication",available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"token_hash",type:"varchar",length:255,notNull:!0},{name:"refresh_token_hash",type:"varchar",length:255},{name:"device_fingerprint",type:"varchar",length:255},{name:"device_name",type:"varchar",length:100},{name:"device_type",type:"varchar",length:50,enumValues:["desktop","mobile","tablet","unknown"]},{name:"browser_name",type:"varchar",length:50},{name:"browser_version",type:"varchar",length:20},{name:"os_name",type:"varchar",length:50},{name:"os_version",type:"varchar",length:20},{name:"ip_address",type:"varchar",length:45,notNull:!0},{name:"location_country",type:"varchar",length:100},{name:"location_city",type:"varchar",length:100},{name:"location_coordinates",type:"varchar",length:50},{name:"last_activity_at",type:"timestamptz",notNull:!0,defaultRaw:"now()"},{name:"expires_at",type:"timestamptz",notNull:!1},{name:"revoked_at",type:"timestamptz"},{name:"revoked_reason",type:"varchar",length:100,enumValues:["user_logout","user_revoked","admin_revoked","security_concern","password_changed","expired","replaced"]},{name:"is_current",type:"boolean",notNull:!0,default:!1},{name:"login_method",type:"varchar",length:50,enumValues:["password","oauth_google","oauth_github","oauth_microsoft","magic_link","sso","api_key"]},{name:"remember_me",type:"boolean",notNull:!0,default:!1},{name:"trust_score",type:"integer",default:100},{name:"approval_status",type:"varchar",length:20,default:"approved",enumValues:["approved","pending","rejected"]},{name:"approval_token",type:"varchar",length:64},{name:"approval_requested_at",type:"timestamptz"},{name:"approval_responded_at",type:"timestamptz"}],indexes:[{columns:["user_id"]},{columns:["token_hash"],unique:!0},{columns:["refresh_token_hash"]},{columns:["user_id","is_active"]},{columns:["expires_at"]},{columns:["device_fingerprint"]},{columns:["ip_address"]},{columns:["last_activity_at"]},{columns:["approval_status"]},{columns:["approval_token"]}]},{table_name:"trusted_devices",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,group_name:"Authentication",available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"token_hash",type:"varchar",length:64,notNull:!0},{name:"status",type:"varchar",length:20,notNull:!0,default:"pending",enumValues:["pending","trusted","revoked"]},{name:"origin_session_id",type:"uuid"},{name:"label",type:"varchar",length:120},{name:"device_fingerprint",type:"varchar",length:255},{name:"first_seen_ip",type:"varchar",length:45},{name:"last_seen_ip",type:"varchar",length:45},{name:"last_seen_at",type:"timestamptz"},{name:"expires_at",type:"timestamptz"},{name:"revoked_at",type:"timestamptz"},{name:"revoked_reason",type:"varchar",length:30,enumValues:["user_revoked","password_reset","logout","admin_revoked","expired","replaced"]}],indexes:[{columns:["token_hash"],unique:!0},{columns:["user_id"]},{columns:["user_id","status"]},{columns:["origin_session_id"]},{columns:["expires_at"]}]},{table_name:"password_reset_tokens",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,group_name:"Authentication",requires:["email"],available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"token_hash",type:"varchar",length:255,notNull:!0},{name:"expires_at",type:"timestamptz",notNull:!0},{name:"used_at",type:"timestamptz"}],indexes:[{columns:["token_hash"],unique:!0},{columns:["user_id"]},{columns:["expires_at"]}]},{table_name:"magic_link_tokens",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,group_name:"Authentication",requires:["email"],available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"email",type:"varchar",length:255,notNull:!0},{name:"token_hash",type:"varchar",length:255,notNull:!0},{name:"expires_at",type:"timestamptz",notNull:!0},{name:"used_at",type:"timestamptz"}],indexes:[{columns:["token_hash"],unique:!0},{columns:["user_id"]},{columns:["email"]},{columns:["expires_at"]}]},{table_name:"webauthn_credentials",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,group_name:"Authentication",requires:[],available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"credential_id",type:"text",notNull:!0},{name:"public_key",type:"text",notNull:!0},{name:"counter",type:"bigint",mode:"number",notNull:!0,defaultValue:0},{name:"transports",type:"jsonb"},{name:"device_type",type:"varchar",length:32},{name:"backed_up",type:"boolean",notNull:!0,defaultValue:!1},{name:"aaguid",type:"varchar",length:64},{name:"authenticator_attachment",type:"varchar",length:32},{name:"nickname",type:"varchar",length:128},{name:"last_used_at",type:"timestamptz"},{name:"revoked_at",type:"timestamptz"}],indexes:[{columns:["credential_id"],unique:!0},{columns:["user_id"]}]},{table_name:"webauthn_challenges",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,group_name:"Authentication",requires:[],available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE","GET"],columns:[{name:"user_id",type:"uuid",references:{table:"users",column:"id",onDelete:"cascade"}},{name:"challenge",type:"text",notNull:!0},{name:"challenge_type",type:"varchar",length:32,notNull:!0},{name:"expires_at",type:"timestamptz",notNull:!0},{name:"consumed_at",type:"timestamptz"}],indexes:[{columns:["challenge"],unique:!0},{columns:["user_id"]},{columns:["expires_at"]}]},{table_name:"audit_logs",feature_set:["audit"],add_base_columns:!1,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","DELETE","PATCH","TOGGLE","VERIFICATION"],columns:[{name:"id",type:"uuid",primaryKey:!0,defaultRaw:"gen_random_uuid()"},{name:"entity_id",type:"uuid"},{name:"entity_name",type:"text",notNull:!0},{name:"operation_type",type:"text",notNull:!0},{name:"user_id",type:"uuid"},{name:"ip_address",type:"text"},{name:"user_agent",type:"text"},{name:"summary",type:"text"},{name:"severity",type:"text",default:"info"},{name:"category",type:"text"},{name:"occurrence_count",type:"integer",default:1},{name:"last_occurrence_at",type:"timestamp"},{name:"old_values",type:"jsonb"},{name:"new_values",type:"jsonb"},{name:"created_at",type:"timestamp",notNull:!0,defaultRaw:"now()"},{name:"path",type:"text"},{name:"query",type:"text"}],indexes:[{columns:["entity_id"]},{columns:["entity_name"]},{columns:["user_id"]},{columns:["created_at"]},{columns:["severity"]},{columns:["category"]}]},{table_name:"monitoring_metrics",feature_set:["monitoring"],add_base_columns:!1,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","DELETE","PATCH","TOGGLE","VERIFICATION"],columns:[{name:"id",type:"uuid",primaryKey:!0,defaultRaw:"gen_random_uuid()"},{name:"metric_type",type:"text",notNull:!0},{name:"metric_name",type:"text",notNull:!0},{name:"value",type:"doublePrecision",notNull:!0},{name:"tags",type:"jsonb"},{name:"recorded_at",type:"timestamp",notNull:!0}],indexes:[{columns:["metric_type"]},{columns:["metric_name"]},{columns:["recorded_at"]}]},{table_name:"oauth_accounts",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!1,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"provider",type:"varchar",length:50,notNull:!0,enumValues:["google","github","microsoft","discord","facebook","twitter","apple","custom"]},{name:"provider_account_id",type:"varchar",length:255,notNull:!0},{name:"provider_email",type:"varchar",length:255},{name:"provider_name",type:"varchar",length:255},{name:"provider_avatar_url",type:"text"},{name:"access_token",type:"text"},{name:"refresh_token",type:"text"},{name:"token_expires_at",type:"timestamp"},{name:"scope",type:"text"},{name:"raw_profile",type:"jsonb"},{name:"is_primary",type:"boolean",notNull:!0,default:!1},{name:"last_used_at",type:"timestamp"}],indexes:[{columns:["user_id"]},{columns:["provider","provider_account_id"],unique:!0},{columns:["provider_email"]},{columns:["user_id","provider"]}],constraints:{unique:[{name:"unique_provider_account",columns:["provider","provider_account_id"]}]}},{table_name:"api_keys",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH"],bulk_endpoints_enabled:!1,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"name",type:"varchar",length:255,notNull:!0},{name:"description",type:"text"},{name:"key_hash",type:"varchar",length:255,notNull:!0},{name:"key_preview",type:"varchar",length:20,notNull:!0},{name:"owner_type",type:"varchar",length:30,notNull:!0,default:"personal",enumValues:["personal","application"]},{name:"application_name",type:"varchar",length:255},{name:"allowed_roles",type:"jsonb",notNull:!0,default:"[]"},{name:"allowed_claims",type:"jsonb",notNull:!0,default:"[]"},{name:"allowed_scopes",type:"jsonb",notNull:!0,default:"[]"},{name:"expires_at",type:"timestamptz"},{name:"last_used_at",type:"timestamptz"},{name:"last_used_ip",type:"varchar",length:45},{name:"usage_count",type:"integer",notNull:!0,default:0},{name:"revoked_at",type:"timestamptz"},{name:"revoked_reason",type:"varchar",length:255}],indexes:[{columns:["key_hash"],unique:!0},{columns:["user_id"]},{columns:["user_id","is_active"]},{columns:["owner_type"]},{columns:["expires_at"]},{columns:["last_used_at"]}]},{table_name:"backup_logs",feature_set:["backup"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main","all"],excluded_schemas:[],excluded_methods:["PUT","PATCH"],columns:[{name:"backup_name",type:"varchar",length:255,notNull:!0},{name:"file_name",type:"varchar",length:500,notNull:!0},{name:"schema_name",type:"varchar",length:100,notNull:!0},{name:"format",type:"varchar",length:20,notNull:!0,default:"json"},{name:"status",type:"varchar",length:20,notNull:!0,default:"pending"},{name:"trigger",type:"varchar",length:20,notNull:!0,default:"manual"},{name:"size_bytes",type:"integer"},{name:"table_count",type:"integer"},{name:"row_count",type:"integer"},{name:"included_tables",type:"jsonb",default:"[]"},{name:"excluded_tables",type:"jsonb",default:"[]"},{name:"error_message",type:"text"},{name:"started_at",type:"timestamp"},{name:"completed_at",type:"timestamp"},{name:"performed_by",type:"varchar",length:255},{name:"cron_expression",type:"varchar",length:100},{name:"retention_days",type:"integer"}],indexes:[{columns:["schema_name"]},{columns:["status"]},{columns:["trigger"]},{columns:["created_at"]}]},{table_name:"payment_transactions",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"user_id",type:"uuid",references:{table:"users",column:"id"}},{name:"order_id",type:"varchar",length:255},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_transaction_id",type:"varchar",length:255},{name:"provider_payment_id",type:"varchar",length:255},{name:"payment_method",type:"varchar",length:50},{name:"amount",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"currency",type:"varchar",length:10,notNull:!0,default:"TRY"},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","processing","completed","failed","refunded","partially_refunded","cancelled"]},{name:"status_code",type:"integer"},{name:"status_message",type:"text"},{name:"card_last_four",type:"varchar",length:4},{name:"card_type",type:"varchar",length:50},{name:"card_association",type:"varchar",length:50},{name:"installment",type:"integer",default:1},{name:"is_three_d_secure",type:"boolean",default:!1},{name:"provider_response",type:"jsonb",default:"{}"},{name:"metadata",type:"jsonb",default:"{}"},{name:"refunded_amount",type:"numeric",precision:12,scale:2,default:0},{name:"refunded_at",type:"timestamptz"},{name:"completed_at",type:"timestamptz"},{name:"failed_at",type:"timestamptz"},{name:"ip_address",type:"varchar",length:45}],indexes:[{columns:["user_id"]},{columns:["order_id"]},{columns:["provider"]},{columns:["provider_payment_id"]},{columns:["status"]},{columns:["user_id","status"]}]},{table_name:"payment_methods",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"type",type:"varchar",length:30,notNull:!0,default:"card",enumValues:["card","bank_account","wallet"]},{name:"alias",type:"varchar",length:100},{name:"card_last_four",type:"varchar",length:4},{name:"card_type",type:"varchar",length:50},{name:"card_association",type:"varchar",length:50},{name:"card_family",type:"varchar",length:100},{name:"card_bank_name",type:"varchar",length:100},{name:"provider_card_user_key",type:"varchar",length:255},{name:"provider_card_token",type:"varchar",length:255},{name:"bin_number",type:"varchar",length:8},{name:"is_default",type:"boolean",default:!1},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["user_id"]},{columns:["provider"]},{columns:["user_id","is_default"]},{columns:["provider_card_user_key"]}]},{table_name:"payment_webhook_logs",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["PUT","PATCH","DELETE"],columns:[{name:"provider",type:"varchar",length:50,notNull:!0},{name:"event_type",type:"varchar",length:100,notNull:!0},{name:"provider_payment_id",type:"varchar",length:255},{name:"raw_payload",type:"jsonb",notNull:!0},{name:"processed",type:"boolean",default:!1},{name:"processing_result",type:"jsonb"},{name:"error_message",type:"text"},{name:"ip_address",type:"varchar",length:45},{name:"idempotency_key",type:"varchar",length:255}],indexes:[{columns:["provider"]},{columns:["event_type"]},{columns:["provider_payment_id"]},{columns:["processed"]},{columns:["idempotency_key"],unique:!0}]},{table_name:"payment_sub_merchants",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",references:{table:"users",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_sub_merchant_key",type:"varchar",length:255},{name:"external_id",type:"varchar",length:255},{name:"type",type:"varchar",length:50,notNull:!0,default:"personal",enumValues:["personal","private_company","limited_or_joint_stock_company"]},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","active","suspended","rejected"]},{name:"name",type:"varchar",length:255,notNull:!0},{name:"email",type:"varchar",length:255,notNull:!0},{name:"gsm_number",type:"varchar",length:20},{name:"address",type:"text"},{name:"iban",type:"varchar",length:50},{name:"contact_name",type:"varchar",length:100},{name:"contact_surname",type:"varchar",length:100},{name:"identity_number",type:"varchar",length:20},{name:"tax_office",type:"varchar",length:100},{name:"tax_number",type:"varchar",length:20},{name:"legal_company_title",type:"varchar",length:255},{name:"currency",type:"varchar",length:10,default:"TRY"},{name:"commission_rate",type:"numeric",precision:5,scale:2,default:0},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["user_id"]},{columns:["provider"]},{columns:["provider_sub_merchant_key"]},{columns:["external_id"]},{columns:["status"]},{columns:["email"]}]},{table_name:"payment_commission_splits",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"transaction_id",type:"uuid",notNull:!0,references:{table:"payment_transactions",column:"id",onDelete:"cascade"}},{name:"sub_merchant_id",type:"uuid",notNull:!0,references:{table:"payment_sub_merchants",column:"id"}},{name:"basket_item_id",type:"varchar",length:255},{name:"item_price",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"sub_merchant_price",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"platform_commission",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"commission_rate",type:"numeric",precision:5,scale:2,default:0},{name:"provider_split_id",type:"varchar",length:255},{name:"currency",type:"varchar",length:10,notNull:!0,default:"TRY"},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","approved","disapproved","refunded"]},{name:"approved_at",type:"timestamptz"},{name:"disapproved_at",type:"timestamptz"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["transaction_id"]},{columns:["sub_merchant_id"]},{columns:["status"]},{columns:["transaction_id","sub_merchant_id"]},{columns:["provider_split_id"]}]},{table_name:"payment_products",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_product_id",type:"varchar",length:255},{name:"name",type:"varchar",length:255,notNull:!0},{name:"description",type:"text"},{name:"type",type:"varchar",length:30,default:"service",enumValues:["service","good"]},{name:"status",type:"varchar",length:30,notNull:!0,default:"active",enumValues:["active","archived","draft"]},{name:"images",type:"jsonb",default:"[]"},{name:"unit_label",type:"varchar",length:50},{name:"url",type:"varchar",length:500},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["provider"]},{columns:["provider_product_id"]},{columns:["name"]},{columns:["status"]},{columns:["type"]}]},{table_name:"payment_prices",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"product_id",type:"uuid",notNull:!0,references:{table:"payment_products",column:"id",onDelete:"cascade"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_price_id",type:"varchar",length:255},{name:"currency",type:"varchar",length:10,notNull:!0,default:"USD"},{name:"unit_amount",type:"integer",notNull:!0,default:0},{name:"unit_amount_decimal",type:"varchar",length:30},{name:"type",type:"varchar",length:30,notNull:!0,default:"one_time",enumValues:["one_time","recurring"]},{name:"billing_scheme",type:"varchar",length:30,default:"per_unit",enumValues:["per_unit","tiered"]},{name:"nickname",type:"varchar",length:255},{name:"recurring_interval",type:"varchar",length:20,enumValues:["day","week","month","year"]},{name:"recurring_interval_count",type:"integer",default:1},{name:"recurring_usage_type",type:"varchar",length:20,default:"licensed",enumValues:["licensed","metered"]},{name:"recurring_aggregate_usage",type:"varchar",length:30,enumValues:["sum","last_during_period","last_ever","max"]},{name:"transform_quantity_divide_by",type:"integer"},{name:"transform_quantity_round",type:"varchar",length:10,enumValues:["up","down"]},{name:"status",type:"varchar",length:30,notNull:!0,default:"active",enumValues:["active","archived"]},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["product_id"]},{columns:["provider"]},{columns:["provider_price_id"]},{columns:["type"]},{columns:["currency"]},{columns:["status"]},{columns:["product_id","status"]}]},{table_name:"payment_customers",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",references:{table:"users",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_customer_id",type:"varchar",length:255,notNull:!0},{name:"email",type:"varchar",length:255,notNull:!0},{name:"name",type:"varchar",length:255},{name:"phone",type:"varchar",length:50},{name:"description",type:"text"},{name:"address",type:"jsonb",default:"{}"},{name:"tax_id_type",type:"varchar",length:50},{name:"tax_id_value",type:"varchar",length:100},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["user_id"]},{columns:["provider"]},{columns:["provider_customer_id"]},{columns:["email"]},{columns:["user_id","provider"],unique:!0}]},{table_name:"payment_subscriptions",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"customer_id",type:"uuid",notNull:!0,references:{table:"payment_customers",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_subscription_id",type:"varchar",length:255},{name:"status",type:"varchar",length:30,notNull:!0,default:"incomplete",enumValues:["active","past_due","unpaid","canceled","incomplete","incomplete_expired","trialing","paused"]},{name:"collection_method",type:"varchar",length:30,default:"charge_automatically",enumValues:["charge_automatically","send_invoice"]},{name:"current_period_start",type:"timestamptz"},{name:"current_period_end",type:"timestamptz"},{name:"cancel_at_period_end",type:"boolean",default:!1},{name:"canceled_at",type:"timestamptz"},{name:"trial_start",type:"timestamptz"},{name:"trial_end",type:"timestamptz"},{name:"items",type:"jsonb",default:"[]"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["customer_id"]},{columns:["provider"]},{columns:["provider_subscription_id"]},{columns:["status"]},{columns:["customer_id","status"]}]},{table_name:"payment_invoices",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"customer_id",type:"uuid",notNull:!0,references:{table:"payment_customers",column:"id"}},{name:"subscription_id",type:"uuid",references:{table:"payment_subscriptions",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_invoice_id",type:"varchar",length:255},{name:"status",type:"varchar",length:30,notNull:!0,default:"draft",enumValues:["draft","open","paid","uncollectible","void"]},{name:"collection_method",type:"varchar",length:30,default:"charge_automatically",enumValues:["charge_automatically","send_invoice"]},{name:"currency",type:"varchar",length:10,notNull:!0,default:"USD"},{name:"amount_due",type:"integer",default:0},{name:"amount_paid",type:"integer",default:0},{name:"amount_remaining",type:"integer",default:0},{name:"description",type:"text"},{name:"hosted_invoice_url",type:"varchar",length:1000},{name:"invoice_pdf",type:"varchar",length:1000},{name:"due_date",type:"timestamptz"},{name:"days_until_due",type:"integer"},{name:"period_start",type:"timestamptz"},{name:"period_end",type:"timestamptz"},{name:"paid_at",type:"timestamptz"},{name:"voided_at",type:"timestamptz"},{name:"lines",type:"jsonb",default:"[]"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["customer_id"]},{columns:["subscription_id"]},{columns:["provider"]},{columns:["provider_invoice_id"]},{columns:["status"]},{columns:["customer_id","status"]}]},{table_name:"chat_conversations",feature_set:["authentication","chat"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"type",type:"varchar",length:20,notNull:!0,default:"direct",enumValues:["direct","group"]},{name:"title",type:"varchar",length:255},{name:"description",type:"text"},{name:"avatar_file_id",type:"uuid"},{name:"direct_key",type:"varchar",length:255},{name:"last_message_at",type:"timestamptz"},{name:"last_message_preview",type:"varchar",length:500},{name:"last_message_sender_id",type:"uuid",references:{table:"users",column:"id",onDelete:"set null"}}],indexes:[{columns:["direct_key"],unique:!0},{columns:["type"]},{columns:["last_message_at"]}]},{table_name:"chat_participants",feature_set:["authentication","chat"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"conversation_id",type:"uuid",notNull:!0,references:{table:"chat_conversations",column:"id",onDelete:"cascade"}},{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"role",type:"varchar",length:20,notNull:!0,default:"member",enumValues:["member","admin","owner"]},{name:"last_read_message_id",type:"uuid"},{name:"last_read_at",type:"timestamptz"},{name:"unread_count",type:"integer",notNull:!0,default:0},{name:"muted",type:"boolean",notNull:!0,default:!1},{name:"muted_until",type:"timestamptz"},{name:"notifications_enabled",type:"boolean",notNull:!0,default:!0},{name:"left_at",type:"timestamptz"}],indexes:[{columns:["user_id"]},{columns:["conversation_id"]}],constraints:{unique:[{name:"unique_conversation_participant",columns:["conversation_id","user_id"]}]}},{table_name:"chat_messages",feature_set:["authentication","chat"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"conversation_id",type:"uuid",notNull:!0,references:{table:"chat_conversations",column:"id",onDelete:"cascade"}},{name:"sender_id",type:"uuid",references:{table:"users",column:"id",onDelete:"set null"}},{name:"content",type:"text"},{name:"content_type",type:"varchar",length:20,notNull:!0,default:"text",enumValues:["text","image","file","video","audio","system"]},{name:"reply_to_id",type:"uuid",references:{table:"chat_messages",column:"id",onDelete:"set null"}},{name:"metadata",type:"jsonb",default:"{}"},{name:"client_message_id",type:"varchar",length:100},{name:"edited_at",type:"timestamptz"},{name:"deleted_at",type:"timestamptz"}],indexes:[{columns:["conversation_id","created_at"]},{columns:["sender_id"]},{columns:["reply_to_id"]}]},{table_name:"chat_message_attachments",feature_set:["authentication","chat","storage"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"message_id",type:"uuid",notNull:!0,references:{table:"chat_messages",column:"id",onDelete:"cascade"}},{name:"conversation_id",type:"uuid",notNull:!0,references:{table:"chat_conversations",column:"id",onDelete:"cascade"}},{name:"file_id",type:"uuid",notNull:!0,references:{table:"files",column:"id",onDelete:"cascade"}},{name:"kind",type:"varchar",length:20,notNull:!0,default:"file",enumValues:["image","video","audio","file"]},{name:"original_name",type:"varchar",length:255},{name:"mime_type",type:"varchar",length:100},{name:"size",type:"bigint",mode:"number"},{name:"width",type:"integer"},{name:"height",type:"integer"},{name:"duration",type:"integer"}],indexes:[{columns:["message_id"]},{columns:["conversation_id"]},{columns:["file_id"]}]},{table_name:"payment_splits",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],group_name:"Payments Marketplace",columns:[{name:"transaction_id",type:"uuid",references:{table:"paymentTransactions",column:"id",onDelete:"set null"}},{name:"recipient_owner_type",type:"varchar",length:20,notNull:!0,default:"seller",comment:"seller | platform | tenant | user"},{name:"recipient_owner_id",type:"uuid",notNull:!0},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"gross_amount",type:"bigint",mode:"number",notNull:!0,comment:"Minor units"},{name:"provider_fee_amount",type:"bigint",mode:"number",notNull:!0,default:0},{name:"platform_fee_amount",type:"bigint",mode:"number",notNull:!0,default:0},{name:"reserve_amount",type:"bigint",mode:"number",notNull:!0,default:0},{name:"net_payable_amount",type:"bigint",mode:"number",notNull:!0},{name:"currency",type:"varchar",length:10,notNull:!0},{name:"available_for_payout_at",type:"timestamptz"},{name:"status",type:"varchar",length:20,notNull:!0,default:"pending",comment:"pending | available | payout_requested | paid | held | refunded | disputed | cancelled"},{name:"source_type",type:"varchar",length:50},{name:"source_id",type:"varchar",length:255},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["recipient_owner_type","recipient_owner_id"]},{columns:["status"]},{columns:["transaction_id"]}]},{table_name:"payment_ledger_entries",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],group_name:"Payments Marketplace",columns:[{name:"account",type:"varchar",length:40,notNull:!0,comment:"platform_revenue | provider_fee | seller_payable | reserve | refund_liability | dispute_liability | payout_in_transit | payout_completed"},{name:"owner_type",type:"varchar",length:20},{name:"owner_id",type:"uuid"},{name:"direction",type:"varchar",length:6,notNull:!0,comment:"debit | credit"},{name:"amount",type:"bigint",mode:"number",notNull:!0,comment:"Minor units"},{name:"currency",type:"varchar",length:10,notNull:!0},{name:"entry_type",type:"varchar",length:40,notNull:!0,comment:"split | refund | payout | reserve_hold | reserve_release | dispute | adjustment"},{name:"reference_type",type:"varchar",length:50},{name:"reference_id",type:"varchar",length:255},{name:"split_id",type:"uuid",references:{table:"paymentSplits",column:"id",onDelete:"set null"}},{name:"description",type:"text"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["account"]},{columns:["owner_type","owner_id"]},{columns:["entry_type"]},{columns:["reference_type","reference_id"]}]},{table_name:"payment_settlement_policies",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],group_name:"Payments Marketplace",columns:[{name:"owner_type",type:"varchar",length:20,notNull:!0,default:"tenant",comment:"tenant | seller"},{name:"owner_id",type:"uuid",notNull:!0},{name:"default_delay_days",type:"integer",notNull:!0,default:7},{name:"new_seller_delay_days",type:"integer",notNull:!0,default:14},{name:"reserve_rate",type:"numeric",precision:5,scale:4,notNull:!0,default:0,comment:"Fraction 0..1 held as reserve"},{name:"reserve_days",type:"integer",notNull:!0,default:0},{name:"minimum_payout_amount",type:"bigint",mode:"number",notNull:!0,default:0},{name:"currency",type:"varchar",length:10},{name:"early_payout_enabled",type:"boolean",notNull:!0,default:!1},{name:"status",type:"varchar",length:20,notNull:!0,default:"active"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["owner_type","owner_id"],unique:!0}]},{table_name:"payment_reserves",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],group_name:"Payments Marketplace",columns:[{name:"owner_type",type:"varchar",length:20,notNull:!0,default:"seller"},{name:"owner_id",type:"uuid",notNull:!0},{name:"split_id",type:"uuid",references:{table:"paymentSplits",column:"id",onDelete:"set null"}},{name:"amount",type:"bigint",mode:"number",notNull:!0},{name:"currency",type:"varchar",length:10,notNull:!0},{name:"reason",type:"varchar",length:30,notNull:!0,default:"refund_window",comment:"refund_window | chargeback_risk | new_seller | manual_hold | dispute | compliance_review"},{name:"status",type:"varchar",length:20,notNull:!0,default:"held",comment:"held | released | consumed | cancelled"},{name:"release_at",type:"timestamptz"},{name:"released_at",type:"timestamptz"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["owner_type","owner_id"]},{columns:["status"]},{columns:["release_at"]}]},{table_name:"payment_payout_requests",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["PUT"],group_name:"Payments Marketplace",columns:[{name:"recipient_owner_type",type:"varchar",length:20,notNull:!0,default:"seller"},{name:"recipient_owner_id",type:"uuid",notNull:!0},{name:"amount",type:"bigint",mode:"number",notNull:!0},{name:"currency",type:"varchar",length:10,notNull:!0},{name:"status",type:"varchar",length:20,notNull:!0,default:"pending",comment:"pending | approved | rejected | processing | completed | failed | cancelled"},{name:"provider",type:"varchar",length:50},{name:"provider_payout_id",type:"varchar",length:255},{name:"provider_transfer_id",type:"varchar",length:255},{name:"destination",type:"varchar",length:255},{name:"requested_by",type:"uuid"},{name:"decided_by",type:"uuid"},{name:"decided_at",type:"timestamptz"},{name:"completed_at",type:"timestamptz"},{name:"failure_reason",type:"text"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["recipient_owner_type","recipient_owner_id"]},{columns:["status"]}]},{table_name:"payment_disputes",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["PUT"],group_name:"Payments Marketplace",columns:[{name:"transaction_id",type:"uuid",references:{table:"paymentTransactions",column:"id",onDelete:"set null"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_dispute_id",type:"varchar",length:255},{name:"owner_type",type:"varchar",length:20},{name:"owner_id",type:"uuid"},{name:"amount",type:"bigint",mode:"number"},{name:"currency",type:"varchar",length:10},{name:"reason",type:"varchar",length:100},{name:"status",type:"varchar",length:30,notNull:!0,default:"open",comment:"open | under_review | won | lost | accepted | cancelled"},{name:"evidence_due_at",type:"timestamptz"},{name:"resolved_at",type:"timestamptz"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["provider","provider_dispute_id"]},{columns:["status"]},{columns:["owner_type","owner_id"]},{columns:["transaction_id"]}]},{table_name:"nucleus_secrets",feature_set:["secrets"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["GET","POST","PUT","PATCH","DELETE","TOGGLE"],bulk_endpoints_enabled:!1,group_name:"Secrets",columns:[{name:"scope",type:"varchar",length:200,notNull:!0,comment:"Config dot-path that owns the credential, e.g. authentication.oauth.providers.microsoft"},{name:"key",type:"varchar",length:120,notNull:!0,comment:"Leaf key under that path, e.g. clientSecret"},{name:"value_enc",type:"text",notNull:!0,comment:"AES-256-GCM envelope v1:iv:tag:ciphertext \u2014 never returned by any route"},{name:"previous_enc",type:"text",comment:"Value replaced by the last rotation, retained for one-step rollback"},{name:"preview",type:"varchar",length:80},{name:"kind",type:"varchar",length:30,notNull:!0,default:"text",enumValues:["text","password","json","connection_string","pem"]},{name:"description",type:"varchar",length:500},{name:"version",type:"integer",notNull:!0,default:1},{name:"rotated_at",type:"timestamptz"},{name:"last_used_at",type:"timestamptz"}],indexes:[{columns:["scope","key"],unique:!0},{columns:["scope"]}]},{table_name:"integration_sources",feature_set:["integrations"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!1,group_name:"Integrations",columns:[{name:"name",type:"varchar",length:150,notNull:!0},{name:"slug",type:"varchar",length:150,notNull:!0,comment:"Stable machine name; referenced by exports and by operators in logs"},{name:"base_url",type:"varchar",length:500,notNull:!0,comment:"Any scheme, host and port \u2014 https, plain http, in-cluster DNS, IP. HTTPS is NOT required and must never be enforced: reaching a service inside the same cluster over http is a legitimate deployment."},{name:"description",type:"text"},{name:"enabled",type:"boolean",default:!0},{name:"auth_type",type:"varchar",length:20,notNull:!0,default:"none",enumValues:["none","bearer","api_key","basic","oauth2"]},{name:"auth_token_encrypted",type:"text",sensitive:!0,comment:"Static credential (bearer / api key / basic blob), encrypted at rest"},{name:"auth_token_hint",type:"varchar",length:24},{name:"auth_header_name",type:"varchar",length:80,default:"Authorization"},{name:"auth_query_param",type:"varchar",length:80,comment:"When set, an api_key credential travels as this query parameter instead of a header"},{name:"extra_headers",type:"jsonb",default:{}},{name:"token_url",type:"varchar",length:500},{name:"oauth_grant_type",type:"varchar",length:40,default:"password",enumValues:["password","client_credentials"]},{name:"oauth_client_id",type:"varchar",length:200},{name:"oauth_client_secret_encrypted",type:"text",sensitive:!0},{name:"oauth_client_secret_hint",type:"varchar",length:24},{name:"oauth_username",type:"varchar",length:200},{name:"oauth_password_encrypted",type:"text",sensitive:!0},{name:"oauth_password_hint",type:"varchar",length:24},{name:"oauth_scope",type:"varchar",length:300},{name:"oauth_client_auth",type:"varchar",length:20,default:"basic",enumValues:["basic","body"]},{name:"tls_verify",type:"boolean",notNull:!0,default:!0,comment:"Per-source certificate verification. Turning it off applies to THIS source's connections only \u2014 never to the process, which is what a NODE_TLS_REJECT_UNAUTHORIZED toggle would do."},{name:"timeout_ms",type:"integer",notNull:!0,default:30000},{name:"spec_url",type:"varchar",length:500,comment:"Optional API description document (OpenAPI/Swagger/Postman/Bruno). Discovery is a convenience: every endpoint can always be defined by hand instead."},{name:"spec_format",type:"varchar",length:20,default:"manual",enumValues:["manual","openapi","swagger","postman","bruno","har"]}],constraints:{unique:[{name:"uniq_integration_source_slug",columns:["slug"]}]},indexes:[{columns:["enabled"]}]},{table_name:"integration_endpoints",feature_set:["integrations"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!1,group_name:"Integrations",columns:[{name:"source_id",type:"uuid",notNull:!0,references:{table:"integrationSources",column:"id",onDelete:"cascade"}},{name:"tag",type:"varchar",length:120,notNull:!0},{name:"name",type:"varchar",length:200},{name:"method",type:"varchar",length:10,notNull:!0,default:"GET",enumValues:["GET","POST","PUT","PATCH","DELETE"]},{name:"path",type:"varchar",length:500,notNull:!0,comment:"Appended to the source base URL. May carry {brace} or :colon path tokens, whose values come from param_bindings."},{name:"description",type:"text"},{name:"query_params",type:"jsonb",default:{}},{name:"request_body",type:"jsonb",default:{}},{name:"param_bindings",type:"jsonb",default:[],comment:"Where each path/query parameter comes from: a static value, another endpoint's records (fan-out), or a column of one of our own tables."},{name:"pagination",type:"jsonb",default:{},comment:"Explicitly chosen paging profile (none/page_number/offset/cursor/link_header). Never guessed \u2014 a wrong guess silently imports one page."},{name:"response_root_path",type:"varchar",length:200},{name:"tree_children_path",type:"varchar",length:200,comment:"Field holding a record's children when the source answers with a shape rather than a list \u2014 each node then becomes its own row and knows its parent"},{name:"sample_response",type:"jsonb",default:{},comment:"A few real records captured by a live test, so the mapping screen still shows fields when the source is unreachable"},{name:"enabled",type:"boolean",default:!0}],indexes:[{columns:["source_id"]},{columns:["source_id","tag"]}]},{table_name:"integration_mappings",feature_set:["integrations"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!1,group_name:"Integrations",columns:[{name:"endpoint_id",type:"uuid",notNull:!0,references:{table:"integrationEndpoints",column:"id",onDelete:"cascade"}},{name:"name",type:"varchar",length:200,notNull:!0},{name:"target_entity",type:"varchar",length:120,notNull:!0,comment:"snake_case table name this mapping writes into"},{name:"field_mappings",type:"jsonb",notNull:!0,default:[]},{name:"reference_checks",type:"jsonb",notNull:!0,default:[],comment:"Columns whose value must already exist in another entity, and what to do when it does not."},{name:"dedup_source_field",type:"varchar",length:200},{name:"dedup_target_field",type:"varchar",length:200,comment:"Target column that identifies the same record across runs. Without it nothing can be matched and every run appends."},{name:"write_mode",type:"varchar",length:20,notNull:!0,default:"upsert",enumValues:["upsert","append","replace"],comment:"replace is the destructive wipe-and-rewrite; it is no longer the default and is gated by the completeness check."},{name:"missing_record_policy",type:"varchar",length:20,notNull:!0,default:"ignore",enumValues:["ignore","deactivate","delete"],comment:"What happens to a row that exists here but no longer in the source. deactivate is the right answer for most HR data and could not be expressed before."},{name:"missing_record_column",type:"varchar",length:120},{name:"missing_record_value",type:"varchar",length:200},{name:"origin_column",type:"varchar",length:120,comment:"Column this mapping stamps on rows it owns. Set it when the target table ALSO holds rows people create by hand: without it every hand-made row looks like one the source stopped carrying, and the first run with a removal policy deletes them all."},{name:"origin_value",type:"varchar",length:120,comment:"The value written into origin_column. Rows carrying it are the only removal candidates."},{name:"max_removal_share",type:"numeric",comment:"Share of the target table (0-1) above which an UNATTENDED run refuses to remove. A scheduled run passes through neither the preview nor a confirmation, so this is the only thing between a wrong plan and the table. 0 or null disables."},{name:"password_target_column",type:"varchar",length:100,comment:"Column that receives the shared opening password given at run time. The password itself is never stored."},{name:"account_rule",type:"jsonb",comment:"Creates a login alongside each imported record, in the same transaction, and links it. The password belongs to the run, never to this row."},{name:"schedule_cron",type:"varchar",length:120},{name:"schedule_timezone",type:"varchar",length:64,comment:"IANA zone the cron expression is read in. Without it a nightly job drifts with the container's clock."},{name:"schedule_enabled",type:"boolean",notNull:!0,default:!1},{name:"last_run_at",type:"timestamptz"},{name:"enabled",type:"boolean",default:!0}],indexes:[{columns:["endpoint_id"]},{columns:["target_entity"]},{columns:["schedule_enabled"]}]},{table_name:"integration_runs",feature_set:["integrations"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],bulk_endpoints_enabled:!1,group_name:"Integrations",columns:[{name:"mapping_id",type:"uuid",references:{table:"integrationMappings",column:"id",onDelete:"set null"},comment:"Nullable and NOT cascaded: deleting a mapping must not erase the record that it once rewrote a table."},{name:"target_entity",type:"varchar",length:120},{name:"write_mode",type:"varchar",length:20,enumValues:["upsert","append","replace"]},{name:"status",type:"varchar",length:20,notNull:!0,default:"queued",enumValues:["queued","running","succeeded","failed","cancelled","reverted"],comment:"There is deliberately no 'partial': a run either applied in full or not at all."},{name:"trigger",type:"varchar",length:20,notNull:!0,default:"manual",enumValues:["manual","schedule","api"]},{name:"total_fetched",type:"integer",notNull:!0,default:0},{name:"source_reported_total",type:"integer",comment:"What the source said it had. When this and total_fetched disagree, a destructive run refuses to start."},{name:"created_count",type:"integer",notNull:!0,default:0},{name:"references_created_count",type:"integer",notNull:!0,default:0,comment:"Rows this run added to OTHER tables so its records could point at them."},{name:"accounts_created_count",type:"integer",notNull:!0,default:0,comment:"Logins this run created so its records could be signed in to."},{name:"updated_count",type:"integer",notNull:!0,default:0},{name:"skipped_count",type:"integer",notNull:!0,default:0},{name:"deleted_count",type:"integer",notNull:!0,default:0},{name:"deactivated_count",type:"integer",notNull:!0,default:0},{name:"error_count",type:"integer",notNull:!0,default:0},{name:"external_call_count",type:"integer",notNull:!0,default:0},{name:"issues",type:"jsonb",default:[]},{name:"errors",type:"jsonb",default:[]},{name:"cancel_requested",type:"boolean",notNull:!0,default:!1,comment:"Set by the cancel endpoint; the engine checks it at every batch boundary. A dropped HTTP connection is NOT a cancellation."},{name:"started_at",type:"timestamptz"},{name:"finished_at",type:"timestamptz"},{name:"pre_images_expire_at",type:"timestamptz",comment:"After this, the run can no longer be reverted and the UI says so rather than offering a button that quietly does nothing."},{name:"reverted_at",type:"timestamptz"},{name:"reverted_by",type:"uuid",references:{table:"users",column:"id"}},{name:"reverted_run_id",type:"uuid"}],indexes:[{columns:["mapping_id"]},{columns:["status"]},{columns:["target_entity"]},{columns:["created_at"]}]},{table_name:"integration_run_items",feature_set:["integrations"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],bulk_endpoints_enabled:!1,group_name:"Integrations",columns:[{name:"run_id",type:"uuid",notNull:!0,references:{table:"integrationRuns",column:"id",onDelete:"cascade"}},{name:"target_entity",type:"varchar",length:120,notNull:!0},{name:"row_id",type:"uuid"},{name:"action",type:"varchar",length:20,notNull:!0,enumValues:["create","update","delete","deactivate"]},{name:"before",type:"jsonb",comment:"The row as it stood before this run touched it. This is what makes a successful run reversible; the bulk delete path already produced these rows and threw them away."},{name:"after",type:"jsonb"}],indexes:[{columns:["run_id"]},{columns:["run_id","action"]},{columns:["target_entity","row_id"]}]}]};var AUTH_ENDPOINT_CONFIGS={login:{key:"LOGIN",method:"POST",defaultRoute:"/auth/login",defaultIsPublic:!0,_payload:void 0,_success:void 0,_error:void 0},register:{key:"REGISTER",method:"POST",defaultRoute:"/auth/register",defaultIsPublic:!0,_payload:void 0,_success:void 0,_error:void 0},logout:{key:"LOGOUT",method:"POST",defaultRoute:"/auth/logout",defaultIsPublic:!1,_payload:void 0,_success:void 0,_error:void 0},refresh:{key:"REFRESH",method:"POST",defaultRoute:"/auth/refresh",defaultIsPublic:!1,_payload:void 0,_success:void 0,_error:void 0},me:{key:"ME",method:"GET",defaultRoute:"/auth/me",defaultIsPublic:!1,_payload:void 0,_success:void 0,_error:void 0},passwordChange:{key:"PASSWORD_CHANGE",method:"POST",defaultRoute:"/auth/password-change",defaultIsPublic:!1,_payload:void 0,_success:void 0,_error:void 0},passwordSet:{key:"PASSWORD_SET",method:"POST",defaultRoute:"/auth/password-set",defaultIsPublic:!1,_payload:void 0,_success:void 0,_error:void 0},passwordReset:{key:"PASSWORD_RESET_REQUEST",method:"POST",defaultRoute:"/auth/password-reset",defaultIsPublic:!0,subEndpoints:[{key:"PASSWORD_RESET_REQUEST",method:"POST",suffix:"/request",_payload:void 0,_success:void 0,_error:void 0},{key:"PASSWORD_RESET_CONFIRM",method:"POST",suffix:"/confirm",_payload:void 0,_success:void 0,_error:void 0}]},sessions:{key:"SESSIONS",method:"GET",defaultRoute:"/auth/sessions",defaultIsPublic:!1,subEndpoints:[{key:"SESSIONS",method:"GET",suffix:"",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_CURRENT",method:"GET",suffix:"/current",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_STATS",method:"GET",suffix:"/stats",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_PENDING",method:"GET",suffix:"/pending",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_REVOKE",method:"DELETE",suffix:"/:sessionId",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_REVOKE_ALL",method:"DELETE",suffix:"/all",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_ADMIN_LIST",method:"GET",suffix:"/admin/:userId",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_ADMIN_REVOKE",method:"DELETE",suffix:"/admin/:userId",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_APPROVE",method:"POST",suffix:"/approve",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_REJECT",method:"POST",suffix:"/reject",_payload:void 0,_success:void 0,_error:void 0}]},magicLink:{key:"MAGIC_LINK",method:"POST",defaultRoute:"/auth/magic-link",defaultIsPublic:!0,subEndpoints:[{key:"MAGIC_LINK",method:"POST",suffix:"",_payload:void 0,_success:void 0,_error:void 0},{key:"MAGIC_LINK_VERIFY",method:"GET",suffix:"/verify",routeKey:"verifyRoute",_payload:void 0,_success:void 0,_error:void 0}]},invite:{key:"INVITE",method:"POST",defaultRoute:"/auth/invite",defaultIsPublic:!1,subEndpoints:[{key:"INVITE",method:"POST",suffix:"",_payload:void 0,_success:void 0,_error:void 0},{key:"INVITE_VERIFY",method:"POST",suffix:"/verify",_payload:void 0,_success:void 0,_error:void 0}]},emailVerification:{key:"VERIFY_EMAIL",method:"GET",defaultRoute:"/verify-email",defaultIsPublic:!0,subEndpoints:[{key:"VERIFY_EMAIL",method:"GET",suffix:"",_payload:void 0,_success:void 0,_error:void 0},{key:"RESEND_VERIFICATION",method:"POST",suffix:"",routeKey:"resendRoute",defaultRoute:"/resend-verification",_payload:void 0,_success:void 0,_error:void 0}]},captcha:{key:"CAPTCHA",method:"GET",defaultRoute:"/auth/captcha",defaultIsPublic:!0,subEndpoints:[{key:"CAPTCHA_GENERATE",method:"GET",suffix:"/generate",_payload:void 0,_success:void 0,_error:void 0},{key:"CAPTCHA_VALIDATE",method:"POST",suffix:"/validate",_payload:void 0,_success:void 0,_error:void 0}]},oauth:{key:"OAUTH_PROVIDERS",method:"GET",defaultRoute:"/auth/oauth/providers",defaultIsPublic:!0,subEndpoints:[{key:"OAUTH_PROVIDERS",method:"GET",suffix:"/providers",_payload:void 0,_success:void 0,_error:void 0},{key:"OAUTH_REDIRECT",method:"GET",suffix:"/:provider",_payload:void 0,_success:void 0,_error:void 0},{key:"OAUTH_ACCOUNTS",method:"GET",suffix:"/accounts",_payload:void 0,_success:void 0,_error:void 0},{key:"OAUTH_UNLINK",method:"DELETE",suffix:"/unlink/:provider",_payload:void 0,_success:void 0,_error:void 0}]},webauthn:{key:"WEBAUTHN",method:"POST",defaultRoute:"/auth/webauthn",defaultIsPublic:!1,subEndpoints:[{key:"WEBAUTHN_REGISTER_OPTIONS",method:"POST",suffix:"/register/options",_payload:void 0,_success:void 0,_error:void 0},{key:"WEBAUTHN_REGISTER_VERIFY",method:"POST",suffix:"/register/verify",_payload:void 0,_success:void 0,_error:void 0},{key:"WEBAUTHN_AUTH_OPTIONS",method:"POST",suffix:"/authenticate/options",_payload:void 0,_success:void 0,_error:void 0},{key:"WEBAUTHN_AUTH_VERIFY",method:"POST",suffix:"/authenticate/verify",_payload:void 0,_success:void 0,_error:void 0},{key:"WEBAUTHN_LIST",method:"GET",suffix:"/credentials",_payload:void 0,_success:void 0,_error:void 0},{key:"WEBAUTHN_REVOKE",method:"DELETE",suffix:"/credentials/:credentialId",_payload:void 0,_success:void 0,_error:void 0},{key:"WEBAUTHN_RENAME",method:"PATCH",suffix:"/credentials/:credentialId",_payload:void 0,_success:void 0,_error:void 0}]},apiKeys:{key:"API_KEYS",method:"GET",defaultRoute:"/auth/api-keys",defaultIsPublic:!1,subEndpoints:[{key:"API_KEYS_CREATE",method:"POST",suffix:"",_payload:void 0,_success:void 0,_error:void 0},{key:"API_KEYS_LIST",method:"GET",suffix:"",_payload:void 0,_success:void 0,_error:void 0},{key:"API_KEYS_DETAIL",method:"GET",suffix:"/:id",_payload:void 0,_success:void 0,_error:void 0},{key:"API_KEYS_UPDATE",method:"PATCH",suffix:"/:id",_payload:void 0,_success:void 0,_error:void 0},{key:"API_KEYS_REVOKE",method:"DELETE",suffix:"/:id",_payload:void 0,_success:void 0,_error:void 0}]}},AUTH_ENDPOINTS={LOGIN:{method:"POST",path:"/auth/login",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},REGISTER:{method:"POST",path:"/auth/register",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},LOGOUT:{method:"POST",path:"/auth/logout",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},REFRESH:{method:"POST",path:"/auth/refresh",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},ME:{method:"GET",path:"/auth/me",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PASSWORD_CHANGE:{method:"POST",path:"/auth/password/change",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PASSWORD_SET:{method:"POST",path:"/auth/password/set",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PASSWORD_RESET_REQUEST:{method:"POST",path:"/auth/password/reset-request",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},PASSWORD_RESET_CONFIRM:{method:"POST",path:"/auth/password/reset-confirm",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},SESSIONS:{method:"GET",path:"/auth/sessions",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},SESSIONS_CURRENT:{method:"GET",path:"/auth/sessions/current",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},SESSIONS_STATS:{method:"GET",path:"/auth/sessions/stats",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},SESSIONS_PENDING:{method:"GET",path:"/auth/sessions/pending",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},SESSIONS_REVOKE:{method:"POST",path:"/auth/sessions/revoke",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},SESSIONS_REVOKE_ALL:{method:"POST",path:"/auth/sessions/revoke-all",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},SESSIONS_ADMIN_LIST:{method:"GET",path:"/auth/sessions/admin/:userId",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},SESSIONS_ADMIN_REVOKE:{method:"DELETE",path:"/auth/sessions/admin/:userId",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},SESSIONS_APPROVE:{method:"POST",path:"/auth/sessions/approve",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},SESSIONS_REJECT:{method:"POST",path:"/auth/sessions/reject",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},MAGIC_LINK:{method:"POST",path:"/auth/magic-link",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},MAGIC_LINK_VERIFY:{method:"POST",path:"/auth/magic-link/verify",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},INVITE:{method:"POST",path:"/auth/invite",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},INVITE_VERIFY:{method:"POST",path:"/auth/invite/verify",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},VERIFY_EMAIL:{method:"POST",path:"/auth/verify-email",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},RESEND_VERIFICATION:{method:"POST",path:"/auth/resend-verification",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},CAPTCHA_GENERATE:{method:"POST",path:"/auth/captcha/generate",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},CAPTCHA_VALIDATE:{method:"POST",path:"/auth/captcha/validate",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},WEBAUTHN_REGISTER_OPTIONS:{method:"POST",path:"/auth/webauthn/register/options",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},WEBAUTHN_REGISTER_VERIFY:{method:"POST",path:"/auth/webauthn/register/verify",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},WEBAUTHN_AUTH_OPTIONS:{method:"POST",path:"/auth/webauthn/authenticate/options",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},WEBAUTHN_AUTH_VERIFY:{method:"POST",path:"/auth/webauthn/authenticate/verify",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},WEBAUTHN_LIST:{method:"GET",path:"/auth/webauthn/credentials",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},WEBAUTHN_REVOKE:{method:"DELETE",path:"/auth/webauthn/credentials/:credentialId",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},WEBAUTHN_RENAME:{method:"PATCH",path:"/auth/webauthn/credentials/:credentialId",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},ADMIN_IMPERSONATE:{method:"POST",path:"/auth/admin/impersonate",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},ADMIN_IMPERSONATE_STOP:{method:"POST",path:"/auth/admin/impersonate/stop",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},ADMIN_CHANGE_USER_ID:{method:"POST",path:"/auth/admin/change-user-id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},ADMIN_CREATE_USER:{method:"POST",path:"/auth/admin/create-user",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},ADMIN_HARD_DELETE_USER:{method:"DELETE",path:"/auth/admin/hard-delete/:userId",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},API_KEYS_CREATE:{method:"POST",path:"/auth/api-keys",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},API_KEYS_LIST:{method:"GET",path:"/auth/api-keys",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},API_KEYS_DETAIL:{method:"GET",path:"/auth/api-keys/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},API_KEYS_UPDATE:{method:"PUT",path:"/auth/api-keys/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},API_KEYS_REVOKE:{method:"DELETE",path:"/auth/api-keys/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0}},CONFIG_ENDPOINTS={CONFIG_GET:{method:"GET",path:"/nucleus/config",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CONFIG_SECTIONS:{method:"GET",path:"/nucleus/config/sections",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CONFIG_SECTION_GET:{method:"GET",path:"/nucleus/config/:section",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CONFIG_SECTION_UPDATE:{method:"PATCH",path:"/nucleus/config/:section",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CONFIG_ENV:{method:"GET",path:"/nucleus/config/env",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CONFIG_OVERRIDES_GET:{method:"GET",path:"/nucleus/config/overrides",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CONFIG_OVERRIDES_CLEAR:{method:"DELETE",path:"/nucleus/config/overrides",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CONFIG_RESTART:{method:"POST",path:"/nucleus/config/restart",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0}},VERIFICATION_ENDPOINTS={VERIFICATION_STATUS:{method:"GET",path:"/verification/status/:entity_name/:entity_id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},VERIFICATION_DECIDE:{method:"POST",path:"/verification/decide/:entity_name/:entity_id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},VERIFICATION_PENDING:{method:"GET",path:"/verification/pending",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},VERIFICATION_HISTORY:{method:"GET",path:"/verification/history/:entity_name/:entity_id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},VERIFICATION_START:{method:"POST",path:"/verification/start",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},VERIFICATION_START_FOR_ENTITY:{method:"POST",path:"/verification/start-for-entity",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},VERIFICATION_ENTITY_STATUSES:{method:"GET",path:"/verification/entity-statuses/:entity_name",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},FLOW_LIST:{method:"GET",path:"/verification/flows",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},FLOW_GET:{method:"GET",path:"/verification/flows/:flow_id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},FLOW_SAVE:{method:"POST",path:"/verification/flows",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},FLOW_PUBLISH:{method:"POST",path:"/verification/flows/:flow_id/publish",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},FLOW_DELETE:{method:"DELETE",path:"/verification/flows/:flow_id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},NOTIFICATION_LIST:{method:"GET",path:"/notifications",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},NOTIFICATION_UNSEEN_COUNT:{method:"GET",path:"/notifications/unseen-count",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},NOTIFICATION_MARK_SEEN:{method:"POST",path:"/notifications/:notification_id/seen",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},NOTIFICATION_MARK_ALL_SEEN:{method:"POST",path:"/notifications/seen-all",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0}},CHAT_ENDPOINTS={CHAT_LIST_CONVERSATIONS:{method:"GET",path:"/chat/conversations",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CHAT_CREATE_CONVERSATION:{method:"POST",path:"/chat/conversations",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CHAT_GET_CONVERSATION:{method:"GET",path:"/chat/conversations/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CHAT_GET_MESSAGES:{method:"GET",path:"/chat/conversations/:id/messages",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CHAT_SEND_MESSAGE:{method:"POST",path:"/chat/conversations/:id/messages",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CHAT_MARK_READ:{method:"POST",path:"/chat/conversations/:id/read",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CHAT_TYPING:{method:"POST",path:"/chat/conversations/:id/typing",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CHAT_ADD_PARTICIPANTS:{method:"POST",path:"/chat/conversations/:id/participants",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CHAT_REMOVE_PARTICIPANT:{method:"DELETE",path:"/chat/conversations/:id/participants/:userId",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CHAT_EDIT_MESSAGE:{method:"PATCH",path:"/chat/messages/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CHAT_DELETE_MESSAGE:{method:"DELETE",path:"/chat/messages/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0}},MONITORING_ENDPOINTS={MONITORING_HEALTH_CHECK:{method:"GET",path:"/monitoring/health",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},MONITORING_GET_SETTINGS:{method:"GET",path:"/monitoring/settings",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},MONITORING_CHANGE_SETTINGS:{method:"PATCH",path:"/monitoring/settings",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},MONITORING_GET_LOGS:{method:"GET",path:"/monitoring/logs",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0}},PAYMENT_ENDPOINTS={PAYMENT_INITIALIZE:{method:"POST",path:"/payments/initialize",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_TRANSACTIONS:{method:"GET",path:"/payments/transactions",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_TRANSACTION_DETAIL:{method:"GET",path:"/payments/transactions/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_BIN_QUERY:{method:"POST",path:"/payments/bin-query",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_DETAIL:{method:"POST",path:"/payments/payment-detail",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_REFUND:{method:"POST",path:"/payments/refund",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_SAVE_CARD:{method:"POST",path:"/payments/cards/save",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_LIST_CARDS:{method:"GET",path:"/payments/cards",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_DELETE_CARD:{method:"DELETE",path:"/payments/cards/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_SYNC_CARDS:{method:"POST",path:"/payments/cards/sync",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_REGISTER_SUB_MERCHANT:{method:"POST",path:"/payments/sub-merchants",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_UPDATE_SUB_MERCHANT:{method:"PUT",path:"/payments/sub-merchants/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_LIST_SUB_MERCHANTS:{method:"GET",path:"/payments/sub-merchants",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_GET_SUB_MERCHANT:{method:"GET",path:"/payments/sub-merchants/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_LIST_SPLITS:{method:"GET",path:"/payments/splits",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_APPROVE_SPLIT:{method:"POST",path:"/payments/splits/:splitId/approve",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_DISAPPROVE_SPLIT:{method:"POST",path:"/payments/splits/:splitId/disapprove",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_CREATE_PRODUCT:{method:"POST",path:"/payments/products",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_UPDATE_PRODUCT:{method:"PUT",path:"/payments/products/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_LIST_PRODUCTS:{method:"GET",path:"/payments/products",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_GET_PRODUCT:{method:"GET",path:"/payments/products/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_ARCHIVE_PRODUCT:{method:"DELETE",path:"/payments/products/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_CREATE_PRICE:{method:"POST",path:"/payments/prices",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_UPDATE_PRICE:{method:"PUT",path:"/payments/prices/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_LIST_PRICES:{method:"GET",path:"/payments/prices",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_GET_PRICE:{method:"GET",path:"/payments/prices/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_ARCHIVE_PRICE:{method:"DELETE",path:"/payments/prices/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_CREATE_CUSTOMER:{method:"POST",path:"/payments/customers",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_UPDATE_CUSTOMER:{method:"PUT",path:"/payments/customers/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_LIST_CUSTOMERS:{method:"GET",path:"/payments/customers",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_GET_CUSTOMER:{method:"GET",path:"/payments/customers/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_DELETE_CUSTOMER:{method:"DELETE",path:"/payments/customers/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_CREATE_SUBSCRIPTION:{method:"POST",path:"/payments/subscriptions",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_UPDATE_SUBSCRIPTION:{method:"PUT",path:"/payments/subscriptions/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_CANCEL_SUBSCRIPTION:{method:"POST",path:"/payments/subscriptions/:id/cancel",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_LIST_SUBSCRIPTIONS:{method:"GET",path:"/payments/subscriptions",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_GET_SUBSCRIPTION:{method:"GET",path:"/payments/subscriptions/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_REPORT_USAGE:{method:"POST",path:"/payments/usage-records",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_LIST_USAGE_SUMMARIES:{method:"GET",path:"/payments/usage-records/:subscriptionItemId/summaries",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_CREATE_INVOICE:{method:"POST",path:"/payments/invoices",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_FINALIZE_INVOICE:{method:"POST",path:"/payments/invoices/:id/finalize",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_SEND_INVOICE:{method:"POST",path:"/payments/invoices/:id/send",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_VOID_INVOICE:{method:"POST",path:"/payments/invoices/:id/void",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_PAY_INVOICE:{method:"POST",path:"/payments/invoices/:id/pay",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_LIST_INVOICES:{method:"GET",path:"/payments/invoices",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_GET_INVOICE:{method:"GET",path:"/payments/invoices/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_GET_BALANCE:{method:"GET",path:"/payments/balance",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_CREATE_PAYOUT:{method:"POST",path:"/payments/payouts",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_LIST_PAYOUTS:{method:"GET",path:"/payments/payouts",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_GET_PAYOUT:{method:"GET",path:"/payments/payouts/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_CANCEL_PAYOUT:{method:"POST",path:"/payments/payouts/:id/cancel",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_CREATE_TRANSFER:{method:"POST",path:"/payments/transfers",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_LIST_TRANSFERS:{method:"GET",path:"/payments/transfers",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0}},TENANT_ENDPOINTS={TENANT_CHECK_SUBDOMAIN:{method:"GET",path:"/tenants/check-subdomain/:subdomain",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},TENANT_PROVISION:{method:"POST",path:"/tenants/provision",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},TENANT_LIST:{method:"GET",path:"/tenants",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},TENANT_DETAIL:{method:"GET",path:"/tenants/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},TENANT_SUSPEND:{method:"POST",path:"/tenants/:id/suspend",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},TENANT_REACTIVATE:{method:"POST",path:"/tenants/:id/reactivate",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},TENANT_SELF_SIGNUP:{method:"POST",path:"/tenants/self-signup",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0}},DOMAIN_ENDPOINTS={DOMAIN_RESOLVE:{method:"GET",path:"/domains/resolve",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},DOMAIN_CREATE_HOSTNAME:{method:"POST",path:"/domains/hostnames",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},DOMAIN_LIST_HOSTNAMES:{method:"GET",path:"/domains/hostnames",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},DOMAIN_GET_HOSTNAME:{method:"GET",path:"/domains/hostnames/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},DOMAIN_HOSTNAME_INSTRUCTIONS:{method:"GET",path:"/domains/hostnames/:id/instructions",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},DOMAIN_VERIFY_HOSTNAME:{method:"POST",path:"/domains/hostnames/:id/verify",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},DOMAIN_ACTIVATE_HOSTNAME:{method:"POST",path:"/domains/hostnames/:id/activate",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},DOMAIN_DISABLE_HOSTNAME:{method:"POST",path:"/domains/hostnames/:id/disable",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},DOMAIN_MAKE_PRIMARY:{method:"POST",path:"/domains/hostnames/:id/make-primary",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},DOMAIN_REFRESH_HOSTNAME:{method:"POST",path:"/domains/hostnames/:id/refresh-status",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},DOMAIN_CREATE_REGISTRATION:{method:"POST",path:"/domains/registrations",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},DOMAIN_LIST_REGISTRATIONS:{method:"GET",path:"/domains/registrations",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},DOMAIN_GET_REGISTRATION:{method:"GET",path:"/domains/registrations/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},DOMAIN_CANCEL_REGISTRATION:{method:"POST",path:"/domains/registrations/:id/cancel",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},DOMAIN_TRANSFER_OUT:{method:"POST",path:"/domains/registrations/:id/transfer-out",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0}},MARKETPLACE_ENDPOINTS={PAYMENT_MARKETPLACE_RECORD_SPLIT:{method:"POST",path:"/payment/marketplace/splits",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_MARKETPLACE_LIST_SPLITS:{method:"GET",path:"/payment/marketplace/splits",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_MARKETPLACE_BALANCE:{method:"GET",path:"/payment/marketplace/balance/:ownerId",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_MARKETPLACE_RELEASE_RESERVE:{method:"POST",path:"/payment/marketplace/reserves/:id/release",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_MARKETPLACE_GET_SETTLEMENT_POLICY:{method:"GET",path:"/payment/marketplace/settlement-policy",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_MARKETPLACE_UPSERT_SETTLEMENT_POLICY:{method:"POST",path:"/payment/marketplace/settlement-policy",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_MARKETPLACE_REQUEST_PAYOUT:{method:"POST",path:"/payment/marketplace/payout-requests",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_MARKETPLACE_LIST_PAYOUTS:{method:"GET",path:"/payment/marketplace/payout-requests",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_MARKETPLACE_GET_PAYOUT:{method:"GET",path:"/payment/marketplace/payout-requests/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_MARKETPLACE_APPROVE_PAYOUT:{method:"POST",path:"/payment/marketplace/payout-requests/:id/approve",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_MARKETPLACE_REJECT_PAYOUT:{method:"POST",path:"/payment/marketplace/payout-requests/:id/reject",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_MARKETPLACE_OPEN_DISPUTE:{method:"POST",path:"/payment/marketplace/disputes",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_MARKETPLACE_LIST_DISPUTES:{method:"GET",path:"/payment/marketplace/disputes",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_MARKETPLACE_RESOLVE_DISPUTE:{method:"POST",path:"/payment/marketplace/disputes/:id/resolve",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0}},COHORT_ENDPOINTS={ADMIN_LIST_COHORTS:{method:"GET",path:"/auth/admin/cohorts",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},ADMIN_GET_COHORT:{method:"GET",path:"/auth/admin/cohorts/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},ADMIN_CREATE_COHORT:{method:"POST",path:"/auth/admin/cohorts",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},ADMIN_UPDATE_COHORT:{method:"PATCH",path:"/auth/admin/cohorts/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},ADMIN_DELETE_COHORT:{method:"DELETE",path:"/auth/admin/cohorts/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},ADMIN_COHORT_BULK_CREATE:{method:"POST",path:"/auth/admin/cohorts/:id/bulk-create",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},ADMIN_COHORT_DEACTIVATE:{method:"POST",path:"/auth/admin/cohorts/:id/deactivate-users",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},ADMIN_COHORT_ACTIVATE:{method:"POST",path:"/auth/admin/cohorts/:id/activate-users",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},ADMIN_COHORT_DELETE_USERS:{method:"POST",path:"/auth/admin/cohorts/:id/delete-users",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},ADMIN_COHORT_EXPORT:{method:"GET",path:"/auth/admin/cohorts/:id/export",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0}};var SYSTEM_TABLE_NAMES=["profiles","addresses","phones","files","users","roles","claims","user_roles","role_claims","audit_logs","monitoring_metrics","integration_sources","integration_endpoints","integration_mappings","integration_runs","integration_run_items"],systemTables=system_tables_default.tables.filter((t)=>SYSTEM_TABLE_NAMES.includes(t.table_name));function toUpperSnakeCase(str){return str.replace(/([a-z])([A-Z])/g,"$1_$2").replace(/[\s-]+/g,"_").toUpperCase()}function snakeToCamelCase(str){return str.replace(/_([a-z])/g,(_,letter)=>letter.toUpperCase())}function singularize(str){if(str.endsWith("ies"))return`${str.slice(0,-3)}y`;if(str.endsWith("ses"))return`${str.slice(0,-2)}`;if(str.endsWith("s"))return str.slice(0,-1);return str}function generateEntityEndpointKey(tableName,method){let upperName=toUpperSnakeCase(tableName),singularName=toUpperSnakeCase(singularize(tableName));switch(method){case"GET":return`GET_${upperName}`;case"POST":return`ADD_${singularName}`;case"PUT":return`UPDATE_${singularName}`;case"PATCH":return`PATCH_${singularName}`;case"DELETE":return`DELETE_${singularName}`}}function generateBulkEndpointKey(tableName,method){let upperName=toUpperSnakeCase(tableName);switch(method){case"POST":return`BULK_ADD_${upperName}`;case"PUT":return`BULK_UPDATE_${upperName}`;case"DELETE":return`BULK_DELETE_${upperName}`}}function isMethodExcluded(table,method){if(!table.excluded_methods)return!1;let methodMap={GET:"GET",POST:"POST",PUT:"PUT",PATCH:"PATCH",DELETE:"DELETE"};return table.excluded_methods.includes(methodMap[method])}function generateEndpointsFromConfig(config){let endpoints={};for(let table of config.entities){let tableName=table.table_name,basePath=`/${snakeToCamelCase(tableName)}`,sid=table.serviceId;if(!isMethodExcluded(table,"GET")){endpoints[generateEntityEndpointKey(tableName,"GET")]={method:"GET",path:basePath,isPublic:table.is_public?.GET??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0};let singularName=toUpperSnakeCase(singularize(tableName));endpoints[`GET_${singularName}_BY_ID`]={method:"GET",path:`${basePath}/:id`,isPublic:table.is_public?.GET??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0},endpoints[`GET_${toUpperSnakeCase(tableName)}_DISTINCT`]={method:"GET",path:`${basePath}/distinct/:field`,isPublic:table.is_public?.GET??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0}}if(!isMethodExcluded(table,"POST"))endpoints[generateEntityEndpointKey(tableName,"POST")]={method:"POST",path:basePath,isPublic:table.is_public?.POST??!1,isFormData:table.is_form_data,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0};if(!isMethodExcluded(table,"PUT"))endpoints[generateEntityEndpointKey(tableName,"PUT")]={method:"PUT",path:`${basePath}/:id`,isPublic:table.is_public?.PUT??!1,isFormData:table.is_form_data,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0};if(!isMethodExcluded(table,"PATCH"))endpoints[generateEntityEndpointKey(tableName,"PATCH")]={method:"PATCH",path:`${basePath}/:id`,isPublic:table.is_public?.PATCH??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0};if(!isMethodExcluded(table,"DELETE"))endpoints[generateEntityEndpointKey(tableName,"DELETE")]={method:"DELETE",path:`${basePath}/:id`,isPublic:table.is_public?.DELETE??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0};if(table.bulk_endpoints_enabled){if(!isMethodExcluded(table,"POST"))endpoints[generateBulkEndpointKey(tableName,"POST")]={method:"POST",path:`${basePath}/bulk`,isPublic:table.is_public?.POST??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0};if(!isMethodExcluded(table,"PUT"))endpoints[generateBulkEndpointKey(tableName,"PUT")]={method:"PUT",path:`${basePath}/bulk`,isPublic:table.is_public?.PUT??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0};if(!isMethodExcluded(table,"DELETE"))endpoints[generateBulkEndpointKey(tableName,"DELETE")]={method:"DELETE",path:`${basePath}/bulk`,isPublic:table.is_public?.DELETE??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0}}}return endpoints}function generateAuthEndpoints(config){let endpoints={},auth=config.authentication;if(!auth?.enabled)return endpoints;for(let[featureKey,endpointConfig]of Object.entries(AUTH_ENDPOINT_CONFIGS)){let feature=auth[featureKey];if(!feature?.enabled)continue;let feat=feature,baseRoute=feat.route||endpointConfig.defaultRoute,isPublic=feat.isPublic??endpointConfig.defaultIsPublic;if("subEndpoints"in endpointConfig&&endpointConfig.subEndpoints)for(let sub of endpointConfig.subEndpoints){let subRoute="routeKey"in sub&&sub.routeKey&&feature[sub.routeKey]?String(feature[sub.routeKey]):("defaultRoute"in sub)&&sub.defaultRoute?String(sub.defaultRoute):`${baseRoute}${sub.suffix}`;endpoints[sub.key]={method:sub.method,path:subRoute,isPublic:sub.key==="MAGIC_LINK_VERIFY"?!0:isPublic,_payload:sub._payload,_success:sub._success,_error:sub._error}}else if("_payload"in endpointConfig)endpoints[endpointConfig.key]={method:endpointConfig.method,path:baseRoute,isPublic,_payload:endpointConfig._payload,_success:endpointConfig._success,_error:endpointConfig._error}}return endpoints}function generateSystemTableEndpoints(){let endpoints={};for(let table of systemTables){let tableName=table.table_name,basePath=`/${snakeToCamelCase(tableName)}`,isFormData=tableName==="files";endpoints[generateEntityEndpointKey(tableName,"GET")]={method:"GET",path:basePath,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0};let singularName=toUpperSnakeCase(singularize(tableName));if(endpoints[`GET_${singularName}_BY_ID`]={method:"GET",path:`${basePath}/:id`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},!isMethodExcluded(table,"POST"))endpoints[generateEntityEndpointKey(tableName,"POST")]={method:"POST",path:basePath,isPublic:!1,isFormData,_payload:void 0,_success:void 0,_error:void 0};if(!isMethodExcluded(table,"PUT"))endpoints[generateEntityEndpointKey(tableName,"PUT")]={method:"PUT",path:`${basePath}/:id`,isPublic:!1,isFormData,_payload:void 0,_success:void 0,_error:void 0};if(!isMethodExcluded(table,"PATCH"))endpoints[generateEntityEndpointKey(tableName,"PATCH")]={method:"PATCH",path:`${basePath}/:id`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0};if(!isMethodExcluded(table,"DELETE"))endpoints[generateEntityEndpointKey(tableName,"DELETE")]={method:"DELETE",path:`${basePath}/:id`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0};if(table.bulk_endpoints_enabled)endpoints[generateBulkEndpointKey(tableName,"POST")]={method:"POST",path:`${basePath}/bulk`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints[generateBulkEndpointKey(tableName,"PUT")]={method:"PUT",path:`${basePath}/bulk`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints[generateBulkEndpointKey(tableName,"DELETE")]={method:"DELETE",path:`${basePath}/bulk`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0}}return endpoints}function generateMonitoringEndpoints(config){if(!config.liveMonitoring?.enabled)return{};return{...MONITORING_ENDPOINTS}}function generateAdminEndpoints(config){let endpoints={};if(!config.authentication?.enabled)return endpoints;return endpoints.ADMIN_IMPERSONATE={method:"POST",path:"/auth/admin/impersonate",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.ADMIN_IMPERSONATE_STOP={method:"POST",path:"/auth/admin/impersonate/stop",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.ADMIN_CHANGE_USER_ID={method:"POST",path:"/auth/admin/change-user-id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.ADMIN_CREATE_USER={method:"POST",path:"/auth/admin/create-user",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.ADMIN_HARD_DELETE_USER={method:"DELETE",path:"/auth/admin/hard-delete/:userId",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints}function generateCohortEndpoints(config){let auth=config.authentication;if(!auth?.enabled||!auth.cohorts?.enabled)return{};return{...COHORT_ENDPOINTS}}function generateVerificationEndpoints(config){let endpoints={},verification=config.verification,notification=config.notification;if(!verification?.enabled)return endpoints;let basePath=verification.endpoints?.basePath||"/verifications",flowBasePath=verification.flowEndpoints?.basePath||"/verification-flows",notifBasePath=notification?.endpoints?.basePath||"/notifications";if(endpoints.VERIFICATION_STATUS={method:"GET",path:`${basePath}/status/:entity_name/:entity_id`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.VERIFICATION_DECIDE={method:"POST",path:`${basePath}/:entity_name/:entity_id/decide`,isPublic:!1,skipCamelCase:!0,_payload:void 0,_success:void 0,_error:void 0},endpoints.VERIFICATION_PENDING={method:"GET",path:`${basePath}/pending`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.VERIFICATION_HISTORY={method:"GET",path:`${basePath}/history/:entity_name/:entity_id`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.VERIFICATION_START={method:"POST",path:`${basePath}/start`,isPublic:!1,skipCamelCase:!0,_payload:void 0,_success:void 0,_error:void 0},endpoints.VERIFICATION_START_FOR_ENTITY={method:"POST",path:`${basePath}/start-for-entity`,isPublic:!1,skipCamelCase:!0,_payload:void 0,_success:void 0,_error:void 0},endpoints.VERIFICATION_ENTITY_STATUSES={method:"GET",path:`${basePath}/statuses/:entity_name`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},verification.flowEndpoints?.enabled)endpoints.FLOW_LIST={method:"GET",path:flowBasePath,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.FLOW_GET={method:"GET",path:`${flowBasePath}/:flow_id`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.FLOW_SAVE={method:"POST",path:flowBasePath,isPublic:!1,skipCamelCase:!0,_payload:void 0,_success:void 0,_error:void 0},endpoints.FLOW_PUBLISH={method:"POST",path:`${flowBasePath}/:flow_id/publish`,isPublic:!1,skipCamelCase:!0,_payload:void 0,_success:void 0,_error:void 0},endpoints.FLOW_DELETE={method:"DELETE",path:`${flowBasePath}/:flow_id`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0};if(notification?.enabled&¬ification.endpoints?.enabled)endpoints.NOTIFICATION_LIST={method:"GET",path:notifBasePath,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.NOTIFICATION_UNSEEN_COUNT={method:"GET",path:`${notifBasePath}/unseen-count`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.NOTIFICATION_MARK_SEEN={method:"POST",path:`${notifBasePath}/:notification_id/seen`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.NOTIFICATION_MARK_ALL_SEEN={method:"POST",path:`${notifBasePath}/seen-all`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0};return endpoints}function generateTenantEndpoints(config){if(!config.database?.isMultiTenant)return{};return{...TENANT_ENDPOINTS}}function generateChatEndpoints(config){if(!config.chat?.enabled)return{};return{...CHAT_ENDPOINTS}}function generateDomainEndpoints(config){if(!config.domains?.enabled)return{};return{...DOMAIN_ENDPOINTS}}function generateMarketplaceEndpoints(config){let payment=config.payment;if(!payment?.enabled||!payment.marketplace?.enabled)return{};return{...MARKETPLACE_ENDPOINTS}}function generateAllEndpoints(config,extraEndpoints){let entityEndpoints=generateEndpointsFromConfig(config),authEndpoints=generateAuthEndpoints(config),adminEndpoints=generateAdminEndpoints(config),cohortEndpoints=generateCohortEndpoints(config),systemEndpoints=generateSystemTableEndpoints(),monitoringEndpoints=generateMonitoringEndpoints(config),verificationEndpoints=generateVerificationEndpoints(config),chatEndpoints=generateChatEndpoints(config),tenantEndpoints=generateTenantEndpoints(config),domainEndpoints=generateDomainEndpoints(config),marketplaceEndpoints=generateMarketplaceEndpoints(config);return{...entityEndpoints,...authEndpoints,...adminEndpoints,...cohortEndpoints,...systemEndpoints,...monitoringEndpoints,...verificationEndpoints,...chatEndpoints,...tenantEndpoints,...domainEndpoints,...marketplaceEndpoints,...extraEndpoints??{}}}init_Logger();var DEFAULT_CONFIG2={timeout:30000,retries:0,retryDelay:1000,debug:!1};class ServerFetch{config;logger;constructor(config={}){this.config={...DEFAULT_CONFIG2,...config},this.logger=new Logger({service:"ServerFetch",prettyPrint:this.config.debug,colorize:this.config.debug,auditEnabled:!1})}buildUrl(url){if(url.startsWith("http://")||url.startsWith("https://"))return url;return this.config.baseUrl?`${this.config.baseUrl}${url}`:url}buildHeaders(customHeaders){let headers=new Headers;if(this.config.defaultHeaders)for(let[key,value]of Object.entries(this.config.defaultHeaders))headers.set(key,value);if(customHeaders)if(customHeaders instanceof Headers)customHeaders.forEach((value,key)=>{headers.set(key,value)});else if(Array.isArray(customHeaders))for(let[key,value]of customHeaders)headers.set(key,value);else for(let[key,value]of Object.entries(customHeaders))headers.set(key,value);return headers}parseResponseHeaders(headers){let result={};if(headers.forEach((value,key)=>{if(key.toLowerCase()==="set-cookie"){let existing=result[key];result[key]=existing?`${existing}, ${value}`:value}else result[key]=value}),typeof headers.getSetCookie==="function"){let setCookies=headers.getSetCookie();if(setCookies.length>0)result["set-cookie"]=setCookies.join(", ")}return result}async executeWithTimeout(promise,timeoutMs,_requestId){let controller=new AbortController,timeoutId=setTimeout(()=>controller.abort(),timeoutMs);try{return await Promise.race([promise,new Promise((_,reject)=>{controller.signal.addEventListener("abort",()=>{reject(Error(`Request timeout after ${timeoutMs}ms`))})})])}finally{clearTimeout(timeoutId)}}async fetch(options){let requestId=randomId(),startTime=performance.now(),url=this.buildUrl(options.url),headers=this.buildHeaders(options.headers),timeout=options.timeout??this.config.timeout??30000,retries=options.retries??this.config.retries??0,retryDelay=options.retryDelay??this.config.retryDelay??1000,body;if(options.body)if(typeof options.body==="object"&&!(options.body instanceof FormData)&&!(options.body instanceof URLSearchParams)&&!(options.body instanceof Blob)&&!(options.body instanceof ArrayBuffer)){if(body=JSON.stringify(options.body),!headers.has("content-type"))headers.set("content-type","application/json")}else body=options.body;this.logger.debug(`[${requestId}] ${options.method} ${url}`,{method:options.method,url,hasBody:!!body});let lastError=null,attempt=0;while(attempt<=retries)try{let response=await this.executeWithTimeout(fetch(url,{method:options.method,headers,body}),timeout,requestId),durationMs2=performance.now()-startTime,responseHeaders=this.parseResponseHeaders(response.headers),rawSetCookies=typeof response.headers.getSetCookie==="function"?response.headers.getSetCookie():[],responseData,errorData,rawText=await response.text();if(rawText)try{let json=JSON.parse(rawText);if(response.ok)responseData=json;else errorData=json}catch{if(!response.ok)errorData={message:rawText||response.statusText}}else if(!response.ok)errorData={message:response.statusText};let result={isSuccess:response.ok,response:responseData,errors:errorData,code:response.status,headers:responseHeaders,rawSetCookies,durationMs:durationMs2,requestId,createdAt:new Date};if(response.ok)this.logger.info(`[${requestId}] ${options.method} ${url} ${response.status}`,{method:options.method,url,statusCode:response.status,durationMs:Math.round(durationMs2)});else this.logger.warn(`[${requestId}] ${options.method} ${url} ${response.status}`,{method:options.method,url,statusCode:response.status,durationMs:Math.round(durationMs2),error:errorData});return result}catch(error){if(lastError=error instanceof Error?error:Error(String(error)),attempt++,attempt<=retries)this.logger.warn(`[${requestId}] Retry ${attempt}/${retries} after error`,{method:options.method,url,error:lastError.message,attempt,retries}),await new Promise((resolve)=>setTimeout(resolve,retryDelay))}let durationMs=performance.now()-startTime;return this.logger.error(`[${requestId}] ${options.method} ${url} failed`,lastError,{method:options.method,url,durationMs:Math.round(durationMs),attempts:attempt}),{isSuccess:!1,response:void 0,errors:{message:lastError?.message||"Unknown error"},code:null,headers:{},rawSetCookies:[],durationMs,requestId,createdAt:new Date}}async get(url,options){return this.fetch({...options,url,method:"GET"})}async post(url,body,options){return this.fetch({...options,url,method:"POST",body})}async put(url,body,options){return this.fetch({...options,url,method:"PUT",body})}async patch(url,body,options){return this.fetch({...options,url,method:"PATCH",body})}async delete(url,options){return this.fetch({...options,url,method:"DELETE"})}}var serverFetch=new ServerFetch;var DEFAULT_TOKEN_NAMES={accessToken:"access_token",refreshToken:"refresh_token",sessionToken:"session_token"};function splitSetCookieHeader(header){let cookies=[],current="";for(let i=0;i<header.length;i++){let char=header[i];if(char===","){let next=header.slice(i+1).trimStart();if(/^[a-zA-Z0-9_-]+=/.test(next)){cookies.push(current.trim()),current="";continue}}current+=char}if(current.trim())cookies.push(current.trim());return cookies}function buildRequestHeaders(headersStore,tokenNames){let headers={},forwardHeaders=["x-forwarded-for","x-real-ip","user-agent","accept-language","x-request-id","x-client-ip","cf-connecting-ip","true-client-ip","x-tenant-id","x-app-origin"];for(let header of forwardHeaders){let value=headersStore.get(header);if(value)headers[header]=value}if(!headers["user-agent"])headers["user-agent"]="Nucleus-ServerAction/1.0";let accessToken=headersStore.get(`x-${tokenNames.accessToken}`),refreshToken=headersStore.get(`x-${tokenNames.refreshToken}`),sessionToken=headersStore.get(`x-${tokenNames.sessionToken}`);if(accessToken)headers[`x-${tokenNames.accessToken}`]=accessToken;if(refreshToken)headers[`x-${tokenNames.refreshToken}`]=refreshToken;if(sessionToken)headers[`x-${tokenNames.sessionToken}`]=sessionToken;let cookieHeader=headersStore.get("cookie");if(cookieHeader)headers.cookie=cookieHeader;return headers}function toCamelCase(str){return str.replace(/_([a-z])/g,(_,c)=>c.toUpperCase())}function convertKeysToCamelCase(obj){let result={};for(let[key,value]of Object.entries(obj)){let camelKey=key.startsWith("_")?key:toCamelCase(key);if(value instanceof Date)result[camelKey]=value.toISOString();else if(value&&typeof value==="object"&&!Array.isArray(value))result[camelKey]=convertKeysToCamelCase(value);else result[camelKey]=value}return result}var JSON_STRINGIFY_KEYS=new Set(["filters","sort","with","searchFields","select","distinctOn"]);function appendQueryParams(url,params){let searchParams=new URLSearchParams;for(let[key,value]of Object.entries(params)){if(value===void 0||value===null)continue;if(JSON_STRINGIFY_KEYS.has(key)&&typeof value==="object"){searchParams.append(key,JSON.stringify(value));continue}if(value instanceof Date)searchParams.append(key,value.toISOString());else if(Array.isArray(value))searchParams.append(key,value.filter((v)=>v!=null).map(String).join(","));else if(typeof value==="object")searchParams.append(key,JSON.stringify(value));else searchParams.append(key,String(value))}let queryString=searchParams.toString();if(!queryString)return url;return url.includes("?")?`${url}&${queryString}`:`${url}?${queryString}`}function createServerFactory(endpoints,config,getCookies,getHeaders){let tokenNames={...DEFAULT_TOKEN_NAMES,...config.tokenNames},serverFetch2=new ServerFetch({baseUrl:config.baseUrl,debug:config.debug,timeout:30000,retries:0});return async function(endpointKey,payload){let endpoint=endpoints[endpointKey];if(!endpoint)return{isSuccess:!1,errors:{message:`Endpoint "${endpointKey}" not found`},code:404};let cookieStore=await getCookies(),headersStore=await getHeaders(),allHeaders={};if(headersStore.forEach((value,key)=>{allHeaders[key]=value}),(endpoint.path.includes("/auth/login")||endpoint.path.includes("/auth/oauth"))&&endpoint.method==="POST")try{cookieStore.delete(tokenNames.accessToken),cookieStore.delete(tokenNames.refreshToken),cookieStore.delete(tokenNames.sessionToken)}catch(_){}let headers=buildRequestHeaders(headersStore,tokenNames),url=endpoint.path,body,pathParamNames=new Set,pathParamRegex=/:([a-zA-Z_][a-zA-Z0-9_]*)/g,paramMatch=pathParamRegex.exec(url);while(paramMatch!==null){if(paramMatch[1])pathParamNames.add(paramMatch[1]);paramMatch=pathParamRegex.exec(url)}if(payload&&typeof payload==="object"&&!(payload instanceof FormData)){let payloadObj=payload;for(let[key,value]of Object.entries(payloadObj))if(value!=null){if(pathParamNames.has(key))url=url.replace(`:${key}`,String(value));else if(key.startsWith("_")&&pathParamNames.has(key.substring(1)))url=url.replace(`:${key.substring(1)}`,String(value));else if(key==="id"&&pathParamNames.has("id"))url=url.replace(":id",String(value))}}if(endpoint.method==="GET"&&payload&&typeof payload==="object"){let queryPayload={...payload};for(let paramName of pathParamNames)delete queryPayload[paramName],delete queryPayload[`_${paramName}`];url=appendQueryParams(url,queryPayload)}else if(payload!==void 0){if(endpoint.isFormData&&payload instanceof FormData)body=payload;else if(Array.isArray(payload)){if(body=payload.map((item)=>item&&typeof item==="object"?convertKeysToCamelCase(item):item),!headers["content-type"])headers["content-type"]="application/json"}else if(body=endpoint.skipCamelCase?payload:convertKeysToCamelCase(payload),!headers["content-type"])headers["content-type"]="application/json"}let response=await serverFetch2.fetch({url,method:endpoint.method,headers,body}),setCookiesToProcess=response.rawSetCookies.length>0?response.rawSetCookies:response.headers["set-cookie"]?splitSetCookieHeader(response.headers["set-cookie"]):[];if(setCookiesToProcess.length>0)try{for(let cookie of setCookiesToProcess){let[nameValue,...options]=cookie.split(";");if(!nameValue)continue;let eqIdx=nameValue.indexOf("=");if(eqIdx===-1)continue;let name=nameValue.substring(0,eqIdx).trim(),value=nameValue.substring(eqIdx+1).trim();if(name&&value){let cookieOptions={};for(let opt of options){let trimmed=opt.trim(),optEqIdx=trimmed.indexOf("="),optName=optEqIdx===-1?trimmed:trimmed.substring(0,optEqIdx),optValue=optEqIdx===-1?void 0:trimmed.substring(optEqIdx+1);if(!optName)continue;let optNameLower=optName.toLowerCase();if(optNameLower==="path")cookieOptions.path=optValue;else if(optNameLower==="domain")cookieOptions.domain=optValue;else if(optNameLower==="max-age")cookieOptions.maxAge=Number(optValue);else if(optNameLower==="expires"&&optValue)cookieOptions.expires=new Date(optValue);else if(optNameLower==="httponly")cookieOptions.httpOnly=!0;else if(optNameLower==="secure")cookieOptions.secure=!0;else if(optNameLower==="samesite")cookieOptions.sameSite=optValue}cookieStore.set(name,value,cookieOptions)}}}catch(cookieError){console.warn("[ServerFactory] Failed to process Set-Cookie headers:",cookieError instanceof Error?cookieError.message:String(cookieError))}let normalizedResponse=response.response;if(response.isSuccess&&normalizedResponse&&typeof normalizedResponse==="object"&&!Array.isArray(normalizedResponse)){let raw=normalizedResponse;if("success"in raw&&!("data"in raw)){let{success,message,error,...rest}=raw;normalizedResponse={success,...message!==void 0?{message}:{},...error!==void 0?{error}:{},...Object.keys(rest).length>0?{data:rest}:{}}}}return{isSuccess:response.isSuccess,data:normalizedResponse,errors:response.errors,code:response.code,message:response.isSuccess?void 0:response.errors?.message}}}var SYSTEM_TABLES=[{table_name:"users",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"email",type:"varchar",length:255},{name:"password",type:"varchar",length:255},{name:"verified_at",type:"timestamp"},{name:"email_verification_token",type:"varchar",length:255},{name:"email_verification_token_expires_at",type:"timestamp"},{name:"email_verification_sent_at",type:"timestamp"},{name:"email_verification_attempts",type:"integer",default:0},{name:"last_login_at",type:"timestamp"},{name:"login_count",type:"integer",default:0},{name:"is_locked",type:"boolean",default:!1},{name:"locked_until",type:"timestamp"},{name:"failed_login_attempts",type:"integer",default:0},{name:"is_god",type:"boolean",default:!1},{name:"cohort_id",type:"uuid",references:{table:"user_cohorts",column:"id",onDelete:"set null"}},{name:"email_verified",type:"boolean",default:!1}],indexes:[{columns:["email"],unique:!0},{columns:["email","is_active"]},{columns:["last_login_at"]},{columns:["is_locked","locked_until"]}]},{table_name:"profiles",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id"}},{name:"first_name",type:"varchar",length:100,notNull:!0},{name:"last_name",type:"varchar",length:100,notNull:!0}],indexes:[{columns:["user_id"],unique:!0},{columns:["first_name","last_name"]}]},{table_name:"roles",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"name",type:"varchar",length:100,notNull:!0},{name:"description",type:"varchar",length:500}],indexes:[{columns:["name"],unique:!0}]},{table_name:"claims",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"action",type:"varchar",length:100,notNull:!0},{name:"description",type:"varchar",length:500},{name:"path",type:"varchar",length:200,notNull:!0},{name:"method",type:"varchar",length:10,notNull:!0},{name:"policy",type:"jsonb"}],indexes:[{columns:["action"],unique:!0},{columns:["path","method"]}]},{table_name:"user_roles",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"role_id",type:"uuid",notNull:!0,references:{table:"roles",column:"id",onDelete:"cascade"}}],indexes:[{columns:["user_id"]},{columns:["role_id"]}],constraints:{unique:[{name:"unique_user_role",columns:["user_id","role_id"]}]}},{table_name:"role_claims",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"role_id",type:"uuid",notNull:!0,references:{table:"roles",column:"id",onDelete:"cascade"}},{name:"claim_id",type:"uuid",notNull:!0,references:{table:"claims",column:"id",onDelete:"cascade"}},{name:"scope",type:"text"}],indexes:[{columns:["role_id"]},{columns:["claim_id"]},{columns:["role_id","claim_id","scope"]}]},{table_name:"files",feature_set:["storage"],add_base_columns:!0,is_form_data:!0,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"name",type:"varchar",length:255,notNull:!0},{name:"original_name",type:"varchar",length:255,notNull:!0},{name:"type",type:"varchar",length:50,enumValues:["image","document","video","audio","profile_picture"]},{name:"path",type:"varchar",length:500,notNull:!0},{name:"size",type:"bigint",mode:"number",notNull:!0},{name:"mime_type",type:"varchar",length:100,notNull:!0},{name:"extension",type:"varchar",length:10,notNull:!0},{name:"uploaded_by",type:"uuid",references:{table:"users",column:"id"}}],indexes:[{columns:["type"]},{columns:["uploaded_by"]},{columns:["size"]}]},{table_name:"addresses",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"owner_type",type:"varchar",length:50,notNull:!0,enumValues:["user","company","contact"]},{name:"owner_id",type:"uuid",notNull:!0},{name:"name",type:"varchar",length:100,notNull:!0},{name:"street",type:"varchar",length:255},{name:"city",type:"varchar",length:100},{name:"state",type:"varchar",length:50},{name:"zip",type:"varchar",length:20},{name:"country",type:"varchar",length:50,default:"US"},{name:"latitude",type:"decimal",precision:10,scale:8},{name:"longitude",type:"decimal",precision:11,scale:8},{name:"neighborhood",type:"varchar",length:100},{name:"apartment",type:"varchar",length:50},{name:"province",type:"varchar",length:100},{name:"district",type:"varchar",length:100},{name:"type",type:"varchar",length:50}],indexes:[{columns:["city","state"]},{columns:["latitude","longitude"]},{columns:["type"]},{columns:["owner_type","owner_id"]}]},{table_name:"phones",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"owner_type",type:"varchar",length:50,notNull:!0,enumValues:["user","company","contact"]},{name:"owner_id",type:"uuid",notNull:!0},{name:"name",type:"varchar",length:100,notNull:!0},{name:"type",type:"varchar",length:50,enumValues:["mobile","office","fax"]},{name:"number",type:"varchar",length:20,notNull:!0},{name:"country_code",type:"varchar",length:10,notNull:!0,default:"+1"},{name:"extension",type:"varchar",length:10}],indexes:[{columns:["number"]},{columns:["type"]},{columns:["owner_type","owner_id"]}]},{table_name:"notifications",feature_set:["notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",notNull:!0},{name:"title",type:"varchar",length:255,notNull:!0},{name:"body",type:"varchar",length:1000},{name:"entity_name",type:"varchar",length:100},{name:"entity_id",type:"uuid"},{name:"type",type:"varchar",length:50,notNull:!0,default:"system",enumValues:["verification","system","custom"]},{name:"source",type:"varchar",length:100},{name:"is_seen",type:"boolean",notNull:!0,default:!1},{name:"seen_at",type:"timestamptz"}],indexes:[{columns:["user_id","created_at"]},{columns:["is_seen"]},{columns:["type"]},{columns:["user_id","type","is_seen"]}]},{table_name:"tenants",feature_set:["multi-tenant"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:[],columns:[{name:"subdomain",type:"varchar",length:100,notNull:!0,unique:!0},{name:"schema_name",type:"varchar",length:100,notNull:!0,unique:!0},{name:"company_id",type:"uuid",notNull:!0},{name:"company_name",type:"varchar",length:255},{name:"god_admin_email",type:"varchar",length:255,notNull:!0},{name:"status",type:"varchar",length:20,notNull:!0,default:"provisioning"},{name:"plan",type:"varchar",length:50,default:"free"},{name:"domain",type:"varchar",length:255},{name:"settings",type:"jsonb",default:"{}"},{name:"trusted_sources",type:"jsonb",default:"[]"},{name:"max_users",type:"integer"},{name:"provisioned_at",type:"timestamptz"},{name:"suspended_at",type:"timestamptz"},{name:"suspended_reason",type:"text"}],indexes:[{columns:["status"]}]},{table_name:"tenant_events",feature_set:["multi-tenant"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],columns:[{name:"tenant_id",type:"uuid",notNull:!0,references:{table:"tenants",column:"id",onDelete:"cascade"}},{name:"event_type",type:"varchar",length:50,notNull:!0},{name:"event_data",type:"jsonb",default:"{}"},{name:"performed_by",type:"varchar",length:255},{name:"ip_address",type:"varchar",length:45}],indexes:[{columns:["tenant_id"]},{columns:["event_type"]}]},{table_name:"tenant_features",feature_set:["multi-tenant"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:[],columns:[{name:"tenant_id",type:"uuid",notNull:!0,references:{table:"tenants",column:"id",onDelete:"cascade"}},{name:"feature_name",type:"varchar",length:100,notNull:!0},{name:"enabled",type:"boolean",notNull:!0,default:!0},{name:"config",type:"jsonb",default:"{}"}],indexes:[{columns:["tenant_id","feature_name"],unique:!0},{columns:["feature_name"]}]},{table_name:"domain_hostnames",feature_set:["domains"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:["PUT"],group_name:"Domains",columns:[{name:"owner_type",type:"varchar",length:20,notNull:!0,default:"tenant",comment:"tenant | organization | user | external"},{name:"owner_id",type:"uuid",notNull:!0,comment:"Product-defined owner reference (e.g. band id, org id)"},{name:"tenant_id",type:"uuid",references:{table:"tenants",column:"id",onDelete:"cascade"},comment:"Tenant this hostname routes to; null for non-tenant owners"},{name:"schema_name",type:"varchar",length:100,comment:"Resolved tenant schema for routing"},{name:"hostname",type:"varchar",length:255,notNull:!0,comment:"Original hostname as entered by the user"},{name:"normalized_hostname",type:"varchar",length:255,notNull:!0,unique:!0,comment:"Lowercased, punycode, port-stripped hostname used for matching"},{name:"hostname_kind",type:"varchar",length:20,notNull:!0,default:"apex",comment:"platform_subdomain | apex | www | subdomain"},{name:"status",type:"varchar",length:20,notNull:!0,default:"pending_verification",comment:"draft | pending_verification | verifying | active | failed | disabled | archived"},{name:"routing_status",type:"varchar",length:20,notNull:!0,default:"inactive",comment:"inactive | pending | active | failed"},{name:"certificate_status",type:"varchar",length:20,notNull:!0,default:"pending",comment:"not_required | pending | active | failed"},{name:"verification_status",type:"varchar",length:20,notNull:!0,default:"pending",comment:"pending | verified | failed | expired"},{name:"provider",type:"varchar",length:30,notNull:!0,default:"manual_dns",comment:"manual_dns | cloudflare_for_saas | cloudflare_registrar"},{name:"provider_hostname_id",type:"varchar",length:255},{name:"dns_target",type:"varchar",length:255,comment:"CNAME / A target the customer must point at"},{name:"is_primary",type:"boolean",notNull:!0,default:!1},{name:"redirect_to_hostname_id",type:"uuid",comment:"When set, this hostname 301-redirects to another hostname (e.g. apex to www)"},{name:"activated_at",type:"timestamptz"},{name:"disabled_at",type:"timestamptz"},{name:"failure_reason",type:"text"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["tenant_id"]},{columns:["schema_name"]},{columns:["status"]},{columns:["owner_type","owner_id"]},{columns:["provider","provider_hostname_id"]}]},{table_name:"domain_registrations",feature_set:["domains"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:["PUT"],group_name:"Domains",columns:[{name:"owner_type",type:"varchar",length:20,notNull:!0,default:"tenant"},{name:"owner_id",type:"uuid",notNull:!0},{name:"tenant_id",type:"uuid",references:{table:"tenants",column:"id",onDelete:"set null"}},{name:"requested_domain",type:"varchar",length:255,notNull:!0},{name:"registered_domain",type:"varchar",length:255},{name:"provider",type:"varchar",length:30,notNull:!0,default:"cloudflare_registrar"},{name:"provider_registration_id",type:"varchar",length:255},{name:"registrant_owner_type",type:"varchar",length:20,notNull:!0,default:"customer",comment:"customer | platform"},{name:"registrant_contact_snapshot",type:"jsonb",default:"{}"},{name:"status",type:"varchar",length:30,notNull:!0,default:"draft",comment:"draft | availability_checked | awaiting_payment | registering | active | failed | transfer_requested | transferred_out | cancelled | expired"},{name:"price_amount",type:"numeric",precision:12,scale:2},{name:"currency",type:"varchar",length:10},{name:"renewal_date",type:"timestamptz"},{name:"auto_renew",type:"boolean",notNull:!0,default:!0},{name:"terms_version",type:"varchar",length:50},{name:"terms_accepted_at",type:"timestamptz"},{name:"failure_reason",type:"text"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["owner_type","owner_id"]},{columns:["tenant_id"]},{columns:["status"]}]},{table_name:"domain_verification_challenges",feature_set:["domains"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],group_name:"Domains",columns:[{name:"domain_hostname_id",type:"uuid",notNull:!0,references:{table:"domainHostnames",column:"id",onDelete:"cascade"}},{name:"challenge_type",type:"varchar",length:30,notNull:!0,default:"ownership_validation",comment:"hostname_validation | certificate_validation | ownership_validation"},{name:"record_type",type:"varchar",length:10,notNull:!0,default:"TXT",comment:"TXT | CNAME | A | AAAA | HTTP"},{name:"record_name",type:"varchar",length:255,notNull:!0},{name:"record_value",type:"text",notNull:!0},{name:"expected_target",type:"varchar",length:255},{name:"status",type:"varchar",length:20,notNull:!0,default:"pending",comment:"pending | verified | failed | expired"},{name:"expires_at",type:"timestamptz"},{name:"verified_at",type:"timestamptz"},{name:"failure_reason",type:"text"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["domain_hostname_id"]},{columns:["status"]}]},{table_name:"domain_provider_records",feature_set:["domains"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],group_name:"Domains",columns:[{name:"domain_hostname_id",type:"uuid",notNull:!0,references:{table:"domainHostnames",column:"id",onDelete:"cascade"}},{name:"provider",type:"varchar",length:30,notNull:!0},{name:"provider_resource_type",type:"varchar",length:30,notNull:!0,comment:"custom_hostname | certificate | validation | zone | dns_record | registration"},{name:"provider_resource_id",type:"varchar",length:255},{name:"provider_status",type:"varchar",length:50},{name:"last_synced_at",type:"timestamptz"},{name:"raw_status",type:"jsonb",default:"{}"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["domain_hostname_id"]},{columns:["provider","provider_resource_id"]}]},{table_name:"domain_events",feature_set:["domains"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],group_name:"Domains",columns:[{name:"domain_hostname_id",type:"uuid",references:{table:"domainHostnames",column:"id",onDelete:"cascade"}},{name:"domain_registration_id",type:"uuid",references:{table:"domainRegistrations",column:"id",onDelete:"cascade"}},{name:"event_type",type:"varchar",length:50,notNull:!0},{name:"actor_type",type:"varchar",length:20},{name:"actor_id",type:"varchar",length:255},{name:"message",type:"text"},{name:"ip_address",type:"varchar",length:45},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["domain_hostname_id"]},{columns:["event_type"]}]},{table_name:"verifications",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"instance_id",type:"uuid",notNull:!0,references:{table:"verificationInstances",column:"id",onDelete:"cascade"}},{name:"requirement_id",type:"uuid",notNull:!0,references:{table:"verificationRequirements",column:"id"}},{name:"verifier_id",type:"uuid",notNull:!0,references:{table:"users",column:"id"}},{name:"signature_id",type:"uuid",references:{table:"files",column:"id"}},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"entity_id",type:"uuid",notNull:!0},{name:"step_order",type:"integer",notNull:!0,default:1},{name:"decision",type:"varchar",length:50,notNull:!0,default:"pending",enumValues:["approved","rejected","pending"]},{name:"reason",type:"text"},{name:"diff",type:"jsonb"}],indexes:[{columns:["instance_id"]},{columns:["requirement_id"]},{columns:["verifier_id"]},{columns:["entity_name","entity_id"]},{columns:["entity_name","entity_id","step_order"]},{columns:["decision"]}]},{table_name:"verificationRequirements",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"instance_id",type:"uuid",notNull:!0,references:{table:"verificationInstances",column:"id",onDelete:"cascade"}},{name:"step_node_id",type:"varchar",length:100,notNull:!0},{name:"verifier_node_id",type:"varchar",length:100,notNull:!0},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"entity_id",type:"uuid",notNull:!0},{name:"verifier_type",type:"varchar",length:30,notNull:!0,enumValues:["user","role"]},{name:"verifier_user_id",type:"uuid"},{name:"verifier_role",type:"varchar",length:100},{name:"require_signature",type:"boolean",notNull:!0,default:!1},{name:"all_must_approve",type:"boolean",notNull:!0,default:!1},{name:"step_order",type:"integer",notNull:!0,default:1},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","approved","rejected"]}],indexes:[{columns:["instance_id"]},{columns:["instance_id","step_order"]},{columns:["entity_name","entity_id"]},{columns:["verifier_user_id"]},{columns:["status"]}]},{table_name:"verificationFlows",feature_set:["authentication","verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"name",type:"varchar",length:255,notNull:!0},{name:"description",type:"text"},{name:"trigger_on",type:"varchar",length:50,notNull:!0,default:"update",enumValues:["create","update","delete","manual"]},{name:"trigger_fields",type:"jsonb"},{name:"is_draft",type:"boolean",notNull:!0,default:!0},{name:"published_at",type:"timestamptz"},{name:"viewport",type:"jsonb"}],indexes:[{columns:["entity_name"]},{columns:["entity_name","trigger_on"]},{columns:["is_draft"]}]},{table_name:"verificationSteps",feature_set:["authentication","verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"node_id",type:"varchar",length:100,notNull:!0},{name:"node_type",type:"varchar",length:50,notNull:!0,default:"step",enumValues:["step","verifier","notification"]},{name:"step_order",type:"integer",notNull:!0,default:1},{name:"name",type:"varchar",length:255},{name:"description",type:"text"},{name:"position_x",type:"numeric",notNull:!0,default:0},{name:"position_y",type:"numeric",notNull:!0,default:0},{name:"width",type:"numeric"},{name:"height",type:"numeric"},{name:"style",type:"jsonb"},{name:"data",type:"jsonb"}],indexes:[{columns:["flow_id"]},{columns:["entity_name"]},{columns:["flow_id","node_id"],unique:!0},{columns:["entity_name","step_order"]}]},{table_name:"verificationEdges",feature_set:["authentication","verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"edge_id",type:"varchar",length:100,notNull:!0},{name:"source_node_id",type:"varchar",length:100,notNull:!0},{name:"target_node_id",type:"varchar",length:100,notNull:!0},{name:"source_handle",type:"varchar",length:50},{name:"target_handle",type:"varchar",length:50},{name:"edge_type",type:"varchar",length:50,default:"default",enumValues:["default","conditional","success","failure"]},{name:"label",type:"varchar",length:255},{name:"condition",type:"jsonb"},{name:"style",type:"jsonb"},{name:"animated",type:"boolean",default:!1}],indexes:[{columns:["flow_id"]},{columns:["flow_id","edge_id"],unique:!0},{columns:["source_node_id"]},{columns:["target_node_id"]}]},{table_name:"verificationNotificationRules",feature_set:["verification","notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"node_id",type:"varchar",length:100,notNull:!0},{name:"trigger",type:"varchar",length:50,notNull:!0,enumValues:["on_flow_started","on_step_reached","on_approved","on_rejected","on_flow_completed"]},{name:"title_template",type:"varchar",length:255},{name:"body_template",type:"text"},{name:"starts_at",type:"timestamptz"},{name:"expires_at",type:"timestamptz"}],indexes:[{columns:["flow_id"]},{columns:["flow_id","node_id"],unique:!0},{columns:["trigger"]}]},{table_name:"verificationNotificationRecipients",feature_set:["verification","notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"rule_id",type:"uuid",notNull:!0,references:{table:"verificationNotificationRules",column:"id",onDelete:"cascade"}},{name:"recipient_type",type:"varchar",length:30,notNull:!0,enumValues:["user","role","all_verifiers","step_verifier","entity_creator"]},{name:"recipient_user_id",type:"uuid"},{name:"recipient_role",type:"varchar",length:100}],indexes:[{columns:["rule_id"]},{columns:["recipient_type"]}]},{table_name:"verificationVerifierConfigs",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"node_id",type:"varchar",length:100,notNull:!0},{name:"verifier_type",type:"varchar",length:30,notNull:!0,enumValues:["user","role"]},{name:"verifier_user_id",type:"uuid"},{name:"verifier_role",type:"varchar",length:100},{name:"require_signature",type:"boolean",notNull:!0,default:!1},{name:"all_must_approve",type:"boolean",notNull:!0,default:!1}],indexes:[{columns:["flow_id"]},{columns:["flow_id","node_id"],unique:!0},{columns:["verifier_type"]}]},{table_name:"verificationInstances",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id"}},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"entity_id",type:"uuid",notNull:!0},{name:"started_by",type:"uuid",references:{table:"users",column:"id"}},{name:"status",type:"varchar",length:30,notNull:!0,default:"active",enumValues:["active","completed","rejected","cancelled"]},{name:"current_step_order",type:"integer",notNull:!0,default:1},{name:"started_at",type:"timestamptz",notNull:!0,defaultRaw:"now()"},{name:"completed_at",type:"timestamptz"}],indexes:[{columns:["flow_id"]},{columns:["entity_name","entity_id"]},{columns:["entity_name","entity_id","status"]},{columns:["status"]},{columns:["started_by"]}]},{table_name:"verificationNotificationChannels",feature_set:["verification","notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"rule_id",type:"uuid",notNull:!0,references:{table:"verificationNotificationRules",column:"id",onDelete:"cascade"}},{name:"channel",type:"varchar",length:30,notNull:!0,enumValues:["portal","email","sms","telegram","webhook"]}],indexes:[{columns:["rule_id"]},{columns:["rule_id","channel"],unique:!0},{columns:["channel"]}]},{table_name:"user_cohorts",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"name",type:"varchar",length:255,notNull:!0},{name:"description",type:"text"},{name:"created_by",type:"uuid",references:{table:"users",column:"id",onDelete:"set null"}},{name:"expires_at",type:"timestamptz"},{name:"user_count",type:"integer",notNull:!0,default:0},{name:"metadata",type:"jsonb",default:"{}"}]},{table_name:"user_sessions",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,group_name:"Authentication",available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"token_hash",type:"varchar",length:255,notNull:!0},{name:"refresh_token_hash",type:"varchar",length:255},{name:"device_fingerprint",type:"varchar",length:255},{name:"device_name",type:"varchar",length:100},{name:"device_type",type:"varchar",length:50,enumValues:["desktop","mobile","tablet","unknown"]},{name:"browser_name",type:"varchar",length:50},{name:"browser_version",type:"varchar",length:20},{name:"os_name",type:"varchar",length:50},{name:"os_version",type:"varchar",length:20},{name:"ip_address",type:"varchar",length:45,notNull:!0},{name:"location_country",type:"varchar",length:100},{name:"location_city",type:"varchar",length:100},{name:"location_coordinates",type:"varchar",length:50},{name:"last_activity_at",type:"timestamptz",notNull:!0,defaultRaw:"now()"},{name:"expires_at",type:"timestamptz",notNull:!0},{name:"revoked_at",type:"timestamptz"},{name:"revoked_reason",type:"varchar",length:100,enumValues:["user_logout","user_revoked","admin_revoked","security_concern","password_changed","expired","replaced"]},{name:"is_current",type:"boolean",notNull:!0,default:!1},{name:"login_method",type:"varchar",length:50,enumValues:["password","oauth_google","oauth_github","oauth_microsoft","magic_link","sso","api_key"]},{name:"remember_me",type:"boolean",notNull:!0,default:!1},{name:"trust_score",type:"integer",default:100},{name:"approval_status",type:"varchar",length:20,default:"approved",enumValues:["approved","pending","rejected"]},{name:"approval_token",type:"varchar",length:64},{name:"approval_requested_at",type:"timestamptz"},{name:"approval_responded_at",type:"timestamptz"}],indexes:[{columns:["user_id"]},{columns:["token_hash"],unique:!0},{columns:["refresh_token_hash"]},{columns:["user_id","is_active"]},{columns:["expires_at"]},{columns:["device_fingerprint"]},{columns:["ip_address"]},{columns:["last_activity_at"]},{columns:["approval_status"]},{columns:["approval_token"]}]},{table_name:"trusted_devices",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,group_name:"Authentication",available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"token_hash",type:"varchar",length:64,notNull:!0},{name:"status",type:"varchar",length:20,notNull:!0,default:"pending",enumValues:["pending","trusted","revoked"]},{name:"origin_session_id",type:"uuid"},{name:"label",type:"varchar",length:120},{name:"device_fingerprint",type:"varchar",length:255},{name:"first_seen_ip",type:"varchar",length:45},{name:"last_seen_ip",type:"varchar",length:45},{name:"last_seen_at",type:"timestamptz"},{name:"expires_at",type:"timestamptz"},{name:"revoked_at",type:"timestamptz"},{name:"revoked_reason",type:"varchar",length:30,enumValues:["user_revoked","password_reset","logout","admin_revoked","expired","replaced"]}],indexes:[{columns:["token_hash"],unique:!0},{columns:["user_id"]},{columns:["user_id","status"]},{columns:["origin_session_id"]},{columns:["expires_at"]}]},{table_name:"password_reset_tokens",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,group_name:"Authentication",requires:["email"],available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"token_hash",type:"varchar",length:255,notNull:!0},{name:"expires_at",type:"timestamptz",notNull:!0},{name:"used_at",type:"timestamptz"}],indexes:[{columns:["token_hash"],unique:!0},{columns:["user_id"]},{columns:["expires_at"]}]},{table_name:"magic_link_tokens",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,group_name:"Authentication",requires:["email"],available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"email",type:"varchar",length:255,notNull:!0},{name:"token_hash",type:"varchar",length:255,notNull:!0},{name:"expires_at",type:"timestamptz",notNull:!0},{name:"used_at",type:"timestamptz"}],indexes:[{columns:["token_hash"],unique:!0},{columns:["user_id"]},{columns:["email"]},{columns:["expires_at"]}]},{table_name:"webauthn_credentials",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,group_name:"Authentication",requires:[],available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"credential_id",type:"text",notNull:!0},{name:"public_key",type:"text",notNull:!0},{name:"counter",type:"bigint",mode:"number",notNull:!0,defaultValue:0},{name:"transports",type:"jsonb"},{name:"device_type",type:"varchar",length:32},{name:"backed_up",type:"boolean",notNull:!0,defaultValue:!1},{name:"aaguid",type:"varchar",length:64},{name:"authenticator_attachment",type:"varchar",length:32},{name:"nickname",type:"varchar",length:128},{name:"last_used_at",type:"timestamptz"},{name:"revoked_at",type:"timestamptz"}],indexes:[{columns:["credential_id"],unique:!0},{columns:["user_id"]}]},{table_name:"webauthn_challenges",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,group_name:"Authentication",requires:[],available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE","GET"],columns:[{name:"user_id",type:"uuid",references:{table:"users",column:"id",onDelete:"cascade"}},{name:"challenge",type:"text",notNull:!0},{name:"challenge_type",type:"varchar",length:32,notNull:!0},{name:"expires_at",type:"timestamptz",notNull:!0},{name:"consumed_at",type:"timestamptz"}],indexes:[{columns:["challenge"],unique:!0},{columns:["user_id"]},{columns:["expires_at"]}]},{table_name:"audit_logs",feature_set:["audit"],add_base_columns:!1,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","DELETE","PATCH","TOGGLE","VERIFICATION"],columns:[{name:"id",type:"uuid",primaryKey:!0,defaultRaw:"gen_random_uuid()"},{name:"entity_id",type:"uuid"},{name:"entity_name",type:"text",notNull:!0},{name:"operation_type",type:"text",notNull:!0},{name:"user_id",type:"uuid"},{name:"ip_address",type:"text"},{name:"user_agent",type:"text"},{name:"summary",type:"text"},{name:"severity",type:"text",default:"info"},{name:"category",type:"text"},{name:"occurrence_count",type:"integer",default:1},{name:"last_occurrence_at",type:"timestamp"},{name:"old_values",type:"jsonb"},{name:"new_values",type:"jsonb"},{name:"created_at",type:"timestamp",notNull:!0,defaultRaw:"now()"},{name:"path",type:"text"},{name:"query",type:"text"}],indexes:[{columns:["entity_id"]},{columns:["entity_name"]},{columns:["user_id"]},{columns:["created_at"]},{columns:["severity"]},{columns:["category"]}]},{table_name:"monitoring_metrics",feature_set:["monitoring"],add_base_columns:!1,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","DELETE","PATCH","TOGGLE","VERIFICATION"],columns:[{name:"id",type:"uuid",primaryKey:!0,defaultRaw:"gen_random_uuid()"},{name:"metric_type",type:"text",notNull:!0},{name:"metric_name",type:"text",notNull:!0},{name:"value",type:"doublePrecision",notNull:!0},{name:"tags",type:"jsonb"},{name:"recorded_at",type:"timestamp",notNull:!0}],indexes:[{columns:["metric_type"]},{columns:["metric_name"]},{columns:["recorded_at"]}]},{table_name:"oauth_accounts",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!1,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"provider",type:"varchar",length:50,notNull:!0,enumValues:["google","github","microsoft","discord","facebook","twitter","apple","custom"]},{name:"provider_account_id",type:"varchar",length:255,notNull:!0},{name:"provider_email",type:"varchar",length:255},{name:"provider_name",type:"varchar",length:255},{name:"provider_avatar_url",type:"text"},{name:"access_token",type:"text"},{name:"refresh_token",type:"text"},{name:"token_expires_at",type:"timestamp"},{name:"scope",type:"text"},{name:"raw_profile",type:"jsonb"},{name:"is_primary",type:"boolean",notNull:!0,default:!1},{name:"last_used_at",type:"timestamp"}],indexes:[{columns:["user_id"]},{columns:["provider","provider_account_id"],unique:!0},{columns:["provider_email"]},{columns:["user_id","provider"]}],constraints:{unique:[{name:"unique_provider_account",columns:["provider","provider_account_id"]}]}},{table_name:"api_keys",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH"],bulk_endpoints_enabled:!1,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"name",type:"varchar",length:255,notNull:!0},{name:"description",type:"text"},{name:"key_hash",type:"varchar",length:255,notNull:!0},{name:"key_preview",type:"varchar",length:20,notNull:!0},{name:"owner_type",type:"varchar",length:30,notNull:!0,default:"personal",enumValues:["personal","application"]},{name:"application_name",type:"varchar",length:255},{name:"allowed_roles",type:"jsonb",notNull:!0,default:"[]"},{name:"allowed_claims",type:"jsonb",notNull:!0,default:"[]"},{name:"allowed_scopes",type:"jsonb",notNull:!0,default:"[]"},{name:"expires_at",type:"timestamptz"},{name:"last_used_at",type:"timestamptz"},{name:"last_used_ip",type:"varchar",length:45},{name:"usage_count",type:"integer",notNull:!0,default:0},{name:"revoked_at",type:"timestamptz"},{name:"revoked_reason",type:"varchar",length:255}],indexes:[{columns:["key_hash"],unique:!0},{columns:["user_id"]},{columns:["user_id","is_active"]},{columns:["owner_type"]},{columns:["expires_at"]},{columns:["last_used_at"]}]},{table_name:"backup_logs",feature_set:["backup"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main","all"],excluded_schemas:[],excluded_methods:["PUT","PATCH"],columns:[{name:"backup_name",type:"varchar",length:255,notNull:!0},{name:"file_name",type:"varchar",length:500,notNull:!0},{name:"schema_name",type:"varchar",length:100,notNull:!0},{name:"format",type:"varchar",length:20,notNull:!0,default:"json"},{name:"status",type:"varchar",length:20,notNull:!0,default:"pending"},{name:"trigger",type:"varchar",length:20,notNull:!0,default:"manual"},{name:"size_bytes",type:"integer"},{name:"table_count",type:"integer"},{name:"row_count",type:"integer"},{name:"included_tables",type:"jsonb",default:"[]"},{name:"excluded_tables",type:"jsonb",default:"[]"},{name:"error_message",type:"text"},{name:"started_at",type:"timestamp"},{name:"completed_at",type:"timestamp"},{name:"performed_by",type:"varchar",length:255},{name:"cron_expression",type:"varchar",length:100},{name:"retention_days",type:"integer"}],indexes:[{columns:["schema_name"]},{columns:["status"]},{columns:["trigger"]},{columns:["created_at"]}]},{table_name:"payment_transactions",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"user_id",type:"uuid",references:{table:"users",column:"id"}},{name:"order_id",type:"varchar",length:255},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_transaction_id",type:"varchar",length:255},{name:"provider_payment_id",type:"varchar",length:255},{name:"payment_method",type:"varchar",length:50},{name:"amount",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"currency",type:"varchar",length:10,notNull:!0,default:"TRY"},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","processing","completed","failed","refunded","partially_refunded","cancelled"]},{name:"status_code",type:"integer"},{name:"status_message",type:"text"},{name:"card_last_four",type:"varchar",length:4},{name:"card_type",type:"varchar",length:50},{name:"card_association",type:"varchar",length:50},{name:"installment",type:"integer",default:1},{name:"is_three_d_secure",type:"boolean",default:!1},{name:"provider_response",type:"jsonb",default:"{}"},{name:"metadata",type:"jsonb",default:"{}"},{name:"refunded_amount",type:"numeric",precision:12,scale:2,default:0},{name:"refunded_at",type:"timestamptz"},{name:"completed_at",type:"timestamptz"},{name:"failed_at",type:"timestamptz"},{name:"ip_address",type:"varchar",length:45}],indexes:[{columns:["user_id"]},{columns:["order_id"]},{columns:["provider"]},{columns:["provider_payment_id"]},{columns:["status"]},{columns:["user_id","status"]}]},{table_name:"payment_methods",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"type",type:"varchar",length:30,notNull:!0,default:"card",enumValues:["card","bank_account","wallet"]},{name:"alias",type:"varchar",length:100},{name:"card_last_four",type:"varchar",length:4},{name:"card_type",type:"varchar",length:50},{name:"card_association",type:"varchar",length:50},{name:"card_family",type:"varchar",length:100},{name:"card_bank_name",type:"varchar",length:100},{name:"provider_card_user_key",type:"varchar",length:255},{name:"provider_card_token",type:"varchar",length:255},{name:"bin_number",type:"varchar",length:8},{name:"is_default",type:"boolean",default:!1},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["user_id"]},{columns:["provider"]},{columns:["user_id","is_default"]},{columns:["provider_card_user_key"]}]},{table_name:"payment_webhook_logs",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["PUT","PATCH","DELETE"],columns:[{name:"provider",type:"varchar",length:50,notNull:!0},{name:"event_type",type:"varchar",length:100,notNull:!0},{name:"provider_payment_id",type:"varchar",length:255},{name:"raw_payload",type:"jsonb",notNull:!0},{name:"processed",type:"boolean",default:!1},{name:"processing_result",type:"jsonb"},{name:"error_message",type:"text"},{name:"ip_address",type:"varchar",length:45},{name:"idempotency_key",type:"varchar",length:255}],indexes:[{columns:["provider"]},{columns:["event_type"]},{columns:["provider_payment_id"]},{columns:["processed"]},{columns:["idempotency_key"],unique:!0}]},{table_name:"payment_sub_merchants",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",references:{table:"users",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_sub_merchant_key",type:"varchar",length:255},{name:"external_id",type:"varchar",length:255},{name:"type",type:"varchar",length:50,notNull:!0,default:"personal",enumValues:["personal","private_company","limited_or_joint_stock_company"]},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","active","suspended","rejected"]},{name:"name",type:"varchar",length:255,notNull:!0},{name:"email",type:"varchar",length:255,notNull:!0},{name:"gsm_number",type:"varchar",length:20},{name:"address",type:"text"},{name:"iban",type:"varchar",length:50},{name:"contact_name",type:"varchar",length:100},{name:"contact_surname",type:"varchar",length:100},{name:"identity_number",type:"varchar",length:20},{name:"tax_office",type:"varchar",length:100},{name:"tax_number",type:"varchar",length:20},{name:"legal_company_title",type:"varchar",length:255},{name:"currency",type:"varchar",length:10,default:"TRY"},{name:"commission_rate",type:"numeric",precision:5,scale:2,default:0},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["user_id"]},{columns:["provider"]},{columns:["provider_sub_merchant_key"]},{columns:["external_id"]},{columns:["status"]},{columns:["email"]}]},{table_name:"payment_commission_splits",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"transaction_id",type:"uuid",notNull:!0,references:{table:"payment_transactions",column:"id",onDelete:"cascade"}},{name:"sub_merchant_id",type:"uuid",notNull:!0,references:{table:"payment_sub_merchants",column:"id"}},{name:"basket_item_id",type:"varchar",length:255},{name:"item_price",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"sub_merchant_price",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"platform_commission",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"commission_rate",type:"numeric",precision:5,scale:2,default:0},{name:"provider_split_id",type:"varchar",length:255},{name:"currency",type:"varchar",length:10,notNull:!0,default:"TRY"},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","approved","disapproved","refunded"]},{name:"approved_at",type:"timestamptz"},{name:"disapproved_at",type:"timestamptz"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["transaction_id"]},{columns:["sub_merchant_id"]},{columns:["status"]},{columns:["transaction_id","sub_merchant_id"]},{columns:["provider_split_id"]}]},{table_name:"payment_products",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_product_id",type:"varchar",length:255},{name:"name",type:"varchar",length:255,notNull:!0},{name:"description",type:"text"},{name:"type",type:"varchar",length:30,default:"service",enumValues:["service","good"]},{name:"status",type:"varchar",length:30,notNull:!0,default:"active",enumValues:["active","archived","draft"]},{name:"images",type:"jsonb",default:"[]"},{name:"unit_label",type:"varchar",length:50},{name:"url",type:"varchar",length:500},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["provider"]},{columns:["provider_product_id"]},{columns:["name"]},{columns:["status"]},{columns:["type"]}]},{table_name:"payment_prices",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"product_id",type:"uuid",notNull:!0,references:{table:"payment_products",column:"id",onDelete:"cascade"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_price_id",type:"varchar",length:255},{name:"currency",type:"varchar",length:10,notNull:!0,default:"USD"},{name:"unit_amount",type:"integer",notNull:!0,default:0},{name:"unit_amount_decimal",type:"varchar",length:30},{name:"type",type:"varchar",length:30,notNull:!0,default:"one_time",enumValues:["one_time","recurring"]},{name:"billing_scheme",type:"varchar",length:30,default:"per_unit",enumValues:["per_unit","tiered"]},{name:"nickname",type:"varchar",length:255},{name:"recurring_interval",type:"varchar",length:20,enumValues:["day","week","month","year"]},{name:"recurring_interval_count",type:"integer",default:1},{name:"recurring_usage_type",type:"varchar",length:20,default:"licensed",enumValues:["licensed","metered"]},{name:"recurring_aggregate_usage",type:"varchar",length:30,enumValues:["sum","last_during_period","last_ever","max"]},{name:"transform_quantity_divide_by",type:"integer"},{name:"transform_quantity_round",type:"varchar",length:10,enumValues:["up","down"]},{name:"status",type:"varchar",length:30,notNull:!0,default:"active",enumValues:["active","archived"]},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["product_id"]},{columns:["provider"]},{columns:["provider_price_id"]},{columns:["type"]},{columns:["currency"]},{columns:["status"]},{columns:["product_id","status"]}]},{table_name:"payment_customers",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",references:{table:"users",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_customer_id",type:"varchar",length:255,notNull:!0},{name:"email",type:"varchar",length:255,notNull:!0},{name:"name",type:"varchar",length:255},{name:"phone",type:"varchar",length:50},{name:"description",type:"text"},{name:"address",type:"jsonb",default:"{}"},{name:"tax_id_type",type:"varchar",length:50},{name:"tax_id_value",type:"varchar",length:100},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["user_id"]},{columns:["provider"]},{columns:["provider_customer_id"]},{columns:["email"]},{columns:["user_id","provider"],unique:!0}]},{table_name:"payment_subscriptions",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"customer_id",type:"uuid",notNull:!0,references:{table:"payment_customers",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_subscription_id",type:"varchar",length:255},{name:"status",type:"varchar",length:30,notNull:!0,default:"incomplete",enumValues:["active","past_due","unpaid","canceled","incomplete","incomplete_expired","trialing","paused"]},{name:"collection_method",type:"varchar",length:30,default:"charge_automatically",enumValues:["charge_automatically","send_invoice"]},{name:"current_period_start",type:"timestamptz"},{name:"current_period_end",type:"timestamptz"},{name:"cancel_at_period_end",type:"boolean",default:!1},{name:"canceled_at",type:"timestamptz"},{name:"trial_start",type:"timestamptz"},{name:"trial_end",type:"timestamptz"},{name:"items",type:"jsonb",default:"[]"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["customer_id"]},{columns:["provider"]},{columns:["provider_subscription_id"]},{columns:["status"]},{columns:["customer_id","status"]}]},{table_name:"payment_invoices",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"customer_id",type:"uuid",notNull:!0,references:{table:"payment_customers",column:"id"}},{name:"subscription_id",type:"uuid",references:{table:"payment_subscriptions",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_invoice_id",type:"varchar",length:255},{name:"status",type:"varchar",length:30,notNull:!0,default:"draft",enumValues:["draft","open","paid","uncollectible","void"]},{name:"collection_method",type:"varchar",length:30,default:"charge_automatically",enumValues:["charge_automatically","send_invoice"]},{name:"currency",type:"varchar",length:10,notNull:!0,default:"USD"},{name:"amount_due",type:"integer",default:0},{name:"amount_paid",type:"integer",default:0},{name:"amount_remaining",type:"integer",default:0},{name:"description",type:"text"},{name:"hosted_invoice_url",type:"varchar",length:1000},{name:"invoice_pdf",type:"varchar",length:1000},{name:"due_date",type:"timestamptz"},{name:"days_until_due",type:"integer"},{name:"period_start",type:"timestamptz"},{name:"period_end",type:"timestamptz"},{name:"paid_at",type:"timestamptz"},{name:"voided_at",type:"timestamptz"},{name:"lines",type:"jsonb",default:"[]"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["customer_id"]},{columns:["subscription_id"]},{columns:["provider"]},{columns:["provider_invoice_id"]},{columns:["status"]},{columns:["customer_id","status"]}]},{table_name:"chat_conversations",feature_set:["authentication","chat"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"type",type:"varchar",length:20,notNull:!0,default:"direct",enumValues:["direct","group"]},{name:"title",type:"varchar",length:255},{name:"description",type:"text"},{name:"avatar_file_id",type:"uuid"},{name:"direct_key",type:"varchar",length:255},{name:"last_message_at",type:"timestamptz"},{name:"last_message_preview",type:"varchar",length:500},{name:"last_message_sender_id",type:"uuid",references:{table:"users",column:"id",onDelete:"set null"}}],indexes:[{columns:["direct_key"],unique:!0},{columns:["type"]},{columns:["last_message_at"]}]},{table_name:"chat_participants",feature_set:["authentication","chat"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"conversation_id",type:"uuid",notNull:!0,references:{table:"chat_conversations",column:"id",onDelete:"cascade"}},{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"role",type:"varchar",length:20,notNull:!0,default:"member",enumValues:["member","admin","owner"]},{name:"last_read_message_id",type:"uuid"},{name:"last_read_at",type:"timestamptz"},{name:"unread_count",type:"integer",notNull:!0,default:0},{name:"muted",type:"boolean",notNull:!0,default:!1},{name:"muted_until",type:"timestamptz"},{name:"notifications_enabled",type:"boolean",notNull:!0,default:!0},{name:"left_at",type:"timestamptz"}],indexes:[{columns:["user_id"]},{columns:["conversation_id"]}],constraints:{unique:[{name:"unique_conversation_participant",columns:["conversation_id","user_id"]}]}},{table_name:"chat_messages",feature_set:["authentication","chat"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"conversation_id",type:"uuid",notNull:!0,references:{table:"chat_conversations",column:"id",onDelete:"cascade"}},{name:"sender_id",type:"uuid",references:{table:"users",column:"id",onDelete:"set null"}},{name:"content",type:"text"},{name:"content_type",type:"varchar",length:20,notNull:!0,default:"text",enumValues:["text","image","file","video","audio","system"]},{name:"reply_to_id",type:"uuid",references:{table:"chat_messages",column:"id",onDelete:"set null"}},{name:"metadata",type:"jsonb",default:"{}"},{name:"client_message_id",type:"varchar",length:100},{name:"edited_at",type:"timestamptz"},{name:"deleted_at",type:"timestamptz"}],indexes:[{columns:["conversation_id","created_at"]},{columns:["sender_id"]},{columns:["reply_to_id"]}]},{table_name:"chat_message_attachments",feature_set:["authentication","chat","storage"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"message_id",type:"uuid",notNull:!0,references:{table:"chat_messages",column:"id",onDelete:"cascade"}},{name:"conversation_id",type:"uuid",notNull:!0,references:{table:"chat_conversations",column:"id",onDelete:"cascade"}},{name:"file_id",type:"uuid",notNull:!0,references:{table:"files",column:"id",onDelete:"cascade"}},{name:"kind",type:"varchar",length:20,notNull:!0,default:"file",enumValues:["image","video","audio","file"]},{name:"original_name",type:"varchar",length:255},{name:"mime_type",type:"varchar",length:100},{name:"size",type:"bigint",mode:"number"},{name:"width",type:"integer"},{name:"height",type:"integer"},{name:"duration",type:"integer"}],indexes:[{columns:["message_id"]},{columns:["conversation_id"]},{columns:["file_id"]}]},{table_name:"payment_splits",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],group_name:"Payments Marketplace",columns:[{name:"transaction_id",type:"uuid",references:{table:"paymentTransactions",column:"id",onDelete:"set null"}},{name:"recipient_owner_type",type:"varchar",length:20,notNull:!0,default:"seller",comment:"seller | platform | tenant | user"},{name:"recipient_owner_id",type:"uuid",notNull:!0},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"gross_amount",type:"bigint",mode:"number",notNull:!0,comment:"Minor units"},{name:"provider_fee_amount",type:"bigint",mode:"number",notNull:!0,default:0},{name:"platform_fee_amount",type:"bigint",mode:"number",notNull:!0,default:0},{name:"reserve_amount",type:"bigint",mode:"number",notNull:!0,default:0},{name:"net_payable_amount",type:"bigint",mode:"number",notNull:!0},{name:"currency",type:"varchar",length:10,notNull:!0},{name:"available_for_payout_at",type:"timestamptz"},{name:"status",type:"varchar",length:20,notNull:!0,default:"pending",comment:"pending | available | payout_requested | paid | held | refunded | disputed | cancelled"},{name:"source_type",type:"varchar",length:50},{name:"source_id",type:"varchar",length:255},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["recipient_owner_type","recipient_owner_id"]},{columns:["status"]},{columns:["transaction_id"]}]},{table_name:"payment_ledger_entries",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],group_name:"Payments Marketplace",columns:[{name:"account",type:"varchar",length:40,notNull:!0,comment:"platform_revenue | provider_fee | seller_payable | reserve | refund_liability | dispute_liability | payout_in_transit | payout_completed"},{name:"owner_type",type:"varchar",length:20},{name:"owner_id",type:"uuid"},{name:"direction",type:"varchar",length:6,notNull:!0,comment:"debit | credit"},{name:"amount",type:"bigint",mode:"number",notNull:!0,comment:"Minor units"},{name:"currency",type:"varchar",length:10,notNull:!0},{name:"entry_type",type:"varchar",length:40,notNull:!0,comment:"split | refund | payout | reserve_hold | reserve_release | dispute | adjustment"},{name:"reference_type",type:"varchar",length:50},{name:"reference_id",type:"varchar",length:255},{name:"split_id",type:"uuid",references:{table:"paymentSplits",column:"id",onDelete:"set null"}},{name:"description",type:"text"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["account"]},{columns:["owner_type","owner_id"]},{columns:["entry_type"]},{columns:["reference_type","reference_id"]}]},{table_name:"payment_settlement_policies",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],group_name:"Payments Marketplace",columns:[{name:"owner_type",type:"varchar",length:20,notNull:!0,default:"tenant",comment:"tenant | seller"},{name:"owner_id",type:"uuid",notNull:!0},{name:"default_delay_days",type:"integer",notNull:!0,default:7},{name:"new_seller_delay_days",type:"integer",notNull:!0,default:14},{name:"reserve_rate",type:"numeric",precision:5,scale:4,notNull:!0,default:0,comment:"Fraction 0..1 held as reserve"},{name:"reserve_days",type:"integer",notNull:!0,default:0},{name:"minimum_payout_amount",type:"bigint",mode:"number",notNull:!0,default:0},{name:"currency",type:"varchar",length:10},{name:"early_payout_enabled",type:"boolean",notNull:!0,default:!1},{name:"status",type:"varchar",length:20,notNull:!0,default:"active"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["owner_type","owner_id"],unique:!0}]},{table_name:"payment_reserves",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],group_name:"Payments Marketplace",columns:[{name:"owner_type",type:"varchar",length:20,notNull:!0,default:"seller"},{name:"owner_id",type:"uuid",notNull:!0},{name:"split_id",type:"uuid",references:{table:"paymentSplits",column:"id",onDelete:"set null"}},{name:"amount",type:"bigint",mode:"number",notNull:!0},{name:"currency",type:"varchar",length:10,notNull:!0},{name:"reason",type:"varchar",length:30,notNull:!0,default:"refund_window",comment:"refund_window | chargeback_risk | new_seller | manual_hold | dispute | compliance_review"},{name:"status",type:"varchar",length:20,notNull:!0,default:"held",comment:"held | released | consumed | cancelled"},{name:"release_at",type:"timestamptz"},{name:"released_at",type:"timestamptz"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["owner_type","owner_id"]},{columns:["status"]},{columns:["release_at"]}]},{table_name:"payment_payout_requests",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["PUT"],group_name:"Payments Marketplace",columns:[{name:"recipient_owner_type",type:"varchar",length:20,notNull:!0,default:"seller"},{name:"recipient_owner_id",type:"uuid",notNull:!0},{name:"amount",type:"bigint",mode:"number",notNull:!0},{name:"currency",type:"varchar",length:10,notNull:!0},{name:"status",type:"varchar",length:20,notNull:!0,default:"pending",comment:"pending | approved | rejected | processing | completed | failed | cancelled"},{name:"provider",type:"varchar",length:50},{name:"provider_payout_id",type:"varchar",length:255},{name:"provider_transfer_id",type:"varchar",length:255},{name:"destination",type:"varchar",length:255},{name:"requested_by",type:"uuid"},{name:"decided_by",type:"uuid"},{name:"decided_at",type:"timestamptz"},{name:"completed_at",type:"timestamptz"},{name:"failure_reason",type:"text"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["recipient_owner_type","recipient_owner_id"]},{columns:["status"]}]},{table_name:"payment_disputes",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["PUT"],group_name:"Payments Marketplace",columns:[{name:"transaction_id",type:"uuid",references:{table:"paymentTransactions",column:"id",onDelete:"set null"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_dispute_id",type:"varchar",length:255},{name:"owner_type",type:"varchar",length:20},{name:"owner_id",type:"uuid"},{name:"amount",type:"bigint",mode:"number"},{name:"currency",type:"varchar",length:10},{name:"reason",type:"varchar",length:100},{name:"status",type:"varchar",length:30,notNull:!0,default:"open",comment:"open | under_review | won | lost | accepted | cancelled"},{name:"evidence_due_at",type:"timestamptz"},{name:"resolved_at",type:"timestamptz"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["provider","provider_dispute_id"]},{columns:["status"]},{columns:["owner_type","owner_id"]},{columns:["transaction_id"]}]},{table_name:"nucleus_secrets",feature_set:["secrets"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["GET","POST","PUT","PATCH","DELETE","TOGGLE"],bulk_endpoints_enabled:!1,group_name:"Secrets",columns:[{name:"scope",type:"varchar",length:200,notNull:!0,comment:"Config dot-path that owns the credential, e.g. authentication.oauth.providers.microsoft"},{name:"key",type:"varchar",length:120,notNull:!0,comment:"Leaf key under that path, e.g. clientSecret"},{name:"value_enc",type:"text",notNull:!0,comment:"AES-256-GCM envelope v1:iv:tag:ciphertext \u2014 never returned by any route"},{name:"previous_enc",type:"text",comment:"Value replaced by the last rotation, retained for one-step rollback"},{name:"preview",type:"varchar",length:80},{name:"kind",type:"varchar",length:30,notNull:!0,default:"text",enumValues:["text","password","json","connection_string","pem"]},{name:"description",type:"varchar",length:500},{name:"version",type:"integer",notNull:!0,default:1},{name:"rotated_at",type:"timestamptz"},{name:"last_used_at",type:"timestamptz"}],indexes:[{columns:["scope","key"],unique:!0},{columns:["scope"]}]},{table_name:"integration_sources",feature_set:["integrations"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!1,group_name:"Integrations",columns:[{name:"name",type:"varchar",length:150,notNull:!0},{name:"slug",type:"varchar",length:150,notNull:!0,comment:"Stable machine name; referenced by exports and by operators in logs"},{name:"base_url",type:"varchar",length:500,notNull:!0,comment:"Any scheme, host and port \u2014 https, plain http, in-cluster DNS, IP. HTTPS is NOT required and must never be enforced: reaching a service inside the same cluster over http is a legitimate deployment."},{name:"description",type:"text"},{name:"enabled",type:"boolean",default:!0},{name:"auth_type",type:"varchar",length:20,notNull:!0,default:"none",enumValues:["none","bearer","api_key","basic","oauth2"]},{name:"auth_token_encrypted",type:"text",sensitive:!0,comment:"Static credential (bearer / api key / basic blob), encrypted at rest"},{name:"auth_token_hint",type:"varchar",length:24},{name:"auth_header_name",type:"varchar",length:80,default:"Authorization"},{name:"auth_query_param",type:"varchar",length:80,comment:"When set, an api_key credential travels as this query parameter instead of a header"},{name:"extra_headers",type:"jsonb",default:{}},{name:"token_url",type:"varchar",length:500},{name:"oauth_grant_type",type:"varchar",length:40,default:"password",enumValues:["password","client_credentials"]},{name:"oauth_client_id",type:"varchar",length:200},{name:"oauth_client_secret_encrypted",type:"text",sensitive:!0},{name:"oauth_client_secret_hint",type:"varchar",length:24},{name:"oauth_username",type:"varchar",length:200},{name:"oauth_password_encrypted",type:"text",sensitive:!0},{name:"oauth_password_hint",type:"varchar",length:24},{name:"oauth_scope",type:"varchar",length:300},{name:"oauth_client_auth",type:"varchar",length:20,default:"basic",enumValues:["basic","body"]},{name:"tls_verify",type:"boolean",notNull:!0,default:!0,comment:"Per-source certificate verification. Turning it off applies to THIS source's connections only \u2014 never to the process, which is what a NODE_TLS_REJECT_UNAUTHORIZED toggle would do."},{name:"timeout_ms",type:"integer",notNull:!0,default:30000},{name:"spec_url",type:"varchar",length:500,comment:"Optional API description document (OpenAPI/Swagger/Postman/Bruno). Discovery is a convenience: every endpoint can always be defined by hand instead."},{name:"spec_format",type:"varchar",length:20,default:"manual",enumValues:["manual","openapi","swagger","postman","bruno","har"]}],constraints:{unique:[{name:"uniq_integration_source_slug",columns:["slug"]}]},indexes:[{columns:["enabled"]}]},{table_name:"integration_endpoints",feature_set:["integrations"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!1,group_name:"Integrations",columns:[{name:"source_id",type:"uuid",notNull:!0,references:{table:"integrationSources",column:"id",onDelete:"cascade"}},{name:"tag",type:"varchar",length:120,notNull:!0},{name:"name",type:"varchar",length:200},{name:"method",type:"varchar",length:10,notNull:!0,default:"GET",enumValues:["GET","POST","PUT","PATCH","DELETE"]},{name:"path",type:"varchar",length:500,notNull:!0,comment:"Appended to the source base URL. May carry {brace} or :colon path tokens, whose values come from param_bindings."},{name:"description",type:"text"},{name:"query_params",type:"jsonb",default:{}},{name:"request_body",type:"jsonb",default:{}},{name:"param_bindings",type:"jsonb",default:[],comment:"Where each path/query parameter comes from: a static value, another endpoint's records (fan-out), or a column of one of our own tables."},{name:"pagination",type:"jsonb",default:{},comment:"Explicitly chosen paging profile (none/page_number/offset/cursor/link_header). Never guessed \u2014 a wrong guess silently imports one page."},{name:"response_root_path",type:"varchar",length:200},{name:"tree_children_path",type:"varchar",length:200,comment:"Field holding a record's children when the source answers with a shape rather than a list \u2014 each node then becomes its own row and knows its parent"},{name:"sample_response",type:"jsonb",default:{},comment:"A few real records captured by a live test, so the mapping screen still shows fields when the source is unreachable"},{name:"enabled",type:"boolean",default:!0}],indexes:[{columns:["source_id"]},{columns:["source_id","tag"]}]},{table_name:"integration_mappings",feature_set:["integrations"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!1,group_name:"Integrations",columns:[{name:"endpoint_id",type:"uuid",notNull:!0,references:{table:"integrationEndpoints",column:"id",onDelete:"cascade"}},{name:"name",type:"varchar",length:200,notNull:!0},{name:"target_entity",type:"varchar",length:120,notNull:!0,comment:"snake_case table name this mapping writes into"},{name:"field_mappings",type:"jsonb",notNull:!0,default:[]},{name:"reference_checks",type:"jsonb",notNull:!0,default:[],comment:"Columns whose value must already exist in another entity, and what to do when it does not."},{name:"dedup_source_field",type:"varchar",length:200},{name:"dedup_target_field",type:"varchar",length:200,comment:"Target column that identifies the same record across runs. Without it nothing can be matched and every run appends."},{name:"write_mode",type:"varchar",length:20,notNull:!0,default:"upsert",enumValues:["upsert","append","replace"],comment:"replace is the destructive wipe-and-rewrite; it is no longer the default and is gated by the completeness check."},{name:"missing_record_policy",type:"varchar",length:20,notNull:!0,default:"ignore",enumValues:["ignore","deactivate","delete"],comment:"What happens to a row that exists here but no longer in the source. deactivate is the right answer for most HR data and could not be expressed before."},{name:"missing_record_column",type:"varchar",length:120},{name:"missing_record_value",type:"varchar",length:200},{name:"removal_scope_column",type:"varchar",length:120,comment:"Target column carrying whatever the fan-out varies \u2014 a company code, a branch, a tenant. Set it when one mapping reads its source through several calls: removal is then confined to the values actually read, so a call that answers HTTP 500 costs that slice its cleanup instead of costing the whole run. Without it a single failing call refuses every removal, and a source whose one bad endpoint fails every night is never cleaned at all."},{name:"origin_column",type:"varchar",length:120,comment:"Column this mapping stamps on rows it owns. Set it when the target table ALSO holds rows people create by hand: without it every hand-made row looks like one the source stopped carrying, and the first run with a removal policy deletes them all."},{name:"origin_value",type:"varchar",length:120,comment:"The value written into origin_column. Rows carrying it are the only removal candidates."},{name:"max_removal_share",type:"numeric",comment:"Share of the target table (0-1) above which an UNATTENDED run refuses to remove. A scheduled run passes through neither the preview nor a confirmation, so this is the only thing between a wrong plan and the table. 0 or null disables."},{name:"password_target_column",type:"varchar",length:100,comment:"Column that receives the shared opening password given at run time. The password itself is never stored."},{name:"account_rule",type:"jsonb",comment:"Creates a login alongside each imported record, in the same transaction, and links it. The password belongs to the run, never to this row."},{name:"schedule_cron",type:"varchar",length:120},{name:"schedule_timezone",type:"varchar",length:64,comment:"IANA zone the cron expression is read in. Without it a nightly job drifts with the container's clock."},{name:"schedule_enabled",type:"boolean",notNull:!0,default:!1},{name:"last_run_at",type:"timestamptz"},{name:"enabled",type:"boolean",default:!0}],indexes:[{columns:["endpoint_id"]},{columns:["target_entity"]},{columns:["schedule_enabled"]}]},{table_name:"integration_runs",feature_set:["integrations"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],bulk_endpoints_enabled:!1,group_name:"Integrations",columns:[{name:"mapping_id",type:"uuid",references:{table:"integrationMappings",column:"id",onDelete:"set null"},comment:"Nullable and NOT cascaded: deleting a mapping must not erase the record that it once rewrote a table."},{name:"target_entity",type:"varchar",length:120},{name:"write_mode",type:"varchar",length:20,enumValues:["upsert","append","replace"]},{name:"status",type:"varchar",length:20,notNull:!0,default:"queued",enumValues:["queued","running","succeeded","failed","cancelled","reverted"],comment:"There is deliberately no 'partial': a run either applied in full or not at all."},{name:"trigger",type:"varchar",length:20,notNull:!0,default:"manual",enumValues:["manual","schedule","api"]},{name:"total_fetched",type:"integer",notNull:!0,default:0},{name:"source_reported_total",type:"integer",comment:"What the source said it had. When this and total_fetched disagree, a destructive run refuses to start."},{name:"created_count",type:"integer",notNull:!0,default:0},{name:"references_created_count",type:"integer",notNull:!0,default:0,comment:"Rows this run added to OTHER tables so its records could point at them."},{name:"accounts_created_count",type:"integer",notNull:!0,default:0,comment:"Logins this run created so its records could be signed in to."},{name:"updated_count",type:"integer",notNull:!0,default:0},{name:"skipped_count",type:"integer",notNull:!0,default:0},{name:"deleted_count",type:"integer",notNull:!0,default:0},{name:"deactivated_count",type:"integer",notNull:!0,default:0},{name:"error_count",type:"integer",notNull:!0,default:0},{name:"external_call_count",type:"integer",notNull:!0,default:0},{name:"issues",type:"jsonb",default:[]},{name:"errors",type:"jsonb",default:[]},{name:"cancel_requested",type:"boolean",notNull:!0,default:!1,comment:"Set by the cancel endpoint; the engine checks it at every batch boundary. A dropped HTTP connection is NOT a cancellation."},{name:"started_at",type:"timestamptz"},{name:"finished_at",type:"timestamptz"},{name:"pre_images_expire_at",type:"timestamptz",comment:"After this, the run can no longer be reverted and the UI says so rather than offering a button that quietly does nothing."},{name:"reverted_at",type:"timestamptz"},{name:"reverted_by",type:"uuid",references:{table:"users",column:"id"}},{name:"reverted_run_id",type:"uuid"}],indexes:[{columns:["mapping_id"]},{columns:["status"]},{columns:["target_entity"]},{columns:["created_at"]}]},{table_name:"integration_run_items",feature_set:["integrations"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],bulk_endpoints_enabled:!1,group_name:"Integrations",columns:[{name:"run_id",type:"uuid",notNull:!0,references:{table:"integrationRuns",column:"id",onDelete:"cascade"}},{name:"target_entity",type:"varchar",length:120,notNull:!0},{name:"row_id",type:"uuid"},{name:"action",type:"varchar",length:20,notNull:!0,enumValues:["create","update","delete","deactivate"]},{name:"before",type:"jsonb",comment:"The row as it stood before this run touched it. This is what makes a successful run reversible; the bulk delete path already produced these rows and threw them away."},{name:"after",type:"jsonb"}],indexes:[{columns:["run_id"]},{columns:["run_id","action"]},{columns:["target_entity","row_id"]}]}];import{batch as batch2,createStore as createStore2}from"h-state";var initialState={connection:{status:"disconnected",clientId:null,subscribedTopics:[],error:null,reconnectAttempt:0},events:[],maxEvents:100},{useStore:usePubSubStore}=createStore2(initialState,{setConnectionStatus:(store)=>(status)=>{store.connection.status=status},setClientId:(store)=>(clientId)=>{store.connection.clientId=clientId},setSubscribedTopics:(store)=>(topics)=>{store.connection.subscribedTopics=topics},setError:(store)=>(error)=>{store.connection.error=error},setReconnectAttempt:(store)=>(attempt)=>{store.connection.reconnectAttempt=attempt},addEvent:(store)=>(event)=>{let updated=[event,...store.events];store.events=updated.slice(0,store.maxEvents)},clearEvents:(store)=>()=>{store.events=[]},reset:(store)=>()=>{batch2(()=>{store.connection.status="disconnected",store.connection.clientId=null,store.connection.subscribedTopics=[],store.connection.error=null,store.connection.reconnectAttempt=0,store.events=[]})}});import{useEffect}from"react";function buildWsUrl(config){let path=config.wsPath||"/api/events/subscribe",topics=(config.topics||["*"]).join(","),query=`?userId=${encodeURIComponent(config.userId)}&topics=${encodeURIComponent(topics)}`;if(config.wsUrl)return`${config.wsUrl.replace(/\/$/,"")}${path}${query}`;if(typeof window>"u")return"";return`${window.location.protocol==="https:"?"wss:":"ws:"}//${window.location.host}${path}${query}`}var connections=new Map,eventIdCounter=0;function log(conn,...args){if(conn.options.debug)console.log("[usePubSub]",...args)}function clearTimers(conn){if(conn.heartbeat)clearInterval(conn.heartbeat),conn.heartbeat=null;if(conn.reconnectTimeout)clearTimeout(conn.reconnectTimeout),conn.reconnectTimeout=null}function detachSocket(conn){let ws=conn.ws;if(!ws)return;if(ws.onopen=null,ws.onmessage=null,ws.onerror=null,ws.onclose=null,ws.readyState===WebSocket.OPEN||ws.readyState===WebSocket.CONNECTING)ws.close();conn.ws=null}function startHeartbeat(conn){if(conn.heartbeat)clearInterval(conn.heartbeat);conn.heartbeat=setInterval(()=>{if(conn.ws?.readyState===WebSocket.OPEN)conn.ws.send(JSON.stringify({type:"ping"}))},conn.options.heartbeatInterval)}var HANDSHAKE_FAILURE_LIMIT=3;function scheduleReconnect(conn){if(!conn.options.autoReconnect)return;if(connections.get(conn.url)!==conn)return;if(conn.reconnectAttempt>=conn.options.maxReconnectAttempts){conn.dispatch.setConnectionStatus("disconnected"),conn.dispatch.setError(Error("Max reconnection attempts reached")),log(conn,"Max reconnect attempts reached");return}let delay=Math.min(conn.options.reconnectBaseDelay*2**conn.reconnectAttempt,conn.options.reconnectMaxDelay);if(conn.reconnectAttempt+=1,conn.dispatch.setConnectionStatus("reconnecting"),conn.dispatch.setReconnectAttempt(conn.reconnectAttempt),log(conn,`Reconnecting in ${delay}ms (attempt ${conn.reconnectAttempt})`),conn.reconnectTimeout)clearTimeout(conn.reconnectTimeout);conn.reconnectTimeout=setTimeout(()=>{if(connections.get(conn.url)===conn)openSocket(conn)},delay)}function handleMessage(conn,raw){let message;try{message=JSON.parse(raw)}catch{log(conn,"Failed to parse message");return}switch(message.type){case"connected":conn.reconnectAttempt=0,conn.dispatch.setConnectionStatus("connected"),conn.dispatch.setClientId(message.clientId),conn.dispatch.setSubscribedTopics(message.subscribedTopics),conn.dispatch.setReconnectAttempt(0),conn.dispatch.setError(null),log(conn,"Connected, clientId:",message.clientId);break;case"subscribed":conn.dispatch.setSubscribedTopics(message.topics),log(conn,"Subscribed to:",message.topics);break;case"event":{if(conn.dispatch.addEvent({id:`evt_${Date.now()}_${eventIdCounter++}`,topic:message.topic,data:message.data,timestamp:message.timestamp,receivedAt:Date.now(),messageId:message.messageId,isRedelivery:message.isRedelivery}),message.messageId&&conn.ws?.readyState===WebSocket.OPEN)conn.ws.send(JSON.stringify({type:"ack",messageId:message.messageId}));break}case"pong":break;case"error":conn.dispatch.setError(Error(message.error)),log(conn,"Server error:",message.error);break}}function openSocket(conn){if(conn.ws?.readyState===WebSocket.OPEN||conn.ws?.readyState===WebSocket.CONNECTING)return;detachSocket(conn),conn.dispatch.setConnectionStatus("connecting"),conn.dispatch.setError(null),log(conn,"Connecting to:",conn.url);let ws=new WebSocket(conn.url);conn.ws=ws;let opened=!1;ws.onopen=()=>{log(conn,"WebSocket opened"),opened=!0,conn.handshakeFailures=0,conn.reconnectAttempt=0,startHeartbeat(conn)},ws.onmessage=(event)=>handleMessage(conn,event.data),ws.onerror=()=>{log(conn,"WebSocket error"),conn.dispatch.setError(Error("WebSocket connection error"))},ws.onclose=(event)=>{if(log(conn,"WebSocket closed",event.code,event.reason),conn.heartbeat)clearInterval(conn.heartbeat),conn.heartbeat=null;if(conn.dispatch.setConnectionStatus("disconnected"),conn.dispatch.setClientId(null),connections.get(conn.url)!==conn)return;if(event.code===4001){conn.dispatch.setConnectionStatus("unauthorized"),conn.dispatch.setError(Error("WebSocket rejected: session is not valid"));return}if(!opened){if(conn.handshakeFailures+=1,conn.handshakeFailures>=HANDSHAKE_FAILURE_LIMIT){conn.dispatch.setConnectionStatus("unauthorized"),conn.dispatch.setError(Error("WebSocket handshake refused \u2014 the session needs refreshing")),log(conn,"Handshake refused repeatedly; not retrying");return}}else conn.handshakeFailures=0;scheduleReconnect(conn)}}function acquire(url,dispatch,options){let conn=connections.get(url);if(!conn)conn={url,ws:null,refCount:0,reconnectAttempt:0,handshakeFailures:0,heartbeat:null,reconnectTimeout:null,dispatch,options},connections.set(url,conn);else conn.dispatch=dispatch,conn.options=options;conn.refCount+=1,openSocket(conn)}function release(url){let conn=connections.get(url);if(!conn)return;if(conn.refCount-=1,conn.refCount>0)return;connections.delete(url),clearTimers(conn),detachSocket(conn),conn.dispatch.setConnectionStatus("disconnected"),conn.dispatch.setClientId(null)}function send(url,payload){let ws=connections.get(url)?.ws;if(ws?.readyState===WebSocket.OPEN)ws.send(JSON.stringify(payload))}function usePubSub(config){let store=usePubSubStore(),url=config.userId?buildWsUrl(config):"";return useEffect(()=>{if(!url)return;let dispatch={setConnectionStatus:store.setConnectionStatus,setClientId:store.setClientId,setSubscribedTopics:store.setSubscribedTopics,setError:store.setError,setReconnectAttempt:store.setReconnectAttempt,addEvent:store.addEvent},options={autoReconnect:config.autoReconnect??!0,maxReconnectAttempts:config.maxReconnectAttempts??10,reconnectBaseDelay:config.reconnectBaseDelay??1000,reconnectMaxDelay:config.reconnectMaxDelay??30000,heartbeatInterval:config.heartbeatInterval??30000,debug:config.debug??!1};return acquire(url,dispatch,options),()=>release(url)},[url]),{isConnected:store.connection.status==="connected",isConnecting:store.connection.status==="connecting"||store.connection.status==="reconnecting",sessionExpired:store.connection.status==="unauthorized",clientId:store.connection.clientId,subscribedTopics:store.connection.subscribedTopics,events:store.events,error:store.connection.error,reconnectAttempt:store.connection.reconnectAttempt,connect:()=>{let conn=connections.get(url);if(conn)openSocket(conn)},disconnect:()=>release(url),subscribe:(topics)=>send(url,{type:"subscribe",topics}),unsubscribe:(topics)=>send(url,{type:"unsubscribe",topics}),clearEvents:store.clearEvents,getEventsByTopic:(topic)=>store.events.filter((e)=>e.topic===topic)}}import{createHash as createHash4,randomUUID as randomUUID9}from"crypto";var import_fast_decode_uri_component=__toESM(require_fast_decode_uri_component(),1);import{Elysia,NotFoundError}from"elysia";var fs,path,isBun=typeof Bun<"u"&&!!Bun.file;function getBuiltinModule(){if(fs||(fs=process.getBuiltinModule("fs/promises")),path||(path=process.getBuiltinModule("path")),!path){console.warn("@elysiajs/static require path to be available.");return}return[fs,path]}async function listHTMLFiles(dir){if(fs||getBuiltinModule(),isBun){let glob=new Bun.Glob("**/*.html"),files=[];for await(let file of glob.scan(dir))files.push(path.join(dir,file));return files}return[]}async function listFiles(dir){if(fs||getBuiltinModule(),isBun){let glob=new Bun.Glob("**/*"),files2=[];for await(let file of glob.scan(dir))files2.push(path.join(dir,file));return files2}let files=await fs.readdir(dir).catch(()=>[]);return(await Promise.all(files.map(async(name)=>{let file=dir+path.sep+name,stats=await fs.stat(file).catch(()=>null);return stats?stats.isDirectory()?await listFiles(file):[path.resolve(dir,file)]:[]}))).flat()}function fileExists(path2){return fs||getBuiltinModule(),fs.stat(path2).then(()=>!0,()=>!1)}class LRUCache{constructor(max=250,ttl=10800){this.max=max,this.ttl=ttl,this.map=new Map}get(key){let entry=this.map.get(key);if(entry)return entry[1]<=Date.now()?void this.delete(key):(this.map.delete(key),this.map.set(key,entry),entry[0])}set(key,value){if(this.interval||(this.interval=setInterval(()=>{let now=Date.now();for(let[key2,entry]of this.map)entry[1]<=now&&this.map.delete(key2)},this.ttl)),this.map.has(key))this.map.delete(key);else if(this.map.size>=this.max){let oldestKey=this.map.keys().next().value;oldestKey!==void 0&&this.delete(oldestKey)}this.map.set(key,[value,Date.now()+this.ttl*1000])}delete(key){this.map.get(key)&&this.map.delete(key)}clear(){this.map.clear()}size(){return this.map.size}[Symbol.dispose](){this.interval&&clearInterval(this.interval)}}function isCached(headers,etag,filePath){if(headers["cache-control"]&&/no-cache|no-store/.test(headers["cache-control"]))return!1;if("if-none-match"in headers){let ifNoneMatch=headers["if-none-match"];return ifNoneMatch==="*"?!0:ifNoneMatch===null||typeof etag!="string"?!1:ifNoneMatch===etag}if(headers["if-modified-since"]){let ifModifiedSince=headers["if-modified-since"];try{return fs.stat(filePath).then((stat)=>{if(stat.mtime!==void 0&&stat.mtime.getTime()<=Date.parse(ifModifiedSince))return!0})}catch{}}return!1}var Crypto;function getFile(path2){return isBun?Bun.file(path2):(fs||getBuiltinModule(),fs.readFile(path2))}async function generateETag(file){return isBun?new Bun.CryptoHasher("md5").update(await file.arrayBuffer()).digest("base64"):(Crypto||(Crypto=process.getBuiltinModule("crypto")),Crypto?Crypto.createHash("md5").update(file).digest("base64"):void console.warn("[@elysiajs/static] crypto is required to generate etag."))}var isNotEmpty=(obj)=>{if(!obj)return!1;for(let _ in obj)return!0;return!1};async function staticPlugin({assets="public",prefix="/public",staticLimit=1024,alwaysStatic=!1,ignorePatterns=[".DS_Store",".git",".env"],headers:initialHeaders,maxAge=86400,directive="public",etag:useETag=!0,extension=!0,indexHTML=!0,decodeURI,silent}={}){if(typeof process>"u"||typeof process.getBuiltinModule>"u")return silent||console.warn("[@elysiajs/static] require process.getBuiltinModule. Static plugin is disabled"),new Elysia;let builtinModule=getBuiltinModule();if(!builtinModule)return new Elysia;let[fs2,path2]=builtinModule,normalizePath=path2.sep!=="/"?(p)=>p.replace(/\\/g,"/"):(p)=>p,fileCache=new LRUCache;prefix===path2.sep&&(prefix="");let assetsDir=path2.resolve(assets),shouldIgnore=ignorePatterns.length?(file)=>ignorePatterns.find((pattern)=>typeof pattern=="string"?pattern.includes(file):pattern.test(file)):()=>!1,app=new Elysia({name:"static",seed:prefix});if(alwaysStatic){let files=await listFiles(path2.resolve(assets));if(files.length<=staticLimit)for(let absolutePath of files){let handleCache2=function({headers:requestHeaders}){if(etag){let cached=isCached(requestHeaders,etag,absolutePath);if(cached===!0)return new Response(null,{status:304,headers:isNotEmpty(initialHeaders)?initialHeaders:void 0});if(cached!==!1){let cache2=fileCache.get(pathName);return cache2?cache2.clone():cached.then((cached2)=>{if(cached2)return new Response(null,{status:304,headers:initialHeaders||void 0});let response2=new Response(file,{headers:Object.assign({"Cache-Control":maxAge?`${directive}, max-age=${maxAge}`:directive},initialHeaders,etag?{Etag:etag}:{})});return fileCache.set(prefix,response2),response2.clone()})}}let cache=fileCache.get(pathName);if(cache)return cache.clone();let response=new Response(file,{headers:Object.assign({"Cache-Control":maxAge?`${directive}, max-age=${maxAge}`:directive},initialHeaders,etag?{Etag:etag}:{})});return fileCache.set(pathName,response),response.clone()};var handleCache=handleCache2;if(!absolutePath||shouldIgnore(absolutePath))continue;let relativePath=absolutePath.replace(assetsDir,"");decodeURI&&(relativePath=import_fast_decode_uri_component.default(relativePath)??relativePath);let pathName=normalizePath(path2.join(prefix,relativePath));if(isBun&&absolutePath.endsWith(".html")){let htmlBundle=await import(absolutePath);app.get(pathName,htmlBundle.default),indexHTML&&pathName.endsWith("/index.html")&&app.get(pathName.replace("/index.html",""),htmlBundle.default);continue}extension||(pathName=normalizePath(pathName.slice(0,pathName.lastIndexOf("."))));let file=isBun?getFile(absolutePath):await getFile(absolutePath);if(!file)return silent||console.warn(`[@elysiajs/static] Failed to load file: ${absolutePath}`),new Elysia;let etag=await generateETag(file);app.get(pathName,useETag?handleCache2:new Response(file,isNotEmpty(initialHeaders)?{headers:initialHeaders}:void 0)),indexHTML&&pathName.endsWith("/index.html")&&app.get(pathName.replace("/index.html",""),useETag?handleCache2:new Response(file,isNotEmpty(initialHeaders)?{headers:initialHeaders}:void 0))}return app}if(!(`GET_${prefix}/*`in app.routeTree)){if(isBun){let htmls=await listHTMLFiles(path2.resolve(assets));for(let absolutePath of htmls){if(!absolutePath||shouldIgnore(absolutePath))continue;let relativePath=absolutePath.replace(assetsDir,""),pathName=normalizePath(path2.join(prefix,relativePath)),htmlBundle=await import(absolutePath);app.get(pathName,htmlBundle.default),indexHTML&&pathName.endsWith("/index.html")&&app.get(pathName.replace("/index.html",""),htmlBundle.default)}}app.onError(()=>{}).get(`${prefix.endsWith("/")?prefix.slice(0,-1):prefix}/*`,async({params,headers:requestHeaders})=>{let pathName=normalizePath(path2.join(assets,decodeURI?import_fast_decode_uri_component.default(params["*"])??params["*"]:params["*"]));if(shouldIgnore(pathName))throw new NotFoundError;let cache=fileCache.get(pathName);if(cache)return cache.clone();try{let fileStat=await fs2.stat(pathName).catch(()=>null);if(!fileStat)throw new NotFoundError;if(!indexHTML&&fileStat.isDirectory())throw new NotFoundError;let file;if(!isBun&&indexHTML){let htmlPath=path2.join(pathName,"index.html"),cache2=fileCache.get(htmlPath);if(cache2)return cache2.clone();await fileExists(htmlPath)&&(file=await getFile(htmlPath))}if(!file&&!fileStat.isDirectory()&&await fileExists(pathName))file=await getFile(pathName);else throw new NotFoundError;if(!useETag)return new Response(file,isNotEmpty(initialHeaders)?{headers:initialHeaders}:void 0);let etag=await generateETag(file);if(etag&&await isCached(requestHeaders,etag,pathName))return new Response(null,{status:304});let response=new Response(file,{headers:Object.assign({"Cache-Control":maxAge?`${directive}, max-age=${maxAge}`:directive},initialHeaders,etag?{Etag:etag}:{})});return fileCache.set(pathName,response),response.clone()}catch(error){throw error instanceof NotFoundError?error:(silent||console.error("[@elysiajs/static]",error),new NotFoundError)}})}return app}import{pushSchema}from"drizzle-kit/api";import{and as and23,desc as desc7,eq as eq63,lt as lt3,ne as ne3,sql as sql13}from"drizzle-orm";import{drizzle as drizzle2}from"drizzle-orm/node-postgres";import{pgSchema as pgSchema2}from"drizzle-orm/pg-core";import Elysia52 from"elysia";import{join as join3}from"path";class LiveStorageProvider{resolve;constructor(resolve){this.resolve=resolve}get kind(){return this.resolve().kind}get describe(){return this.resolve().describe}isAvailable(){return this.resolve().isAvailable()}exists(relativePath){return this.resolve().exists(relativePath)}stat(relativePath){return this.resolve().stat(relativePath)}read(relativePath){return this.resolve().read(relativePath)}write(relativePath,data){return this.resolve().write(relativePath,data)}delete(relativePath){return this.resolve().delete(relativePath)}ensureDir(relativeDir){return this.resolve().ensureDir(relativeDir)}list(relativeDir){return this.resolve().list(relativeDir)}localPath(relativePath){return this.resolve().localPath(relativePath)}close(){return this.resolve().close()}}import{mkdir,readdir,stat,unlink}from"fs/promises";import{dirname,join}from"path";function normalizeRelativePath(relativePath){let cleaned=relativePath.replace(/\\/g,"/").replace(/^\/+/,""),segments=[];for(let segment of cleaned.split("/")){if(!segment||segment===".")continue;if(segment==="..")throw Error(`Path traversal rejected: ${relativePath}`);segments.push(segment)}return segments.join("/")}class LocalStorageProvider{kind="local";describe;basePath;constructor(basePath,_deps){this.basePath=basePath,this.describe=`local:${basePath}`}resolve(relativePath){return join(this.basePath,normalizeRelativePath(relativePath))}async isAvailable(){try{return await mkdir(this.basePath,{recursive:!0}),!0}catch{return!1}}async exists(relativePath){return Bun.file(this.resolve(relativePath)).exists()}async stat(relativePath){try{let info=await stat(this.resolve(relativePath));return{size:info.size,modifiedAt:info.mtime,isDirectory:info.isDirectory()}}catch{return null}}async read(relativePath){let file=Bun.file(this.resolve(relativePath));if(!await file.exists())return null;return Buffer.from(await file.arrayBuffer())}async write(relativePath,data){let full=this.resolve(relativePath);await mkdir(dirname(full),{recursive:!0}),await Bun.write(full,data)}async delete(relativePath){try{return await unlink(this.resolve(relativePath)),!0}catch{return!1}}async ensureDir(relativeDir){await mkdir(this.resolve(relativeDir),{recursive:!0})}async list(relativeDir){try{return await readdir(this.resolve(relativeDir))}catch{return[]}}async localPath(relativePath){let full=this.resolve(relativePath);return await Bun.file(full).exists()?full:null}async close(){}}import{stat as fsStat,mkdir as mkdir2,rename,unlink as unlink2}from"fs/promises";import{dirname as dirname2,join as join2}from"path";var DEFAULT_TIMEOUT_MS=15000,DEFAULT_CACHE_TTL_SECONDS=300;class SmbStorageProvider{kind="smb";describe;getConfig;logger;client=null;clientFingerprint="";cacheDir;cacheTtlMs;cacheEnabled;inFlight=new Map;constructor(getConfig,deps,defaultCacheDir){this.getConfig=getConfig,this.logger=deps.logger;let config=getConfig();this.cacheEnabled=config.cache?.enabled!==!1,this.cacheDir=config.cache?.path||defaultCacheDir,this.cacheTtlMs=(config.cache?.ttlSeconds??DEFAULT_CACHE_TTL_SECONDS)*1000,this.describe=`smb://${config.host}/${config.share}${config.basePath?`/${config.basePath}`:""}`}async getClient(){let{host,share,domain,username,password,port,timeoutMs}=this.getConfig(),fingerprint=`${host}|${share}|${domain}|${username}|${password}|${port}`;if(this.client&&fingerprint===this.clientFingerprint)return this.client;if(this.client){try{this.client.disconnect()}catch{}this.client=null}let imported=await Promise.resolve().then(() => __toESM(require_smb2(),1)).catch(()=>{throw Error('storage.provider is "smb" but the optional @marsaud/smb2 dependency is not installed \u2014 run: bun add @marsaud/smb2')}),SMB2=imported.default??imported;return this.client=new SMB2({share:`\\\\${host}\\${share}`,domain:domain||"WORKGROUP",username,password,port:port??445,autoCloseTimeout:timeoutMs??DEFAULT_TIMEOUT_MS}),this.clientFingerprint=fingerprint,this.client}async call(fn){let client=await this.getClient(),timeoutMs=this.getConfig().timeoutMs??DEFAULT_TIMEOUT_MS;return new Promise((resolve,reject)=>{let settled=!1,timer=setTimeout(()=>{if(settled)return;settled=!0,reject(Error(`SMB operation timed out after ${timeoutMs}ms (${this.describe})`))},timeoutMs);fn(client,(err,value)=>{if(settled)return;if(settled=!0,clearTimeout(timer),err)reject(err);else resolve(value)})})}remotePath(relativePath){let normalized=normalizeRelativePath(relativePath),configuredBase=this.getConfig().basePath,base=configuredBase?normalizeRelativePath(configuredBase):"";return(base?`${base}/${normalized}`:normalized).replace(/\//g,"\\")}cachePath(relativePath){return join2(this.cacheDir,normalizeRelativePath(relativePath))}async isAvailable(){try{return await this.call((client,cb)=>client.readdir(this.getConfig().basePath?this.remotePath(""):"",cb)),!0}catch(error){return this.logger.warn("[Storage/SMB] Share is not reachable",{target:this.describe,error:error instanceof Error?error.message:String(error)}),!1}}async exists(relativePath){try{return await this.call((client,cb)=>client.exists(this.remotePath(relativePath),cb))}catch{return!1}}async stat(relativePath){try{let info=await this.call((client,cb)=>client.stat(this.remotePath(relativePath),cb));return{size:Number(info.size),modifiedAt:new Date(info.mtime),isDirectory:typeof info.isDirectory==="function"?info.isDirectory():await this.looksLikeDirectory(relativePath)}}catch{return null}}async read(relativePath){try{return await this.call((client,cb)=>client.readFile(this.remotePath(relativePath),cb))}catch(error){return this.logger.warn("[Storage/SMB] Read failed",{path:relativePath,error:error instanceof Error?error.message:String(error)}),null}}async write(relativePath,data){let parent=normalizeRelativePath(relativePath).split("/").slice(0,-1).join("/");if(parent)await this.ensureDir(parent);let payload=typeof data==="string"?Buffer.from(data,"utf-8"):Buffer.from(data);if(await this.call((client,cb)=>client.writeFile(this.remotePath(relativePath),payload,cb)),this.cacheEnabled){let target=this.cachePath(relativePath);await mkdir2(dirname2(target),{recursive:!0}).catch(()=>{}),await Bun.write(target,payload).catch(()=>{})}}async delete(relativePath){try{if(await this.call((client,cb)=>client.unlink(this.remotePath(relativePath),cb)),this.cacheEnabled)await unlink2(this.cachePath(relativePath)).catch(()=>{});return!0}catch{return!1}}async ensureDir(relativeDir){let normalized=normalizeRelativePath(relativeDir);if(!normalized)return;let segments=normalized.split("/");for(let i=1;i<=segments.length;i++){let partial=segments.slice(0,i).join("/");try{await this.call((client,cb)=>client.mkdir(this.remotePath(partial),cb))}catch{}}}async looksLikeDirectory(relativePath){try{return await this.call((client,cb)=>client.readdir(this.remotePath(relativePath),cb)),!0}catch{return!1}}async list(relativeDir){try{return await this.call((client,cb)=>client.readdir(this.remotePath(relativeDir),cb))}catch{return[]}}async localPath(relativePath){if(!this.cacheEnabled)return null;let target=this.cachePath(relativePath),cached=await fsStat(target).catch(()=>null);if(cached&&Date.now()-cached.mtimeMs<this.cacheTtlMs)return target;let pending=this.inFlight.get(target);if(pending)return pending;let download=(async()=>{let data=await this.read(relativePath);if(!data)return null;await mkdir2(dirname2(target),{recursive:!0}).catch(()=>{});let tmp=`${target}.${process.pid}.tmp`;try{return await Bun.write(tmp,data),await rename(tmp,target),target}catch(error){return await unlink2(tmp).catch(()=>{}),this.logger.warn("[Storage/SMB] Could not cache file locally",{path:relativePath,error:error instanceof Error?error.message:String(error)}),null}})().finally(()=>{this.inFlight.delete(target)});return this.inFlight.set(target,download),download}async close(){try{this.client?.disconnect()}catch{}this.client=null}}var DEFAULT_EXCLUDES=[".cache",".tmp","lost+found"];async function migrateStorage(options,deps){let{from,to,onProgress}=options,exclude=new Set([...DEFAULT_EXCLUDES,...options.exclude??[]]),maxFiles=options.maxFiles??50000,report={copied:0,skipped:0,failed:0,bytes:0,failures:[],truncated:!1},walk=async(dir)=>{if(report.truncated)return;let entries=await from.list(dir);for(let entry of entries){if(report.truncated)return;if(!entry||entry==="."||entry==="..")continue;let relative=dir?`${dir}/${entry}`:entry;if(exclude.has(entry))continue;let info=await from.stat(relative);if(!info){if(report.failed+=1,report.failures.length<50)report.failures.push(relative);continue}if(info.isDirectory){await walk(relative);continue}if(report.copied+report.skipped>=maxFiles){report.truncated=!0;return}if(await to.exists(relative)){report.skipped+=1;continue}try{let bytes=await from.read(relative);if(!bytes){if(report.failed+=1,report.failures.length<50)report.failures.push(relative);continue}let parent=relative.includes("/")?relative.slice(0,relative.lastIndexOf("/")):"";if(parent)await to.ensureDir(parent);await to.write(relative,bytes),report.copied+=1,report.bytes+=bytes.length,onProgress?.(report.copied,relative)}catch(error){if(report.failed+=1,report.failures.length<50)report.failures.push(relative);deps.logger.warn("[Storage] Migration copy failed",{path:relative,error:error instanceof Error?error.message:String(error)})}}};return await walk(""),deps.logger.info("[Storage] Migration finished",{from:from.describe,to:to.describe,copied:report.copied,skipped:report.skipped,failed:report.failed,truncated:report.truncated}),report}function parseSmbUrl(value){let raw=(value??"").trim();if(!raw)return{host:"",share:""};let withoutScheme=raw.replace(/^smb:\/\//i,"").replace(/^\\\\/,"").replace(/\\/g,"/"),[host="",share="",...rest]=withoutScheme.split("/").filter(Boolean);return{host,share,basePath:rest.length>0?rest.join("/"):void 0}}function createStorageProvider(options,deps){let{basePath,smb,resolveCredential}=options,setting=(key,configValue)=>resolveCredential?.("storage.smb",key,configValue)??configValue,resolveSmbConfig=()=>{let fromUrl=parseSmbUrl(setting("url"));return{...smb,host:fromUrl.host||setting("host",smb?.host)||"",share:fromUrl.share||setting("share",smb?.share)||"",basePath:fromUrl.basePath??setting("base_path",smb?.basePath),domain:setting("domain",smb?.domain),username:setting("username",smb?.username),password:setting("password",smb?.password)}},resolveKind=()=>{let chosen=resolveCredential?.("storage","provider",options.provider);return chosen==="smb"?"smb":chosen==="local"?"local":options.provider??"local"},local=new LocalStorageProvider(basePath,deps),smbProvider=null,smbSignature="",warnedIncomplete=!1;return new LiveStorageProvider(()=>{if(resolveKind()!=="smb")return local;let config=resolveSmbConfig();if(!config.host||!config.share){if(!warnedIncomplete)warnedIncomplete=!0,deps.logger.error('[Storage] provider is "smb" but the host/share are not set \u2014 using local storage until they are');return local}warnedIncomplete=!1;let signature=JSON.stringify([config.host,config.share,config.basePath,config.domain,config.username,config.password,config.port]);if(!smbProvider||signature!==smbSignature)smbProvider?.close(),smbProvider=new SmbStorageProvider(resolveSmbConfig,deps,join3(basePath,".cache","smb")),smbSignature=signature,deps.logger.info("[Storage] SMB target configured",{target:smbProvider.describe});return smbProvider})}init_Services();init_ApiKey();init_Middleware();init_Captcha();init_Domain();init_ServerLogBuffer();init_transports();init_Secrets();init_lifetime();import{and as and10,desc as desc3,eq as eq16,inArray as inArray4}from"drizzle-orm";var DEFAULT_CHAT_CONFIG={enabled:!1,basePath:"/chat",groupsEnabled:!0,maxGroupParticipants:256,maxMessageLength:8000,editingEnabled:!0,deletionEnabled:!0,typingIndicators:!0,readReceipts:!0,presence:!0,realtimeTopicPrefix:"chat",messagePageSize:50,moderatorRoles:[],attachments:{enabled:!0,maxPerMessage:10,maxFileSizeBytes:null,allowedMimeTypes:[]}};function mergeChatConfig(input){let base=DEFAULT_CHAT_CONFIG;if(!input)return base;return{enabled:input.enabled??base.enabled,basePath:input.basePath??base.basePath,groupsEnabled:input.groupsEnabled??base.groupsEnabled,maxGroupParticipants:input.maxGroupParticipants??base.maxGroupParticipants,maxMessageLength:input.maxMessageLength??base.maxMessageLength,editingEnabled:input.editingEnabled??base.editingEnabled,deletionEnabled:input.deletionEnabled??base.deletionEnabled,typingIndicators:input.typingIndicators??base.typingIndicators,readReceipts:input.readReceipts??base.readReceipts,presence:input.presence??base.presence,realtimeTopicPrefix:input.realtimeTopicPrefix??base.realtimeTopicPrefix,messagePageSize:input.messagePageSize??base.messagePageSize,moderatorRoles:input.moderatorRoles??base.moderatorRoles,attachments:{enabled:input.attachments?.enabled??base.attachments.enabled,maxPerMessage:input.attachments?.maxPerMessage??base.attachments.maxPerMessage,maxFileSizeBytes:input.attachments?.maxFileSizeBytes??base.attachments.maxFileSizeBytes,allowedMimeTypes:input.attachments?.allowedMimeTypes??base.attachments.allowedMimeTypes}}}function getCol(table,col7){return table[col7]}function getTable(schemaTables,name2,logger2){return resolveSchemaTable(schemaTables,name2,logger2)}function computeDirectKey(userA,userB){return[userA,userB].sort().join(":")}function kindFromMime(mime){if(!mime)return"file";if(mime.startsWith("image/"))return"image";if(mime.startsWith("video/"))return"video";if(mime.startsWith("audio/"))return"audio";return"file"}function str3(value){return typeof value==="string"?value:null}function num2(value){return typeof value==="number"?value:null}function date(value){if(value instanceof Date)return value;if(typeof value==="string")return new Date(value);return null}function cdnUrl(cdnBasePath,fileId){if(!fileId)return null;return`${cdnBasePath}/${fileId}`}function mapConversation(row,cdnBasePath){let avatarFileId=str3(row.avatarFileId);return{id:String(row.id),type:str3(row.type)??"direct",title:str3(row.title),description:str3(row.description),avatarFileId,avatarUrl:cdnUrl(cdnBasePath,avatarFileId),directKey:str3(row.directKey),lastMessageAt:date(row.lastMessageAt),lastMessagePreview:str3(row.lastMessagePreview),lastMessageSenderId:str3(row.lastMessageSenderId),createdBy:str3(row.createdBy),createdAt:date(row.createdAt)??new Date(0),updatedAt:date(row.updatedAt)??new Date(0),isActive:row.isActive!==!1}}function mapParticipant(row){return{id:String(row.id),conversationId:String(row.conversationId),userId:String(row.userId),role:str3(row.role)??"member",lastReadMessageId:str3(row.lastReadMessageId),lastReadAt:date(row.lastReadAt),unreadCount:num2(row.unreadCount)??0,muted:row.muted===!0,mutedUntil:date(row.mutedUntil),notificationsEnabled:row.notificationsEnabled!==!1,leftAt:date(row.leftAt),joinedAt:date(row.createdAt)??new Date(0)}}function mapAttachment(row,cdnBasePath){let fileId=String(row.fileId);return{id:String(row.id),messageId:String(row.messageId),conversationId:String(row.conversationId),fileId,kind:str3(row.kind)??"file",originalName:str3(row.originalName),mimeType:str3(row.mimeType),size:num2(row.size),width:num2(row.width),height:num2(row.height),duration:num2(row.duration),url:`${cdnBasePath}/${fileId}`}}function mapMessage(row,attachments){let metadata=row.metadata;return{id:String(row.id),conversationId:String(row.conversationId),senderId:str3(row.senderId),content:str3(row.content),contentType:str3(row.contentType)??"text",replyToId:str3(row.replyToId),metadata:metadata&&typeof metadata==="object"?metadata:null,clientMessageId:str3(row.clientMessageId),editedAt:date(row.editedAt),deletedAt:date(row.deletedAt),createdAt:date(row.createdAt)??new Date(0),updatedAt:date(row.updatedAt)??new Date(0),attachments}}function buildPreview(content,contentType,attachmentCount){if(content&&content.trim().length>0){let trimmed=content.trim();return trimmed.length>280?`${trimmed.slice(0,277)}...`:trimmed}if(attachmentCount>0){if(contentType==="image")return attachmentCount>1?`${attachmentCount} photos`:"Photo";if(contentType==="video")return attachmentCount>1?`${attachmentCount} videos`:"Video";if(contentType==="audio")return"Audio";return attachmentCount>1?`${attachmentCount} files`:"File"}if(contentType==="system")return"System message";return""}import{and as and9,eq as eq15,inArray as inArray3}from"drizzle-orm";class ChatError extends Error{code;constructor(code,message){super(message);this.code=code,this.name="ChatError"}}function resolveChatTables(ctx){let conversations=getTable(ctx.schemaTables,"chat_conversations",ctx.logger),participants=getTable(ctx.schemaTables,"chat_participants",ctx.logger),messages=getTable(ctx.schemaTables,"chat_messages",ctx.logger);if(!conversations||!participants||!messages)throw new ChatError("disabled","Chat tables are not available in this schema");let attachments=getTable(ctx.schemaTables,"chat_message_attachments")??null,files=getTable(ctx.schemaTables,"files")??null;return{conversations,participants,messages,attachments,files}}function chatTopic(ctx){return ctx.config.realtimeTopicPrefix||"chat"}async function getConversationRow(ctx,tables,conversationId){return(await ctx.db.select().from(tables.conversations).where(eq15(getCol(tables.conversations,"id"),conversationId)).limit(1))[0]??null}async function getParticipant(ctx,tables,conversationId,userId){let row=(await ctx.db.select().from(tables.participants).where(and9(eq15(getCol(tables.participants,"conversationId"),conversationId),eq15(getCol(tables.participants,"userId"),userId))).limit(1))[0];return row?mapParticipant(row):null}async function requireActiveMembership(ctx,tables,conversationId,userId){let participant=await getParticipant(ctx,tables,conversationId,userId);if(!participant||participant.leftAt)throw new ChatError("forbidden","You are not a participant of this conversation");return participant}async function listParticipants(ctx,tables,conversationId,includeLeft=!1){let all=(await ctx.db.select().from(tables.participants).where(eq15(getCol(tables.participants,"conversationId"),conversationId))).map(mapParticipant);return includeLeft?all:all.filter((p)=>!p.leftAt)}async function assertUsersExist(ctx,userIds){let unique=[...new Set(userIds)];if(unique.length===0)return;let usersTable=getTable(ctx.schemaTables,"users",ctx.logger);if(!usersTable)throw new ChatError("disabled","Users table is not available in this schema");let rows=await ctx.db.select({id:getCol(usersTable,"id")}).from(usersTable).where(inArray3(getCol(usersTable,"id"),unique)),found=new Set(rows.map((r)=>r.id));for(let id of unique)if(!found.has(id))throw new ChatError("not_found",`User ${id} does not exist`)}function deliverToParticipants(ctx,participants,event,exceptUserId){if(!ctx.broadcaster)return;let topic=chatTopic(ctx);for(let participant of participants){if(participant.leftAt)continue;if(exceptUserId&&participant.userId===exceptUserId)continue;ctx.broadcaster.broadcastToUser(participant.userId,topic,event)}}async function buildSummary(ctx,tables,conversationRow,userId,participantsOverride){let conversation=mapConversation(conversationRow,ctx.cdnBasePath),participants=participantsOverride??await listParticipants(ctx,tables,conversation.id),myParticipant=participants.find((p)=>p.userId===userId)??null;return{...conversation,participants,myParticipant,unreadCount:myParticipant?.unreadCount??0}}async function getOrCreateDirect(ctx,params){let tables=resolveChatTables(ctx),{userId,targetUserId}=params;if(!targetUserId||targetUserId===userId)throw new ChatError("validation","A different target user is required");await assertUsersExist(ctx,[targetUserId]);let directKey=computeDirectKey(userId,targetUserId),existing=(await ctx.db.select().from(tables.conversations).where(eq16(getCol(tables.conversations,"directKey"),directKey)).limit(1))[0];if(existing)return await rejoinIfNeeded(ctx,tables,String(existing.id),[userId,targetUserId]),buildSummary(ctx,tables,existing,userId);let now=new Date,conversationRow;try{conversationRow=(await ctx.db.insert(tables.conversations).values({type:"direct",directKey,createdBy:userId,lastMessageAt:now,lastMessagePreview:""}).returning())[0]}catch(_err){let raced=(await ctx.db.select().from(tables.conversations).where(eq16(getCol(tables.conversations,"directKey"),directKey)).limit(1))[0];if(!raced)throw new ChatError("conflict","Failed to create direct conversation");return await rejoinIfNeeded(ctx,tables,String(raced.id),[userId,targetUserId]),buildSummary(ctx,tables,raced,userId)}let conversationId=String(conversationRow.id);await ctx.db.insert(tables.participants).values([{conversationId,userId,role:"member",createdBy:userId},{conversationId,userId:targetUserId,role:"member",createdBy:userId}]);let summary=await buildSummary(ctx,tables,conversationRow,userId);return deliverToParticipants(ctx,summary.participants,{type:"conversation.created",conversationId,conversation:summary},userId),summary}async function createGroup(ctx,params){if(!ctx.config.groupsEnabled)throw new ChatError("disabled","Group conversations are disabled");let tables=resolveChatTables(ctx),{creatorId,title}=params;if(!title||title.trim().length===0)throw new ChatError("validation","A group title is required");let memberIds=[...new Set([creatorId,...params.participantIds])];if(memberIds.length>ctx.config.maxGroupParticipants)throw new ChatError("validation",`A group cannot exceed ${ctx.config.maxGroupParticipants} participants`);if(await assertUsersExist(ctx,memberIds),params.avatarFileId){if(!tables.files)throw new ChatError("disabled","Avatar files require storage to be enabled");let avatarRow=(await ctx.db.select().from(tables.files).where(eq16(getCol(tables.files,"id"),params.avatarFileId)).limit(1))[0],owner=avatarRow?String(avatarRow.uploadedBy??avatarRow.createdBy??""):"";if(!avatarRow||owner!==creatorId)throw new ChatError("forbidden","Avatar file is not owned by the creator")}let now=new Date,conversationRow=(await ctx.db.insert(tables.conversations).values({type:"group",title:title.trim(),description:params.description??null,avatarFileId:params.avatarFileId??null,createdBy:creatorId,lastMessageAt:now,lastMessagePreview:""}).returning())[0],conversationId=String(conversationRow.id);await ctx.db.insert(tables.participants).values(memberIds.map((memberId)=>({conversationId,userId:memberId,role:memberId===creatorId?"owner":"member",createdBy:creatorId})));let summary=await buildSummary(ctx,tables,conversationRow,creatorId);return deliverToParticipants(ctx,summary.participants,{type:"conversation.created",conversationId,conversation:summary},creatorId),summary}async function listConversations(ctx,params){let tables=resolveChatTables(ctx),limit=Math.min(Math.max(params.limit??30,1),100),offset=Math.max(params.offset??0,0),myParticipants=(await ctx.db.select().from(tables.participants).where(eq16(getCol(tables.participants,"userId"),params.userId))).map(mapParticipant).filter((p)=>!p.leftAt);if(myParticipants.length===0)return[];let conversationIds=myParticipants.map((p)=>p.conversationId),pageRows=await ctx.db.select().from(tables.conversations).where(and10(inArray4(getCol(tables.conversations,"id"),conversationIds),eq16(getCol(tables.conversations,"isActive"),!0))).orderBy(desc3(getCol(tables.conversations,"lastMessageAt"))).limit(limit).offset(offset);if(pageRows.length===0)return[];let pageIds=pageRows.map((r)=>String(r.id)),participantRows=await ctx.db.select().from(tables.participants).where(inArray4(getCol(tables.participants,"conversationId"),pageIds)),byConversation=new Map;for(let row of participantRows){let mapped=mapParticipant(row);if(mapped.leftAt)continue;let list2=byConversation.get(mapped.conversationId)??[];list2.push(mapped),byConversation.set(mapped.conversationId,list2)}let summaries=[];for(let row of pageRows){let id=String(row.id);summaries.push(await buildSummary(ctx,tables,row,params.userId,byConversation.get(id)??[]))}return summaries}async function getConversation(ctx,conversationId,userId){let tables=resolveChatTables(ctx);await requireActiveMembership(ctx,tables,conversationId,userId);let row=await getConversationRow(ctx,tables,conversationId);if(!row)throw new ChatError("not_found","Conversation not found");return buildSummary(ctx,tables,row,userId)}async function rejoinIfNeeded(ctx,tables,conversationId,userIds){for(let userId of userIds){let participant=await getParticipant(ctx,tables,conversationId,userId);if(!participant)await ctx.db.insert(tables.participants).values({conversationId,userId,role:"member",createdBy:userId});else if(participant.leftAt)await ctx.db.update(tables.participants).set({leftAt:null}).where(eq16(getCol(tables.participants,"id"),participant.id))}}function assertCanManage(actor){if(actor.role!=="owner"&&actor.role!=="admin")throw new ChatError("forbidden","Only group admins can manage participants")}async function addParticipants(ctx,conversationId,actorId,userIds){let tables=resolveChatTables(ctx),conversation=await getConversationRow(ctx,tables,conversationId);if(!conversation)throw new ChatError("not_found","Conversation not found");if(mapConversation(conversation,ctx.cdnBasePath).type!=="group")throw new ChatError("validation","Participants can only be managed in group conversations");let actor=await requireActiveMembership(ctx,tables,conversationId,actorId);assertCanManage(actor);let toAdd=[...new Set(userIds)];await assertUsersExist(ctx,toAdd);let current=await listParticipants(ctx,tables,conversationId,!0),activeCount=current.filter((p)=>!p.leftAt).length,newOnes=toAdd.filter((id)=>!current.some((p)=>p.userId===id&&!p.leftAt));if(activeCount+newOnes.length>ctx.config.maxGroupParticipants)throw new ChatError("validation","Group participant limit exceeded");for(let userId of toAdd)await rejoinIfNeeded(ctx,tables,conversationId,[userId]);let participants=await listParticipants(ctx,tables,conversationId);return deliverToParticipants(ctx,participants,{type:"participant.added",conversationId,userIds:toAdd,by:actorId}),participants}async function removeParticipant(ctx,conversationId,actorId,targetUserId){let tables=resolveChatTables(ctx),actor=await requireActiveMembership(ctx,tables,conversationId,actorId);if(actorId!==targetUserId)assertCanManage(actor);let target2=await getParticipant(ctx,tables,conversationId,targetUserId);if(!target2||target2.leftAt)throw new ChatError("not_found","Participant not found in conversation");await ctx.db.update(tables.participants).set({leftAt:new Date}).where(eq16(getCol(tables.participants,"id"),target2.id));let participants=await listParticipants(ctx,tables,conversationId),event={type:"participant.removed",conversationId,userId:targetUserId,by:actorId};if(deliverToParticipants(ctx,participants,event),ctx.broadcaster)ctx.broadcaster.broadcastToUser(targetUserId,ctx.config.realtimeTopicPrefix||"chat",event)}import{and as and11,desc as desc4,eq as eq17,inArray as inArray5,isNull,lt,ne,sql as sql6}from"drizzle-orm";async function loadAttachments(ctx,tables,messageIds){let grouped=new Map;if(!tables.attachments||messageIds.length===0)return grouped;let rows=await ctx.db.select().from(tables.attachments).where(inArray5(getCol(tables.attachments,"messageId"),messageIds));for(let row of rows){let attachment=mapAttachment(row,ctx.cdnBasePath),list2=grouped.get(attachment.messageId)??[];list2.push(attachment),grouped.set(attachment.messageId,list2)}return grouped}function inferContentType(explicit,attachments){if(explicit)return explicit;if(attachments.length===0)return"text";let kind=attachments[0]?.kind;if(kind==="image")return"image";if(kind==="video")return"video";if(kind==="audio")return"audio";return"file"}async function persistAttachments(ctx,tables,conversationId,messageId,params){let inputs=params.attachments??[];if(inputs.length===0)return[];if(!ctx.attachmentsAvailable||!tables.attachments||!tables.files)throw new ChatError("disabled","File attachments require storage and CDN to be enabled");if(inputs.length>ctx.config.attachments.maxPerMessage)throw new ChatError("validation",`A message cannot have more than ${ctx.config.attachments.maxPerMessage} attachments`);let fileIds=inputs.map((a)=>a.fileId),fileRows=await ctx.db.select().from(tables.files).where(inArray5(getCol(tables.files,"id"),fileIds)),filesById=new Map;for(let row of fileRows)filesById.set(String(row.id),row);let payloads=inputs.map((input)=>{let fileRow=filesById.get(input.fileId);if(!fileRow)throw new ChatError("not_found",`Attachment file ${input.fileId} was not found`);if(String(fileRow.uploadedBy??fileRow.createdBy??"")!==params.senderId)throw new ChatError("forbidden",`Attachment file ${input.fileId} is not owned by the sender`);let mimeType=fileRow.mimeType??input.mimeType??null;return{conversationId,messageId,fileId:input.fileId,kind:input.kind??kindFromMime(mimeType),originalName:fileRow.originalName??input.originalName??null,mimeType,size:fileRow.size??input.size??null,width:input.width??null,height:input.height??null,duration:input.duration??null,createdBy:params.senderId}});return(await ctx.db.insert(tables.attachments).values(payloads).returning()).map((row)=>mapAttachment(row,ctx.cdnBasePath))}async function sendMessage(ctx,params){let tables=resolveChatTables(ctx);await requireActiveMembership(ctx,tables,params.conversationId,params.senderId);let content=params.content?.trim()?params.content:null,hasAttachments=(params.attachments?.length??0)>0;if(!content&&!hasAttachments)throw new ChatError("validation","A message must contain text or at least one attachment");if(content&&content.length>ctx.config.maxMessageLength)throw new ChatError("validation",`Message exceeds the maximum length of ${ctx.config.maxMessageLength} characters`);if(params.metadata!==void 0&¶ms.metadata!==null){if(JSON.stringify(params.metadata).length>4096)throw new ChatError("validation","Message metadata exceeds the maximum size of 4096 bytes")}let{message,participants}=await ctx.db.transaction(async(tx)=>{let txCtx={...ctx,db:tx},messageRow=(await tx.insert(tables.messages).values({conversationId:params.conversationId,senderId:params.senderId,content,contentType:params.contentType??"text",replyToId:params.replyToId??null,clientMessageId:params.clientMessageId??null,metadata:params.metadata??{},createdBy:params.senderId}).returning())[0],messageId=String(messageRow.id),attachments=await persistAttachments(txCtx,tables,params.conversationId,messageId,params),contentType=inferContentType(params.contentType,attachments);if(contentType!==messageRow.contentType)await tx.update(tables.messages).set({contentType}).where(eq17(getCol(tables.messages,"id"),messageId)),messageRow.contentType=contentType;let mappedMessage=mapMessage(messageRow,attachments),preview=buildPreview(mappedMessage.content,mappedMessage.contentType,attachments.length),now=mappedMessage.createdAt;await tx.update(tables.conversations).set({lastMessageAt:now,lastMessagePreview:preview,lastMessageSenderId:params.senderId,updatedAt:new Date}).where(eq17(getCol(tables.conversations,"id"),params.conversationId)),await tx.update(tables.participants).set({unreadCount:sql6`${getCol(tables.participants,"unreadCount")} + 1`}).where(and11(eq17(getCol(tables.participants,"conversationId"),params.conversationId),ne(getCol(tables.participants,"userId"),params.senderId),isNull(getCol(tables.participants,"leftAt"))));let parts=await listParticipants(txCtx,tables,params.conversationId);return{message:mappedMessage,participants:parts}});return deliverToParticipants(ctx,participants,{type:"message.created",conversationId:params.conversationId,message}),message}async function getMessages(ctx,params){let tables=resolveChatTables(ctx);await requireActiveMembership(ctx,tables,params.conversationId,params.userId);let limit=Math.min(Math.max(params.limit??ctx.config.messagePageSize,1),100),conditions=[eq17(getCol(tables.messages,"conversationId"),params.conversationId)];if(params.before){let cursor=(await ctx.db.select().from(tables.messages).where(eq17(getCol(tables.messages,"id"),params.before)).limit(1))[0];if(cursor?.createdAt)conditions.push(lt(getCol(tables.messages,"createdAt"),cursor.createdAt))}let rows=await ctx.db.select().from(tables.messages).where(and11(...conditions)).orderBy(desc4(getCol(tables.messages,"createdAt"))).limit(limit+1),pageRows=rows.slice(0,limit),hasMore=rows.length>limit,attachmentsByMessage=await loadAttachments(ctx,tables,pageRows.map((r)=>String(r.id)));return{messages:pageRows.map((row)=>mapMessage(row,attachmentsByMessage.get(String(row.id))??[])),hasMore}}async function markRead(ctx,conversationId,userId,messageId){let tables=resolveChatTables(ctx),participant=await requireActiveMembership(ctx,tables,conversationId,userId),targetMessageId=messageId??null;if(!targetMessageId){let latestRow=(await ctx.db.select().from(tables.messages).where(eq17(getCol(tables.messages,"conversationId"),conversationId)).orderBy(desc4(getCol(tables.messages,"createdAt"))).limit(1))[0];targetMessageId=latestRow?String(latestRow.id):null}let readAt=new Date;if(await ctx.db.update(tables.participants).set({lastReadMessageId:targetMessageId,lastReadAt:readAt,unreadCount:0}).where(eq17(getCol(tables.participants,"id"),participant.id)),ctx.config.readReceipts){let participants=await listParticipants(ctx,tables,conversationId);deliverToParticipants(ctx,participants,{type:"conversation.read",conversationId,userId,lastReadMessageId:targetMessageId,readAt:readAt.toISOString()},userId)}return{lastReadMessageId:targetMessageId,readAt}}async function editMessage(ctx,messageId,userId,content){if(!ctx.config.editingEnabled)throw new ChatError("disabled","Message editing is disabled");let tables=resolveChatTables(ctx),row=(await ctx.db.select().from(tables.messages).where(eq17(getCol(tables.messages,"id"),messageId)).limit(1))[0];if(!row||row.deletedAt)throw new ChatError("not_found","Message not found");if(String(row.senderId)!==userId)throw new ChatError("forbidden","You can only edit your own messages");let trimmed=content.trim();if(!trimmed)throw new ChatError("validation","Message content cannot be empty");if(trimmed.length>ctx.config.maxMessageLength)throw new ChatError("validation","Message exceeds the maximum length");let editedAt=new Date,updated=await ctx.db.update(tables.messages).set({content:trimmed,editedAt,updatedAt:editedAt}).where(eq17(getCol(tables.messages,"id"),messageId)).returning(),attachments=await loadAttachments(ctx,tables,[messageId]),message=mapMessage(updated[0],attachments.get(messageId)??[]),participants=await listParticipants(ctx,tables,String(row.conversationId));return deliverToParticipants(ctx,participants,{type:"message.updated",conversationId:String(row.conversationId),message}),message}async function deleteMessage(ctx,messageId,userId,asModerator=!1){if(!ctx.config.deletionEnabled&&!asModerator)throw new ChatError("disabled","Message deletion is disabled");let tables=resolveChatTables(ctx),row=(await ctx.db.select().from(tables.messages).where(eq17(getCol(tables.messages,"id"),messageId)).limit(1))[0];if(!row||row.deletedAt)throw new ChatError("not_found","Message not found");if(!asModerator&&String(row.senderId)!==userId)throw new ChatError("forbidden","You can only delete your own messages");let deletedAt=new Date;await ctx.db.update(tables.messages).set({content:null,deletedAt,updatedAt:deletedAt}).where(eq17(getCol(tables.messages,"id"),messageId));let participants=await listParticipants(ctx,tables,String(row.conversationId));deliverToParticipants(ctx,participants,{type:"message.deleted",conversationId:String(row.conversationId),messageId})}async function setTyping(ctx,conversationId,userId,isTyping=!0){if(!ctx.config.typingIndicators)return;let tables=resolveChatTables(ctx),participants=await listParticipants(ctx,tables,conversationId);if(!participants.some((p)=>p.userId===userId))throw new ChatError("forbidden","You are not a participant of this conversation");deliverToParticipants(ctx,participants,{type:"typing",conversationId,userId,isTyping},userId)}class ChatService{ctx;constructor(init){this.ctx={db:init.db,schemaTables:init.schemaTables,config:init.config,logger:init.logger,broadcaster:init.broadcaster??null,cdnBasePath:init.cdnBasePath??"/cdn",attachmentsAvailable:init.attachmentsAvailable??!1}}get config(){return this.ctx.config}getOrCreateDirect(userId,targetUserId){return getOrCreateDirect(this.ctx,{userId,targetUserId})}createGroup(params){return createGroup(this.ctx,params)}listConversations(userId,opts){return listConversations(this.ctx,{userId,limit:opts?.limit,offset:opts?.offset})}getConversation(conversationId,userId){return getConversation(this.ctx,conversationId,userId)}addParticipants(conversationId,actorId,userIds){return addParticipants(this.ctx,conversationId,actorId,userIds)}removeParticipant(conversationId,actorId,targetUserId){return removeParticipant(this.ctx,conversationId,actorId,targetUserId)}sendMessage(params){return sendMessage(this.ctx,params)}getMessages(params){return getMessages(this.ctx,params)}markRead(conversationId,userId,messageId){return markRead(this.ctx,conversationId,userId,messageId)}editMessage(messageId,userId,content){return editMessage(this.ctx,messageId,userId,content)}deleteMessage(messageId,userId,asModerator=!1){return deleteMessage(this.ctx,messageId,userId,asModerator)}setTyping(conversationId,userId,isTyping){return setTyping(this.ctx,conversationId,userId,isTyping)}}init_SystemCollector();init_Notification();var EXTEND_ALLOWED_KEYS=new Set(["table_name","extends","columns","indexes"]);function hasDbDefault(column){return column.default!==void 0||column.defaultRaw!==void 0||column.generatedAlwaysAs!==void 0||column.generatedAlwaysAsIdentity===!0||column.generatedByDefaultAsIdentity===!0}var AUTH_FEATURES=new Set(["authentication","authorization"]);function resolveEntities(systemTables2,configEntities,options={}){let errors2=[],warnings=[],consumed=new Set,entities=[];for(let system of systemTables2){let config=configEntities.find((c)=>c.table_name===system.table_name);if(!config){entities.push(system);continue}if(consumed.add(config.table_name),!config.extends){warnings.push(`[Schema] "${config.table_name}" is declared in config.entities AND ships as a system table. Using YOUR definition and skipping the built-in one. Add "extends": true to inherit the built-in columns and route policy instead.`),entities.push(config);continue}for(let key2 of Object.keys(config))if(!EXTEND_ALLOWED_KEYS.has(key2))warnings.push(`[Schema] "${config.table_name}" sets "${key2}" alongside "extends": true \u2014 ignored. `+"An extending entry inherits every table-level setting from the built-in definition.");if(options.enabledTableNames&&!options.enabledTableNames.has(system.table_name))errors2.push({code:"E5_FEATURE_DISABLED",table:system.table_name,message:`"${system.table_name}" is extended but its feature is disabled, so the table is never created. Enable the feature or remove the extending entry.`});if(options.consumerMode&&(system.feature_set??[]).some((f)=>AUTH_FEATURES.has(f)))errors2.push({code:"E3_CONSUMER_AUTH_TABLE",table:system.table_name,message:`"${system.table_name}" is an auth system table and cannot be extended in consumer mode \u2014 `+"the identity tables live in the IDP. Extending it would create a local copy here."});let builtInNames=new Set((system.columns??[]).map((c)=>c.name));if(system.add_base_columns!==!1)for(let name2 of options.baseColumnNames??[])builtInNames.add(name2);for(let column of config.columns??[]){if(builtInNames.has(column.name))errors2.push({code:"E1_COLUMN_COLLISION",table:system.table_name,column:column.name,message:`"${system.table_name}.${column.name}" already exists in the built-in definition. An extending entry may only ADD columns; rename yours.`});if(column.notNull===!0&&column.nullable!==!0&&!hasDbDefault(column))errors2.push({code:"E2_NOT_NULL_WITHOUT_DEFAULT",table:system.table_name,column:column.name,message:`"${system.table_name}.${column.name}" is notNull without a default. The framework writes this table from fixed-column inserts (register, invite, admin create-user, godmin seed, `+"tenant provisioning) that cannot supply it \u2014 every one of them would fail. Make it "+"nullable or give it a default."})}let merged={...system,columns:[...system.columns??[],...config.columns??[]],indexes:[...system.indexes??[],...config.indexes??[]]};entities.push(merged)}for(let config of configEntities){if(consumed.has(config.table_name))continue;if(config.extends){errors2.push({code:"E4_UNKNOWN_SYSTEM_TABLE",table:config.table_name,message:`"${config.table_name}" sets "extends": true but there is no system table with that name. Remove the flag to declare it as an ordinary entity.`});continue}entities.push(config)}return{entities,errors:errors2,warnings}}function resolveAuthType(pathname,auth){let at=(route)=>pathname===route||pathname.endsWith(route)||pathname.includes(`${route}/`);if(at(auth?.login?.route||"/auth/login"))return"login";if(at(auth?.register?.route||"/auth/register"))return"register";if(at(auth?.passwordReset?.route||"/auth/password-reset"))return"passwordReset";if(at(auth?.magicLink?.route||"/auth/magic-link"))return"magicLink";if(at(auth?.invite?.route||"/auth/invite"))return"other";if(at("/sessions/approve")||at("/sessions/reject"))return"login";return}init_Logger2();var METHOD_MAP={GET:["GET"],POST:["POST"],PUT:["PUT"],DELETE:["DELETE"],PATCH:["PATCH"],TOGGLE:["PATCH"],VERIFICATION:["POST"]};function buildAuthPublicRoutes(config,basePath){let routes=[],auth=config.authentication;if(!auth)return routes;if(auth.login?.enabled&&auth.login?.isPublic)routes.push({path:auth.login.route||`${basePath}/auth/login`,method:"POST",source:"auth"});if(auth.register?.enabled&&auth.register?.isPublic)routes.push({path:auth.register.route||`${basePath}/auth/register`,method:"POST",source:"auth"});if(auth.logout?.enabled&&auth.logout?.isPublic)routes.push({path:auth.logout.route||`${basePath}/auth/logout`,method:"POST",source:"auth"});if(auth.refresh?.enabled&&auth.refresh?.isPublic)routes.push({path:auth.refresh.route||`${basePath}/auth/refresh`,method:"POST",source:"auth"});if(auth.passwordReset?.enabled&&auth.passwordReset?.isPublic){let baseRoute=auth.passwordReset.route||`${basePath}/auth/password-reset`;routes.push({path:`${baseRoute}/request`,method:"POST",source:"auth"},{path:`${baseRoute}/confirm`,method:"POST",source:"auth"})}if(auth.passwordChange?.enabled&&auth.passwordChange?.isPublic)routes.push({path:auth.passwordChange.route||`${basePath}/auth/password-change`,method:"POST",source:"auth"});if(auth.magicLink?.enabled&&auth.magicLink?.isPublic)routes.push({path:auth.magicLink.route||`${basePath}/auth/magic-link`,method:"POST",source:"auth"},{path:auth.magicLink.verifyRoute||`${basePath}/auth/magic-link/verify`,method:"GET",source:"auth"});if(auth.register?.enabled&&auth.register?.emailVerification?.enabled)routes.push({path:`${basePath}/verify-email`,method:"GET",source:"auth"},{path:`${basePath}/resend-verification`,method:"POST",source:"auth"});if(auth.invite?.enabled&&auth.invite?.isPublic)routes.push({path:auth.invite.route||`${basePath}/auth/invite`,method:"POST",source:"auth"});if(auth.invite?.enabled){let inviteRoute=auth.invite.route||`${basePath}/auth/invite`;routes.push({path:`${inviteRoute}/verify`,method:"POST",source:"auth"})}if(auth.passwordSet?.enabled)routes.push({path:auth.passwordSet.route||`${basePath}/auth/password-set`,method:"POST",source:"auth"});if(auth.webauthn?.enabled){let webauthnRoute=auth.webauthn.route||`${basePath}/auth/webauthn`;routes.push({path:`${webauthnRoute}/authenticate/options`,method:"POST",source:"auth"},{path:`${webauthnRoute}/authenticate/verify`,method:"POST",source:"auth"})}if(auth.captcha?.enabled&&auth.captcha?.isPublic){let baseRoute=auth.captcha.route||`${basePath}/auth/captcha`;routes.push({path:`${baseRoute}/generate`,method:"GET",source:"auth"},{path:`${baseRoute}/validate`,method:"POST",source:"auth"})}if(auth.sessions?.enabled){let sessionsRoute=auth.sessions.route||`${basePath}/auth/sessions`;routes.push({path:`${sessionsRoute}/approve`,method:"POST",source:"auth"},{path:`${sessionsRoute}/reject`,method:"POST",source:"auth"},{path:`${sessionsRoute}/approve-page`,method:"GET",source:"auth"},{path:`${sessionsRoute}/reject-page`,method:"GET",source:"auth"},{path:`${sessionsRoute}/approval-status`,method:"GET",source:"auth"})}if(auth.oauth?.enabled){let oauthBase=auth.oauth.basePath||`${basePath}/auth/oauth`,knownProviders=["google","github","microsoft","discord","facebook","twitter","apple","custom"];routes.push({path:`${oauthBase}/providers`,method:"GET",source:"auth"});for(let provider of knownProviders)routes.push({path:`${oauthBase}/${provider}`,method:"GET",source:"auth"},{path:`${oauthBase}/${provider}/callback`,method:"GET",source:"auth"})}return routes}function buildEntityPublicRoutes(entities,basePath,_schema){let routes=[];for(let entity of entities){if(!entity.is_public)continue;let camelName=entity.table_name.replace(/_([a-z])/g,(_,l)=>l.toUpperCase()),entityPath=`${basePath}/${camelName}`;for(let[nucleusMethod,isPublic]of Object.entries(entity.is_public)){if(!isPublic)continue;let httpMethods=METHOD_MAP[nucleusMethod];if(!httpMethods)continue;for(let method of httpMethods)if(method==="GET")routes.push({path:entityPath,method:"GET",source:"entity"}),routes.push({path:`${entityPath}/:id`,method:"GET",source:"entity"});else if(method==="POST")routes.push({path:entityPath,method:"POST",source:"entity"});else if(method==="PUT"||method==="PATCH")routes.push({path:`${entityPath}/:id`,method,source:"entity"});else if(method==="DELETE")routes.push({path:`${entityPath}/:id`,method:"DELETE",source:"entity"})}}return routes}function buildSystemTablePublicRoutes(systemTables2,basePath,schema){return buildEntityPublicRoutes(systemTables2,basePath,schema)}function buildPublicRoutes(config,systemTables2,basePath="",schema="public"){let authRoutes=buildAuthPublicRoutes(config,basePath),entityRoutes=buildEntityPublicRoutes(config.entities||[],basePath,schema),systemRoutes=buildSystemTablePublicRoutes(systemTables2,basePath,schema),pubsubRoutes=[];if(config.pubsub?.enabled){let pubsubBasePath=config.pubsub.basePath||"/subs",wsPath=config.pubsub.wsPath||"/api/events/subscribe";pubsubRoutes.push({path:`${pubsubBasePath}/:topic`,method:"POST",source:"system"},{path:wsPath,method:"GET",source:"system"})}let paymentRoutes=[];if(config.payment?.enabled){let paymentBasePath=config.payment.basePath||"/payment";paymentRoutes.push({path:`${paymentBasePath}/callback`,method:"POST",source:"system"},{path:`${paymentBasePath}/callback`,method:"OPTIONS",source:"system"},{path:`${paymentBasePath}/bin-query`,method:"POST",source:"system"},{path:`${paymentBasePath}/webhook`,method:"POST",source:"system"})}let discoveryRoutes=[];if(config.authorization?.endpointDiscovery?.enabled)discoveryRoutes.push({path:"/authorization/route-manifest",method:"GET",source:"system"},{path:"/authorization/route-manifest",method:"OPTIONS",source:"system"},{path:"/authorization/role-claims-manifest",method:"GET",source:"system"},{path:"/authorization/role-claims-manifest",method:"OPTIONS",source:"system"});let domainRoutes=[];if(config.domains?.enabled){let domainsBasePath=config.domains.basePath||"/domains";domainRoutes.push({path:`${basePath}${domainsBasePath}/resolve`,method:"GET",source:"system"})}let tenantRoutes=[];if(config.database?.isMultiTenant)tenantRoutes.push({path:`${basePath}/tenants`,method:"GET",source:"system"}),tenantRoutes.push({path:`${basePath}/tenants/check-subdomain/:subdomain`,method:"GET",source:"system"}),tenantRoutes.push({path:`${basePath}/tenants/self-signup`,method:"POST",source:"system"}),tenantRoutes.push({path:`${basePath}/tenants/refresh`,method:"POST",source:"system"});let customRoutes=[{path:"/nucleus-core",method:"GET",source:"custom"},{path:"/public",method:"GET",source:"custom"},{path:"/docs",method:"GET",source:"custom"},{path:"/docs/json",method:"GET",source:"custom"},{path:"/swagger",method:"GET",source:"custom"},{path:"/swagger/json",method:"GET",source:"custom"}],configPublicPaths=config.authorization?.publicPaths||[],ALL_PUBLIC_METHODS=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],configPublicRoutes=configPublicPaths.flatMap((entry)=>{let trimmed=entry.trim(),qualified=trimmed.match(/^(GET|POST|PUT|PATCH|DELETE|OPTIONS)\s+(.+)$/i);if(qualified?.[1]&&qualified[2]){let method=qualified[1].toUpperCase(),path2=qualified[2].trim(),routes=[{path:path2,method,source:"custom"}];if(method!=="OPTIONS")routes.push({path:path2,method:"OPTIONS",source:"custom"});return routes}if(trimmed.startsWith("/auth/"))return ALL_PUBLIC_METHODS.map((method)=>({path:trimmed,method,source:"custom"}));return logger.warn(`[Security] publicPaths entry "${trimmed}" is unqualified \u2014 exposing GET + OPTIONS only. To make a write method public, use the explicit form, e.g. "POST ${trimmed}".`),[{path:trimmed,method:"GET",source:"custom"},{path:trimmed,method:"OPTIONS",source:"custom"}]});return[...authRoutes,...entityRoutes,...systemRoutes,...pubsubRoutes,...paymentRoutes,...discoveryRoutes,...domainRoutes,...tenantRoutes,...customRoutes,...configPublicRoutes]}function isPublicRoute(publicRoutes,path2,method){if(/\/\/|\\|%2f|%2e|%5c/i.test(path2))return!1;let normalizedPath=path2.replace(/\/$/,""),normalizedMethod=method.toUpperCase();for(let route of publicRoutes){if(route.method!==normalizedMethod)continue;if(matchPath(route.path,normalizedPath))return!0}return!1}function matchPath(pattern,path2){if(pattern===path2)return!0;let patternParts=pattern.split("/").filter(Boolean),pathParts=path2.split("/").filter(Boolean);if(patternParts.length!==pathParts.length)return!1;for(let i=0;i<patternParts.length;i++){let patternPart=patternParts[i],pathPart=pathParts[i];if(patternPart?.startsWith(":"))continue;if(patternPart!==pathPart)return!1}return!0}import{Elysia as Elysia2}from"elysia";import{eq as eq19}from"drizzle-orm";import{eq as eq18}from"drizzle-orm";var col7=(table,name2)=>{let tableRecord=table,snakeCase=name2.replace(/([A-Z])/g,"_$1").toLowerCase();return tableRecord[name2]||tableRecord[snakeCase]};async function requireGodmin(db,usersTable,userId){let user=(await db.select().from(usersTable).where(eq18(col7(usersTable,"id"),userId)).limit(1))[0];return Boolean(user?.isGod)}function validatePassword(pwd,policy){let errors2=[],minLen=policy?.minLength??8,maxLen=policy?.maxLength??128,needUpper=policy?.requireUppercase??!0,needLower=policy?.requireLowercase??!0,needDigit=policy?.requireNumber??!0,needSpecial=policy?.requireSpecialChar??!1;if(pwd.length<minLen)errors2.push(`Password must be at least ${minLen} characters`);if(pwd.length>maxLen)errors2.push(`Password must be at most ${maxLen} characters`);if(needUpper&&!/[A-Z]/.test(pwd))errors2.push("Password must contain uppercase letter");if(needLower&&!/[a-z]/.test(pwd))errors2.push("Password must contain lowercase letter");if(needDigit&&!/[0-9]/.test(pwd))errors2.push("Password must contain a number");if(needSpecial&&!/[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/.test(pwd))errors2.push("Password must contain a special character");return{valid:errors2.length===0,errors:errors2}}var handleActivateUsers=(db,usersTable,logger2)=>async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId||!await requireGodmin(db,usersTable,userId))return ctx.set.status=403,{success:!1,message:"Forbidden"};let result=await db.update(usersTable).set({isLocked:!1,lockedUntil:null,failedLoginAttempts:0,updatedAt:new Date}).where(eq19(col7(usersTable,"cohortId"),ctx.params.id)).returning();return logger2.audit({entityName:"user_cohorts",entityId:ctx.params.id,operation:"COHORT_ACTIVATE_USERS",userId,summary:`Activated ${result.length} users in cohort`}),{success:!0,data:{affected:result.length}}};init_assignDefaultRole();init_utils6();import{count,eq as eq21,inArray as inArray6}from"drizzle-orm";var handleBulkCreateUsers=(config,logger2)=>{let{db,usersTable,cohortsTable,rolesTable,userRolesTable,profilesTable}=config;return async(ctx)=>{if(!db||!usersTable||!cohortsTable)return ctx.set.status=500,{success:!1,message:"Server misconfigured"};let callerId=ctx.request.headers.get("x-user-id");if(!callerId||!await requireGodmin(db,usersTable,callerId))return ctx.set.status=403,{success:!1,message:"Forbidden"};let cohortId=ctx.params.id;if((await db.select().from(cohortsTable).where(eq21(col7(cohortsTable,"id"),cohortId)).limit(1)).length===0)return ctx.set.status=404,{success:!1,message:"Cohort not found"};let{users:explicitUsers,emailPrefix,emailDomain,sharedPassword,count:userCount,roleIds}=ctx.body,userList=[];if(explicitUsers&&explicitUsers.length>0)for(let u of explicitUsers)userList.push({email:u.email.toLowerCase().trim(),password:u.password,firstName:u.profile?.firstName,lastName:u.profile?.lastName});else if(emailPrefix&&emailDomain&&sharedPassword&&userCount){let padLen=String(userCount).length;for(let i=1;i<=userCount;i++){let paddedNum=String(i).padStart(padLen,"0");userList.push({email:`${emailPrefix}-${paddedNum}@${emailDomain}`.toLowerCase(),password:sharedPassword})}}else return ctx.set.status=400,{success:!1,message:'Provide either "users" array or "emailPrefix" + "emailDomain" + "sharedPassword" + "count"'};if(userList.length>500)return ctx.set.status=400,{success:!1,message:"Maximum 500 users per batch"};for(let entry of userList){let validation=validatePassword(entry.password,config.passwordPolicy);if(!validation.valid)return ctx.set.status=400,{success:!1,message:`Password too weak for ${entry.email}`,errors:validation.errors}}let emails=userList.map((u)=>u.email),existingRows=await db.select({email:col7(usersTable,"email")}).from(usersTable).where(inArray6(col7(usersTable,"email"),emails)),existingEmails=new Set(existingRows.map((r)=>String(r.email).toLowerCase())),created=[],skipped=[],now=new Date;for(let entry of userList){if(existingEmails.has(entry.email)){skipped.push(entry.email);continue}let hashedPw=await hashPassword(entry.password),newUser=(await db.insert(usersTable).values({email:entry.email,password:hashedPw,emailVerified:!0,verifiedAt:now,isLocked:!1,cohortId,createdAt:now,updatedAt:now}).returning())[0];if(!newUser)continue;let newUserId=String(newUser.id);if(created.push({id:newUserId,email:entry.email,password:entry.password}),roleIds&&roleIds.length>0&&rolesTable&&userRolesTable){let validIds=(await db.select({id:col7(rolesTable,"id")}).from(rolesTable).where(inArray6(col7(rolesTable,"id"),roleIds))).map((r)=>String(r.id));if(validIds.length>0)await db.insert(userRolesTable).values(validIds.map((roleId)=>({userId:newUserId,roleId})))}else{let cohortDefaultRoles=resolveDefaultRoleNames(config);if(cohortDefaultRoles.length>0)await assignDefaultRoles({db,userId:newUserId,roleNames:cohortDefaultRoles,rolesTable,userRolesTable,logger:logger2})}if((entry.firstName||entry.lastName)&&profilesTable)await db.insert(profilesTable).values({userId:newUserId,firstName:entry.firstName??null,lastName:entry.lastName??null,createdAt:now,updatedAt:now}).catch((err)=>{logger2.warn("[Cohort] Failed to create profile for user",{userId:newUserId,error:err.message})})}let countResult=await db.select({count:count()}).from(usersTable).where(eq21(col7(usersTable,"cohortId"),cohortId)),totalUsers=Number(countResult[0]?.count)||0;return await db.update(cohortsTable).set({userCount:totalUsers,updatedAt:new Date}).where(eq21(col7(cohortsTable,"id"),cohortId)),logger2.audit({entityName:"user_cohorts",entityId:cohortId,operation:"COHORT_BULK_CREATE",userId:callerId,summary:`Bulk created ${created.length} users in cohort (${skipped.length} skipped)`}),{success:!0,data:{created:created.length,skipped:skipped.length,skippedEmails:skipped,users:created}}}};var handleCreateCohort=(db,usersTable,cohortsTable,logger2)=>async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId||!await requireGodmin(db,usersTable,userId))return ctx.set.status=403,{success:!1,message:"Forbidden"};let{name:name2,description,expiresAt,metadata}=ctx.body,now=new Date,inserted=await db.insert(cohortsTable).values({name:name2,description:description??null,createdBy:userId,expiresAt:expiresAt?new Date(expiresAt):null,userCount:0,metadata:metadata??{},createdAt:now,updatedAt:now}).returning();return logger2.audit({entityName:"user_cohorts",entityId:inserted[0]?.id,operation:"COHORT_CREATE",userId,summary:`Created cohort "${name2}"`}),{success:!0,data:inserted[0]}};import{eq as eq22}from"drizzle-orm";var handleDeactivateUsers=(db,usersTable,logger2)=>async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId||!await requireGodmin(db,usersTable,userId))return ctx.set.status=403,{success:!1,message:"Forbidden"};let result=await db.update(usersTable).set({isLocked:!0,updatedAt:new Date}).where(eq22(col7(usersTable,"cohortId"),ctx.params.id)).returning();return logger2.audit({entityName:"user_cohorts",entityId:ctx.params.id,operation:"COHORT_DEACTIVATE_USERS",userId,summary:`Deactivated ${result.length} users in cohort`}),{success:!0,data:{affected:result.length}}};import{eq as eq23,inArray as inArray7}from"drizzle-orm";var handleDeleteUsers=(db,usersTable,cohortsTable,userRolesTable,profilesTable,logger2)=>async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId||!await requireGodmin(db,usersTable,userId))return ctx.set.status=403,{success:!1,message:"Forbidden"};let userIds=(await db.select({id:col7(usersTable,"id")}).from(usersTable).where(eq23(col7(usersTable,"cohortId"),ctx.params.id))).map((u)=>String(u.id));if(userIds.length>0){if(userRolesTable)await db.delete(userRolesTable).where(inArray7(col7(userRolesTable,"userId"),userIds));if(profilesTable)await db.delete(profilesTable).where(inArray7(col7(profilesTable,"userId"),userIds));await db.delete(usersTable).where(inArray7(col7(usersTable,"id"),userIds))}return await db.update(cohortsTable).set({userCount:0,updatedAt:new Date}).where(eq23(col7(cohortsTable,"id"),ctx.params.id)),logger2.audit({entityName:"user_cohorts",entityId:ctx.params.id,operation:"COHORT_DELETE_USERS",userId,summary:`Deleted ${userIds.length} users from cohort`}),{success:!0,data:{deleted:userIds.length}}};import{eq as eq24}from"drizzle-orm";var handleGetCohort=(db,usersTable,cohortsTable)=>async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId||!await requireGodmin(db,usersTable,userId))return ctx.set.status=403,{success:!1,message:"Forbidden"};let rows=await db.select().from(cohortsTable).where(eq24(col7(cohortsTable,"id"),ctx.params.id)).limit(1);if(rows.length===0)return ctx.set.status=404,{success:!1,message:"Cohort not found"};let userRows=await db.select().from(usersTable).where(eq24(col7(usersTable,"cohortId"),ctx.params.id));return{success:!0,data:{...rows[0],users:userRows}}};import{eq as eq25}from"drizzle-orm";var csvCell=(value)=>{let s=value==null?"":String(value);if(/^[=+\-@\t\r]/.test(s))s=`'${s}`;if(/[",\n\r]/.test(s))s=`"${s.replace(/"/g,'""')}"`;return s},handleExportUsers=(db,usersTable)=>async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId||!await requireGodmin(db,usersTable,userId))return ctx.set.status=403,{success:!1,message:"Forbidden"};let userRows=await db.select().from(usersTable).where(eq25(col7(usersTable,"cohortId"),ctx.params.id)),lines=["email,status,locked,created_at"];for(let row of userRows){let u=row;lines.push([csvCell(u.email),csvCell(u.isActive?"active":"inactive"),csvCell(u.isLocked?"yes":"no"),csvCell(u.createdAt)].join(","))}return ctx.set.headers["content-type"]="text/csv",ctx.set.headers["content-disposition"]=`attachment; filename="cohort-${ctx.params.id}-users.csv"`,lines.join(`
|
|
531
|
+
`},createPaymentRoutes=(config)=>{let{provider,basePath,defaultCurrency,defaultLocale,successRedirectUrl,failedRedirectUrl,errorRedirectUrl,savedMethodsEnabled,threeDSecureEnabled,subMerchantsEnabled,transactionsTable,methodsTable,webhookLogsTable,subMerchantsTable,commissionSplitsTable,productsTable,pricesTable,customersTable,subscriptionsTable,invoicesTable,db,logger:logger2}=config,txTable=transactionsTable,pmTable=methodsTable,whTable=webhookLogsTable,smTable=subMerchantsTable,csTable=commissionSplitsTable,prodTable=productsTable,priceTable=pricesTable,cusTable=customersTable,subTable=subscriptionsTable,invTable=invoicesTable,database=db,app=new Elysia47({prefix:basePath}),customerBelongsToCaller=async(request,customerId)=>{if(hasGodminRole(request))return!0;let uid=request.headers.get("x-user-id");if(!uid||!customerId)return!1;let[c]=await database.select().from(cusTable).where(eq59(cusTable.id,String(customerId)));return!!c&&String(c.user_id)===String(uid)},callerCustomerIds=async(uid)=>{return(await database.select().from(cusTable).where(eq59(cusTable.user_id,uid))).map((r2)=>String(r2.id))};if(app.post("/initialize",async(ctx)=>{if(!threeDSecureEnabled)return ctx.set.status=400,{success:!1,error:"3D Secure is not enabled"};let userId=ctx.request.headers.get("x-user-id"),body=ctx.body;try{let[transaction]=await database.insert(txTable).values({userId:userId??null,orderId:body.orderId??body.conversationId??null,provider:provider.name,amount:Number(body.paidPrice??body.price??0),currency:body.currency??defaultCurrency,status:"pending",statusCode:1000,statusMessage:"3DS initialization started",isThreeDSecure:!0,installment:body.installment??1,ipAddress:ctx.request.headers.get("x-forwarded-for")??ctx.request.headers.get("x-real-ip")??null,metadata:body.metadata??{}}).returning(),result=await provider.initialize3DS({locale:body.locale??defaultLocale,conversationId:transaction.id,price:body.price,paidPrice:body.paidPrice,currency:body.currency??defaultCurrency,installment:body.installment,paymentChannel:body.paymentChannel,basketId:body.basketId,paymentGroup:body.paymentGroup,paymentCard:body.paymentCard,buyer:body.buyer,shippingAddress:body.shippingAddress,billingAddress:body.billingAddress,basketItems:body.basketItems,callbackUrl:body.callbackUrl??config.callbackUrl??`${basePath}/callback`});if(!result.success)return await database.update(txTable).set({status:"failed",statusCode:1003,statusMessage:result.errorMessage??"Initialization failed",providerResponse:result.rawResponse??{},failedAt:new Date}).where(eq59(txTable.id,transaction.id)),ctx.set.status=400,{success:!1,error:result.errorMessage??"Payment initialization failed",errorCode:result.errorCode};return await database.update(txTable).set({status:"processing",statusCode:1001,statusMessage:"3DS initialized, awaiting bank verification",providerPaymentId:result.paymentId,providerResponse:result.rawResponse??{}}).where(eq59(txTable.id,transaction.id)),{success:!0,transactionId:transaction.id,threeDSHtmlContent:result.threeDSHtmlContent,paymentId:result.paymentId}}catch(error3){return logger2.error("[Payment] initialize3DS error",{error:error3 instanceof Error?error3.message:String(error3)}),ctx.set.status=500,{success:!1,error:"Internal payment error"}}}),app.post("/callback",async(ctx)=>{let requestOrigin=new URL(ctx.request.url).origin,htmlHeaders={"Content-Type":"text/html; charset=utf-8","Access-Control-Allow-Origin":requestOrigin,"Access-Control-Allow-Methods":"POST, OPTIONS"};try{let formData=await ctx.request.formData(),rawData={};formData.forEach((value2,key2)=>{rawData[key2]=String(value2)});let parsed=provider.parseCallback(rawData);if(await database.insert(whTable).values({provider:provider.name,eventType:"three_ds_callback",providerPaymentId:parsed.paymentId,rawPayload:rawData,processed:!1,idempotencyKey:`${provider.name}:${parsed.paymentId}:${parsed.mdStatus}`,ipAddress:ctx.request.headers.get("x-forwarded-for")??ctx.request.headers.get("x-real-ip")??null}).onConflictDoNothing(),!parsed.success){if(logger2.warn("[Payment] 3DS callback failed",{mdStatus:parsed.mdStatus,paymentId:parsed.paymentId}),parsed.conversationId)await database.update(txTable).set({status:"failed",statusCode:1003,statusMessage:`3DS verification failed: mdStatus=${parsed.mdStatus}`,failedAt:new Date}).where(eq59(txTable.id,parsed.conversationId)).catch(()=>{});return new Response(generateRedirectHtml(`${requestOrigin}${failedRedirectUrl}`,"Payment Failed"),{headers:htmlHeaders})}let completion=await provider.complete3DS({locale:defaultLocale,conversationId:parsed.conversationId,paymentId:parsed.paymentId});if(!completion.success){if(logger2.error("[Payment] 3DS completion failed",{paymentId:parsed.paymentId,errorCode:completion.errorCode,errorMessage:completion.errorMessage}),parsed.conversationId)await database.update(txTable).set({status:"failed",statusCode:1003,statusMessage:`3DS completion failed: ${completion.errorMessage}`,providerResponse:completion.rawResponse??{},failedAt:new Date}).where(eq59(txTable.id,parsed.conversationId)).catch(()=>{});return new Response(generateRedirectHtml(`${requestOrigin}${failedRedirectUrl}`,"Payment Failed"),{headers:htmlHeaders})}if(parsed.conversationId)await database.update(txTable).set({status:"completed",statusCode:1001,statusMessage:"Payment completed successfully",providerPaymentId:completion.paymentId??parsed.paymentId,providerTransactionId:completion.signature,amount:completion.paidPrice??0,currency:completion.currency??defaultCurrency,paymentMethod:completion.cardAssociation,cardLastFour:completion.lastFourDigits,cardType:completion.cardType,cardAssociation:completion.cardAssociation,installment:completion.installment??1,providerResponse:completion.rawResponse??{},completedAt:new Date}).where(and21(eq59(txTable.id,parsed.conversationId),eq59(txTable.status,"pending"))).catch(()=>{});await database.update(whTable).set({processed:!0,processingResult:{completion}}).where(eq59(whTable.idempotencyKey,`${provider.name}:${parsed.paymentId}:${parsed.mdStatus}`)).catch(()=>{}),logger2.info("[Payment] 3DS payment completed",{paymentId:completion.paymentId,amount:completion.paidPrice,currency:completion.currency});let queryParams=new URLSearchParams;if(parsed.conversationId)queryParams.append("transactionId",parsed.conversationId);if(completion.paymentId)queryParams.append("paymentId",completion.paymentId);if(completion.paidPrice)queryParams.append("amount",String(completion.paidPrice));let redirectUrl=`${requestOrigin}${successRedirectUrl}?${queryParams.toString()}`;return new Response(generateRedirectHtml(redirectUrl,"Payment Successful"),{headers:htmlHeaders})}catch(error3){return logger2.error("[Payment] callback error",{error:error3 instanceof Error?error3.message:String(error3)}),new Response(generateRedirectHtml(`${requestOrigin}${errorRedirectUrl}`,"Payment Error"),{headers:htmlHeaders})}}),app.get("/transactions",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{return{success:!0,data:{items:await database.select().from(txTable).where(eq59(txTable.userId,userId)).orderBy(txTable.createdAt)}}}catch(error3){return logger2.error("[Payment] list transactions error",{error:error3 instanceof Error?error3.message:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to list transactions"}}}),app.get("/transactions/:id",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let[transaction]=await database.select().from(txTable).where(and21(eq59(txTable.id,ctx.params.id),eq59(txTable.userId,userId))).limit(1);if(!transaction)return ctx.set.status=404,{success:!1,error:"Transaction not found"};return{success:!0,data:transaction}}catch{return ctx.set.status=500,{success:!1,error:"Failed to get transaction"}}}),app.post("/bin-query",async(ctx)=>{let body=ctx.body,binNumber=body.binNumber??body.cardNumber;if(!binNumber||typeof binNumber!=="string")return ctx.set.status=400,{success:!1,error:"binNumber is required"};try{let result=await provider.queryBin({locale:body.locale??defaultLocale,binNumber,price:body.price});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"BIN query failed",errorCode:result.errorCode};return{success:!0,data:result}}catch{return ctx.set.status=500,{success:!1,error:"BIN query failed"}}}),app.post("/payment-detail",async(ctx)=>{let body=ctx.body;if(!body.paymentId)return ctx.set.status=400,{success:!1,error:"paymentId is required"};try{let result=await provider.getPaymentDetail({locale:body.locale??defaultLocale,paymentId:body.paymentId,conversationId:body.conversationId,paymentConversationId:body.paymentConversationId});return{success:result.success,data:result}}catch{return ctx.set.status=500,{success:!1,error:"Payment detail query failed"}}}),app.post("/refund",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};let body=ctx.body;if(!body.paymentTransactionId||!body.price)return ctx.set.status=400,{success:!1,error:"paymentTransactionId and price are required"};let refundAmt=validateAmount(body.price,"price");if(!refundAmt.ok)return ctx.set.status=400,{success:!1,error:refundAmt.error};if(!hasGodminRole(ctx.request)){if(!body.transactionId)return ctx.set.status=400,{success:!1,error:"transactionId is required"};let[tx]=await database.select().from(txTable).where(eq59(txTable.id,body.transactionId)).limit(1);if(!tx)return ctx.set.status=404,{success:!1,error:"Transaction not found"};if(String(tx.userId)!==String(userId))return ctx.set.status=403,{success:!1,error:"You can only refund your own transactions"};let ownedProviderId=tx.providerTransactionId??tx.providerPaymentId;if(ownedProviderId&&String(body.paymentTransactionId)!==String(ownedProviderId))return ctx.set.status=403,{success:!1,error:"paymentTransactionId does not match this transaction"};let refundable=Number(tx.amount??0)-Number(tx.refundedAmount??0);if(!(Number(body.price)>0)||Number(body.price)>refundable)return ctx.set.status=400,{success:!1,error:`Refund amount exceeds the refundable balance (${refundable})`}}try{let result=await provider.refund({locale:body.locale??defaultLocale,conversationId:body.conversationId,paymentTransactionId:body.paymentTransactionId,price:String(body.price),currency:body.currency??defaultCurrency,ip:ctx.request.headers.get("x-forwarded-for")??ctx.request.headers.get("x-real-ip")??void 0});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Refund failed",errorCode:result.errorCode};if(body.transactionId){let price=Number(body.price);await database.update(txTable).set({status:sql11`CASE WHEN COALESCE(${txTable.refundedAmount}, 0) + ${price} >= ${txTable.amount} THEN 'refunded' ELSE 'partially_refunded' END`,refundedAmount:sql11`COALESCE(${txTable.refundedAmount}, 0) + ${price}`,refundedAt:new Date,statusMessage:"Payment refunded"}).where(eq59(txTable.id,body.transactionId)).catch(()=>{})}return logger2.info("[Payment] Refund processed",{paymentId:result.paymentId,price:result.price}),{success:!0,data:result}}catch{return ctx.set.status=500,{success:!1,error:"Refund failed"}}}),savedMethodsEnabled)app.post("/cards/save",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};let body=ctx.body;if(!body.email||!body.card)return ctx.set.status=400,{success:!1,error:"email and card are required"};try{let result=await provider.saveCard({locale:body.locale??defaultLocale,email:body.email,externalId:userId,card:body.card});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to save card",errorCode:result.errorCode};let[saved]=await database.insert(pmTable).values({userId,provider:provider.name,type:"card",alias:result.cardAlias??body.card.cardAlias,cardLastFour:result.lastFourDigits,cardType:result.cardType,cardAssociation:result.cardAssociation,cardFamily:result.cardFamily,cardBankName:result.cardBankName,providerCardUserKey:result.cardUserKey,providerCardToken:result.cardToken,binNumber:result.binNumber}).returning();return logger2.info("[Payment] Card saved",{userId,cardAlias:result.cardAlias}),{success:!0,data:saved}}catch{return ctx.set.status=500,{success:!1,error:"Failed to save card"}}}),app.get("/cards",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{return{success:!0,data:{items:await database.select().from(pmTable).where(and21(eq59(pmTable.userId,userId),eq59(pmTable.isActive,!0))).orderBy(pmTable.createdAt)}}}catch{return ctx.set.status=500,{success:!1,error:"Failed to list cards"}}}),app.delete("/cards/:id",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let[card]=await database.select().from(pmTable).where(and21(eq59(pmTable.id,ctx.params.id),eq59(pmTable.userId,userId))).limit(1);if(!card)return ctx.set.status=404,{success:!1,error:"Card not found"};if(card.providerCardUserKey&&card.providerCardToken){let deleteResult=await provider.deleteCard({locale:defaultLocale,cardUserKey:card.providerCardUserKey,cardToken:card.providerCardToken});if(!deleteResult.success)logger2.warn("[Payment] Provider card delete failed (proceeding with local delete)",{errorCode:deleteResult.errorCode,errorMessage:deleteResult.errorMessage})}return await database.update(pmTable).set({isActive:!1}).where(eq59(pmTable.id,ctx.params.id)),logger2.info("[Payment] Card deleted",{userId,cardId:ctx.params.id}),{success:!0}}catch{return ctx.set.status=500,{success:!1,error:"Failed to delete card"}}}),app.post("/cards/sync",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};let body=ctx.body,cardUserKey=body.cardUserKey;if(!cardUserKey)return ctx.set.status=400,{success:!1,error:"cardUserKey is required"};try{let result=await provider.listCards({locale:body.locale??defaultLocale,cardUserKey});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to list cards from provider"};return{success:!0,data:{cardUserKey:result.cardUserKey,cards:result.cards}}}catch{return ctx.set.status=500,{success:!1,error:"Failed to sync cards"}}});if(app.post("/products",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};if(!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden: operator privileges required"};let body=ctx.body;if(!body.name)return ctx.set.status=400,{success:!1,error:"name is required"};try{let providerResult=await provider.createProduct({name:body.name,description:body.description,type:body.type,images:body.images,unitLabel:body.unitLabel,url:body.url,metadata:body.metadata});if(!providerResult.success)return ctx.set.status=400,{success:!1,error:providerResult.errorMessage??"Failed to create product at provider",errorCode:providerResult.errorCode};let[saved]=await database.insert(prodTable).values({provider:provider.name,providerProductId:providerResult.providerProductId,name:body.name,description:body.description??null,type:body.type??"service",status:"active",images:body.images?JSON.stringify(body.images):"[]",unitLabel:body.unitLabel??null,url:body.url??null,metadata:body.metadata?JSON.stringify(body.metadata):"{}"}).returning();return logger2.info("[Payment] Product created",{id:saved.id,providerProductId:providerResult.providerProductId}),{success:!0,data:saved}}catch(error3){return logger2.error("[Payment] create product error",{error:error3 instanceof Error?error3.message:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to create product"}}}),app.put("/products/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};if(!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden: operator privileges required"};let body=ctx.body;try{let[existing]=await database.select().from(prodTable).where(eq59(prodTable.id,ctx.params.id)).limit(1);if(!existing)return ctx.set.status=404,{success:!1,error:"Product not found"};if(existing.providerProductId){let providerResult=await provider.updateProduct({providerProductId:existing.providerProductId,name:body.name,description:body.description,images:body.images,unitLabel:body.unitLabel,url:body.url,active:body.status==="active"?!0:body.status==="archived"?!1:void 0,metadata:body.metadata});if(!providerResult.success)logger2.warn("[Payment] Provider product update failed",{errorCode:providerResult.errorCode})}let updateData={};if(body.name)updateData.name=body.name;if(body.description!==void 0)updateData.description=body.description;if(body.type)updateData.type=body.type;if(body.status)updateData.status=body.status;if(body.images)updateData.images=JSON.stringify(body.images);if(body.unitLabel!==void 0)updateData.unitLabel=body.unitLabel;if(body.url!==void 0)updateData.url=body.url;if(body.metadata)updateData.metadata=JSON.stringify(body.metadata);let[updated]=await database.update(prodTable).set(updateData).where(eq59(prodTable.id,ctx.params.id)).returning();return{success:!0,data:updated}}catch{return ctx.set.status=500,{success:!1,error:"Failed to update product"}}}),app.get("/products",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let status=new URL(ctx.request.url).searchParams.get("status"),query=database.select().from(prodTable).where(eq59(prodTable.isActive,!0));if(status)query=database.select().from(prodTable).where(and21(eq59(prodTable.isActive,!0),eq59(prodTable.status,status)));return{success:!0,data:{items:await query.orderBy(prodTable.createdAt)}}}catch{return ctx.set.status=500,{success:!1,error:"Failed to list products"}}}),app.get("/products/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let[item]=await database.select().from(prodTable).where(eq59(prodTable.id,ctx.params.id)).limit(1);if(!item)return ctx.set.status=404,{success:!1,error:"Product not found"};let prices=await database.select().from(priceTable).where(and21(eq59(priceTable.productId,ctx.params.id),eq59(priceTable.isActive,!0))).orderBy(priceTable.createdAt);return{success:!0,data:{...item,prices}}}catch{return ctx.set.status=500,{success:!1,error:"Failed to get product"}}}),app.delete("/products/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};if(!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden: operator privileges required"};try{let[existing]=await database.select().from(prodTable).where(eq59(prodTable.id,ctx.params.id)).limit(1);if(!existing)return ctx.set.status=404,{success:!1,error:"Product not found"};if(existing.providerProductId)await provider.archiveProduct({providerProductId:existing.providerProductId});let[updated]=await database.update(prodTable).set({status:"archived"}).where(eq59(prodTable.id,ctx.params.id)).returning();return{success:!0,data:updated}}catch{return ctx.set.status=500,{success:!1,error:"Failed to archive product"}}}),app.post("/prices",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};if(!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden: operator privileges required"};let body=ctx.body;if(!body.productId||body.unitAmount===void 0||!body.currency)return ctx.set.status=400,{success:!1,error:"productId, unitAmount, and currency are required"};try{let[product]=await database.select().from(prodTable).where(eq59(prodTable.id,body.productId)).limit(1);if(!product)return ctx.set.status=404,{success:!1,error:"Product not found"};let providerResult=await provider.createPrice({providerProductId:product.providerProductId,currency:body.currency,unitAmount:body.unitAmount,type:body.type,billingScheme:body.billingScheme,nickname:body.nickname,recurring:body.recurring,transformQuantity:body.transformQuantity,unitAmountDecimal:body.unitAmountDecimal,metadata:body.metadata});if(!providerResult.success)return ctx.set.status=400,{success:!1,error:providerResult.errorMessage??"Failed to create price at provider",errorCode:providerResult.errorCode};let[saved]=await database.insert(priceTable).values({productId:body.productId,provider:provider.name,providerPriceId:providerResult.providerPriceId,currency:body.currency,unitAmount:body.unitAmount,unitAmountDecimal:body.unitAmountDecimal??null,type:body.type??"one_time",billingScheme:body.billingScheme??"per_unit",nickname:body.nickname??null,recurringInterval:body.recurring?.interval??null,recurringIntervalCount:body.recurring?.intervalCount??1,recurringUsageType:body.recurring?.usageType??"licensed",recurringAggregateUsage:body.recurring?.aggregateUsage??null,transformQuantityDivideBy:body.transformQuantity?.divideBy??null,transformQuantityRound:body.transformQuantity?.round??null,status:"active",metadata:body.metadata?JSON.stringify(body.metadata):"{}"}).returning();return logger2.info("[Payment] Price created",{id:saved.id,providerPriceId:providerResult.providerPriceId}),{success:!0,data:saved}}catch(error3){return logger2.error("[Payment] create price error",{error:error3 instanceof Error?error3.message:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to create price"}}}),app.put("/prices/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};if(!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden: operator privileges required"};let body=ctx.body;try{let[existing]=await database.select().from(priceTable).where(eq59(priceTable.id,ctx.params.id)).limit(1);if(!existing)return ctx.set.status=404,{success:!1,error:"Price not found"};if(existing.providerPriceId){let providerResult=await provider.updatePrice({providerPriceId:existing.providerPriceId,nickname:body.nickname,active:body.status==="active"?!0:body.status==="archived"?!1:void 0,metadata:body.metadata});if(!providerResult.success)logger2.warn("[Payment] Provider price update failed",{errorCode:providerResult.errorCode})}let updateData={};if(body.nickname!==void 0)updateData.nickname=body.nickname;if(body.status)updateData.status=body.status;if(body.metadata)updateData.metadata=JSON.stringify(body.metadata);let[updated]=await database.update(priceTable).set(updateData).where(eq59(priceTable.id,ctx.params.id)).returning();return{success:!0,data:updated}}catch{return ctx.set.status=500,{success:!1,error:"Failed to update price"}}}),app.get("/prices",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let url=new URL(ctx.request.url),productId=url.searchParams.get("productId"),status=url.searchParams.get("status"),query=database.select().from(priceTable).where(eq59(priceTable.isActive,!0));if(productId&&status)query=database.select().from(priceTable).where(and21(eq59(priceTable.productId,productId),eq59(priceTable.status,status),eq59(priceTable.isActive,!0)));else if(productId)query=database.select().from(priceTable).where(and21(eq59(priceTable.productId,productId),eq59(priceTable.isActive,!0)));else if(status)query=database.select().from(priceTable).where(and21(eq59(priceTable.status,status),eq59(priceTable.isActive,!0)));return{success:!0,data:{items:await query.orderBy(priceTable.createdAt)}}}catch{return ctx.set.status=500,{success:!1,error:"Failed to list prices"}}}),app.get("/prices/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let[item]=await database.select().from(priceTable).where(eq59(priceTable.id,ctx.params.id)).limit(1);if(!item)return ctx.set.status=404,{success:!1,error:"Price not found"};return{success:!0,data:item}}catch{return ctx.set.status=500,{success:!1,error:"Failed to get price"}}}),app.delete("/prices/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};if(!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden: operator privileges required"};try{let[existing]=await database.select().from(priceTable).where(eq59(priceTable.id,ctx.params.id)).limit(1);if(!existing)return ctx.set.status=404,{success:!1,error:"Price not found"};if(existing.providerPriceId)await provider.archivePrice({providerPriceId:existing.providerPriceId});let[updated]=await database.update(priceTable).set({status:"archived"}).where(eq59(priceTable.id,ctx.params.id)).returning();return{success:!0,data:updated}}catch{return ctx.set.status=500,{success:!1,error:"Failed to archive price"}}}),app.post("/customers",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let body=ctx.body,result=await provider.createCustomer({email:body.email,name:body.name,phone:body.phone,description:body.description,metadata:body.metadata,address:body.address?{line1:body.address?.line1,line2:body.address?.line2,city:body.address?.city,state:body.address?.state,postalCode:body.address?.postalCode,country:body.address?.country}:void 0,taxId:body.taxId});if(!result.success)return ctx.set.status=400,result;let[row]=await database.insert(cusTable).values({user_id:userId,provider:provider.name,provider_customer_id:result.providerCustomerId,email:body.email,name:body.name??null,phone:body.phone??null,description:body.description??null,address:body.address??{},tax_id_type:body.taxId?.type??null,tax_id_value:body.taxId?.value??null,metadata:body.metadata??{}}).returning();return{success:!0,customer:row,providerCustomerId:result.providerCustomerId}}catch(error3){return logger2.error("[Payment] Create customer error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to create customer"}}}),app.put("/customers/:id",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,body=ctx.body,[existing]=await database.select().from(cusTable).where(eq59(cusTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Customer not found"};if(String(existing.user_id)!==String(userId)&&!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden"};let result=await provider.updateCustomer({providerCustomerId:existing.provider_customer_id,email:body.email,name:body.name,phone:body.phone,description:body.description,metadata:body.metadata,address:body.address?{line1:body.address?.line1,line2:body.address?.line2,city:body.address?.city,state:body.address?.state,postalCode:body.address?.postalCode,country:body.address?.country}:void 0});if(!result.success)return ctx.set.status=400,result;let updates={};if(body.email)updates.email=body.email;if(body.name!==void 0)updates.name=body.name;if(body.phone!==void 0)updates.phone=body.phone;if(body.description!==void 0)updates.description=body.description;if(body.address)updates.address=body.address;if(body.metadata)updates.metadata=body.metadata;let[updated]=await database.update(cusTable).set(updates).where(eq59(cusTable.id,id)).returning();return{success:!0,customer:updated}}catch(error3){return logger2.error("[Payment] Update customer error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to update customer"}}}),app.get("/customers",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{return{success:!0,customers:await database.select().from(cusTable).where(eq59(cusTable.user_id,userId))}}catch(error3){return logger2.error("[Payment] List customers error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to list customers"}}}),app.get("/customers/:id",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,[customer]=await database.select().from(cusTable).where(eq59(cusTable.id,id));if(!customer)return ctx.set.status=404,{success:!1,error:"Customer not found"};if(String(customer.user_id)!==String(userId)&&!hasGodminRole(ctx.request))return ctx.set.status=404,{success:!1,error:"Customer not found"};return{success:!0,customer}}catch(error3){return logger2.error("[Payment] Get customer error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to get customer"}}}),app.delete("/customers/:id",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,[existing]=await database.select().from(cusTable).where(eq59(cusTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Customer not found"};if(String(existing.user_id)!==String(userId)&&!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden"};return await provider.deleteCustomer({providerCustomerId:existing.provider_customer_id}),await database.delete(cusTable).where(eq59(cusTable.id,id)),{success:!0}}catch(error3){return logger2.error("[Payment] Delete customer error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to delete customer"}}}),app.post("/subscriptions",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let body=ctx.body,customerId=body.customerId,[customer]=await database.select().from(cusTable).where(eq59(cusTable.id,customerId));if(!customer)return ctx.set.status=404,{success:!1,error:"Customer not found"};if(String(customer.user_id)!==String(userId)&&!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden"};let items=body.items,result=await provider.createSubscription({providerCustomerId:customer.provider_customer_id,items,trialPeriodDays:body.trialPeriodDays,collectionMethod:body.collectionMethod,daysUntilDue:body.daysUntilDue,cancelAtPeriodEnd:body.cancelAtPeriodEnd,metadata:body.metadata,defaultPaymentMethod:body.defaultPaymentMethod});if(!result.success)return ctx.set.status=400,result;let[row]=await database.insert(subTable).values({customer_id:customerId,provider:provider.name,provider_subscription_id:result.providerSubscriptionId,status:result.status??"incomplete",collection_method:body.collectionMethod??"charge_automatically",current_period_start:result.currentPeriodStart?new Date(result.currentPeriodStart):null,current_period_end:result.currentPeriodEnd?new Date(result.currentPeriodEnd):null,cancel_at_period_end:body.cancelAtPeriodEnd??!1,items,metadata:body.metadata??{}}).returning();return{success:!0,subscription:row,clientSecret:result.clientSecret}}catch(error3){return logger2.error("[Payment] Create subscription error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to create subscription"}}}),app.put("/subscriptions/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,body=ctx.body,[existing]=await database.select().from(subTable).where(eq59(subTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Subscription not found"};if(!await customerBelongsToCaller(ctx.request,existing.customer_id))return ctx.set.status=403,{success:!1,error:"Forbidden"};let result=await provider.updateSubscription({providerSubscriptionId:existing.provider_subscription_id,items:body.items,cancelAtPeriodEnd:body.cancelAtPeriodEnd,metadata:body.metadata,collectionMethod:body.collectionMethod,daysUntilDue:body.daysUntilDue,defaultPaymentMethod:body.defaultPaymentMethod,prorationBehavior:body.prorationBehavior});if(!result.success)return ctx.set.status=400,result;let updates={};if(result.status)updates.status=result.status;if(body.cancelAtPeriodEnd!==void 0)updates.cancel_at_period_end=body.cancelAtPeriodEnd;if(body.items)updates.items=body.items;if(body.metadata)updates.metadata=body.metadata;if(body.collectionMethod)updates.collection_method=body.collectionMethod;let[updated]=await database.update(subTable).set(updates).where(eq59(subTable.id,id)).returning();return{success:!0,subscription:updated}}catch(error3){return logger2.error("[Payment] Update subscription error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to update subscription"}}}),app.post("/subscriptions/:id/cancel",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,body=ctx.body??{},[existing]=await database.select().from(subTable).where(eq59(subTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Subscription not found"};if(!await customerBelongsToCaller(ctx.request,existing.customer_id))return ctx.set.status=403,{success:!1,error:"Forbidden"};let result=await provider.cancelSubscription({providerSubscriptionId:existing.provider_subscription_id,cancelAtPeriodEnd:body.cancelAtPeriodEnd,invoiceNow:body.invoiceNow,prorate:body.prorate});if(!result.success)return ctx.set.status=400,result;let updates={status:result.status??"canceled",canceled_at:new Date};if(body.cancelAtPeriodEnd)updates.cancel_at_period_end=!0;let[updated]=await database.update(subTable).set(updates).where(eq59(subTable.id,id)).returning();return{success:!0,subscription:updated}}catch(error3){return logger2.error("[Payment] Cancel subscription error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to cancel subscription"}}}),app.get("/subscriptions",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let query=ctx.query,conditions=[];if(query.customerId)conditions.push(eq59(subTable.customer_id,query.customerId));if(query.status)conditions.push(eq59(subTable.status,query.status));if(!hasGodminRole(ctx.request)){let ids=await callerCustomerIds(userId);if(ids.length===0)return{success:!0,subscriptions:[]};conditions.push(inArray17(subTable.customer_id,ids))}return{success:!0,subscriptions:conditions.length>0?await database.select().from(subTable).where(and21(...conditions)):await database.select().from(subTable)}}catch(error3){return logger2.error("[Payment] List subscriptions error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to list subscriptions"}}}),app.get("/subscriptions/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,[subscription]=await database.select().from(subTable).where(eq59(subTable.id,id));if(!subscription)return ctx.set.status=404,{success:!1,error:"Subscription not found"};if(!await customerBelongsToCaller(ctx.request,subscription.customer_id))return ctx.set.status=403,{success:!1,error:"Forbidden"};return{success:!0,subscription}}catch(error3){return logger2.error("[Payment] Get subscription error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to get subscription"}}}),app.post("/usage-records",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let body=ctx.body,result=await provider.reportUsage({subscriptionItemId:body.subscriptionItemId,quantity:body.quantity,timestamp:body.timestamp,action:body.action});if(!result.success)return ctx.set.status=400,result;return{success:!0,usageRecord:result}}catch(error3){return logger2.error("[Payment] Report usage error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to report usage"}}}),app.get("/usage-records/:subscriptionItemId/summaries",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{subscriptionItemId}=ctx.params,query=ctx.query,result=await provider.listUsageRecordSummaries({subscriptionItemId,limit:query.limit?parseInt(query.limit,10):void 0,startingAfter:query.startingAfter});if(!result.success)return ctx.set.status=400,result;return{success:!0,summaries:result.summaries,hasMore:result.hasMore}}catch(error3){return logger2.error("[Payment] List usage summaries error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to list usage summaries"}}}),app.post("/invoices",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let body=ctx.body,customerId=body.customerId,[customer]=await database.select().from(cusTable).where(eq59(cusTable.id,customerId));if(!customer)return ctx.set.status=404,{success:!1,error:"Customer not found"};if(String(customer.user_id)!==String(userId)&&!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden"};let result=await provider.createInvoice({providerCustomerId:customer.provider_customer_id,collectionMethod:body.collectionMethod,daysUntilDue:body.daysUntilDue,description:body.description,metadata:body.metadata,autoAdvance:body.autoAdvance,items:body.items});if(!result.success)return ctx.set.status=400,result;let[row]=await database.insert(invTable).values({customer_id:customerId,subscription_id:body.subscriptionId??null,provider:provider.name,provider_invoice_id:result.providerInvoiceId,status:result.status??"draft",collection_method:body.collectionMethod??"charge_automatically",currency:body.currency??defaultCurrency,description:body.description??null,hosted_invoice_url:result.hostedInvoiceUrl??null,invoice_pdf:result.invoicePdf??null,days_until_due:body.daysUntilDue??null,lines:body.items??[],metadata:body.metadata??{}}).returning();return{success:!0,invoice:row,providerInvoiceId:result.providerInvoiceId}}catch(error3){return logger2.error("[Payment] Create invoice error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to create invoice"}}}),app.post("/invoices/:id/finalize",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,body=ctx.body??{},[existing]=await database.select().from(invTable).where(eq59(invTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Invoice not found"};if(!await customerBelongsToCaller(ctx.request,existing.customer_id))return ctx.set.status=403,{success:!1,error:"Forbidden"};let result=await provider.finalizeInvoice({providerInvoiceId:existing.provider_invoice_id,autoAdvance:body.autoAdvance});if(!result.success)return ctx.set.status=400,result;let[updated]=await database.update(invTable).set({status:result.status??"open",hosted_invoice_url:result.hostedInvoiceUrl??existing.hosted_invoice_url,invoice_pdf:result.invoicePdf??existing.invoice_pdf}).where(eq59(invTable.id,id)).returning();return{success:!0,invoice:updated}}catch(error3){return logger2.error("[Payment] Finalize invoice error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to finalize invoice"}}}),app.post("/invoices/:id/send",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,[existing]=await database.select().from(invTable).where(eq59(invTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Invoice not found"};if(!await customerBelongsToCaller(ctx.request,existing.customer_id))return ctx.set.status=403,{success:!1,error:"Forbidden"};let result=await provider.sendInvoice({providerInvoiceId:existing.provider_invoice_id});if(!result.success)return ctx.set.status=400,result;return{success:!0}}catch(error3){return logger2.error("[Payment] Send invoice error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to send invoice"}}}),app.post("/invoices/:id/void",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,[existing]=await database.select().from(invTable).where(eq59(invTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Invoice not found"};if(!await customerBelongsToCaller(ctx.request,existing.customer_id))return ctx.set.status=403,{success:!1,error:"Forbidden"};let result=await provider.voidInvoice({providerInvoiceId:existing.provider_invoice_id});if(!result.success)return ctx.set.status=400,result;let[updated]=await database.update(invTable).set({status:"void",voided_at:new Date}).where(eq59(invTable.id,id)).returning();return{success:!0,invoice:updated}}catch(error3){return logger2.error("[Payment] Void invoice error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to void invoice"}}}),app.post("/invoices/:id/pay",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,body=ctx.body??{},[existing]=await database.select().from(invTable).where(eq59(invTable.id,id));if(!existing)return ctx.set.status=404,{success:!1,error:"Invoice not found"};if(!await customerBelongsToCaller(ctx.request,existing.customer_id))return ctx.set.status=403,{success:!1,error:"Forbidden"};let result=await provider.payInvoice({providerInvoiceId:existing.provider_invoice_id,paymentMethod:body.paymentMethod});if(!result.success)return ctx.set.status=400,result;let[updated]=await database.update(invTable).set({status:result.status??"paid",amount_paid:result.amountPaid??existing.amount_paid,amount_due:result.amountDue??existing.amount_due,paid_at:new Date}).where(eq59(invTable.id,id)).returning();return{success:!0,invoice:updated}}catch(error3){return logger2.error("[Payment] Pay invoice error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to pay invoice"}}}),app.get("/invoices",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let query=ctx.query,conditions=[];if(query.customerId)conditions.push(eq59(invTable.customer_id,query.customerId));if(query.subscriptionId)conditions.push(eq59(invTable.subscription_id,query.subscriptionId));if(query.status)conditions.push(eq59(invTable.status,query.status));if(!hasGodminRole(ctx.request)){let ids=await callerCustomerIds(userId);if(ids.length===0)return{success:!0,invoices:[]};conditions.push(inArray17(invTable.customer_id,ids))}return{success:!0,invoices:conditions.length>0?await database.select().from(invTable).where(and21(...conditions)):await database.select().from(invTable)}}catch(error3){return logger2.error("[Payment] List invoices error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to list invoices"}}}),app.get("/invoices/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let{id}=ctx.params,[invoice]=await database.select().from(invTable).where(eq59(invTable.id,id));if(!invoice)return ctx.set.status=404,{success:!1,error:"Invoice not found"};if(!await customerBelongsToCaller(ctx.request,invoice.customer_id))return ctx.set.status=403,{success:!1,error:"Forbidden"};return{success:!0,invoice}}catch(error3){return logger2.error("[Payment] Get invoice error",{error:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to get invoice"}}}),subMerchantsEnabled)app.post("/sub-merchants",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};let body=ctx.body;if(!body.name||!body.email||!body.subMerchantType)return ctx.set.status=400,{success:!1,error:"name, email, and subMerchantType are required"};try{let externalId=body.externalId??`sm-${Date.now().toString(36)}`,result=await provider.registerSubMerchant({locale:body.locale??defaultLocale,subMerchantExternalId:externalId,subMerchantType:body.subMerchantType,name:body.name,email:body.email,gsmNumber:body.gsmNumber,address:body.address,iban:body.iban,contactName:body.contactName,contactSurname:body.contactSurname,identityNumber:body.identityNumber,taxOffice:body.taxOffice,taxNumber:body.taxNumber,legalCompanyTitle:body.legalCompanyTitle,currency:body.currency??defaultCurrency});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to register sub-merchant",errorCode:result.errorCode};let[saved]=await database.insert(smTable).values({userId:hasGodminRole(ctx.request)?body.userId??userId:userId,provider:provider.name,providerSubMerchantKey:result.subMerchantKey,externalId,type:body.subMerchantType,status:"active",name:body.name,email:body.email,gsmNumber:body.gsmNumber??null,address:body.address??null,iban:body.iban??null,contactName:body.contactName??null,contactSurname:body.contactSurname??null,identityNumber:body.identityNumber??null,taxOffice:body.taxOffice??null,taxNumber:body.taxNumber??null,legalCompanyTitle:body.legalCompanyTitle??null,currency:body.currency??defaultCurrency,commissionRate:hasGodminRole(ctx.request)?body.commissionRate??0:0}).returning();return logger2.info("[Payment] Sub-merchant registered",{externalId,providerKey:result.subMerchantKey}),{success:!0,data:saved}}catch(error3){return logger2.error("[Payment] register sub-merchant error",{error:error3 instanceof Error?error3.message:String(error3)}),ctx.set.status=500,{success:!1,error:"Failed to register sub-merchant"}}}),app.put("/sub-merchants/:id",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};let body=ctx.body;try{let[existing]=await database.select().from(smTable).where(eq59(smTable.id,ctx.params.id)).limit(1);if(!existing)return ctx.set.status=404,{success:!1,error:"Sub-merchant not found"};let smIsGodmin=hasGodminRole(ctx.request);if(String(existing.userId)!==String(userId)&&!smIsGodmin)return ctx.set.status=403,{success:!1,error:"Forbidden"};if(existing.providerSubMerchantKey){let providerResult=await provider.updateSubMerchant({locale:body.locale??defaultLocale,subMerchantKey:existing.providerSubMerchantKey,name:body.name,email:body.email,gsmNumber:body.gsmNumber,address:body.address,iban:body.iban,contactName:body.contactName,contactSurname:body.contactSurname,identityNumber:body.identityNumber,taxOffice:body.taxOffice,taxNumber:body.taxNumber,legalCompanyTitle:body.legalCompanyTitle,currency:body.currency});if(!providerResult.success)logger2.warn("[Payment] Provider sub-merchant update failed",{errorCode:providerResult.errorCode})}let updateData={};if(body.name)updateData.name=body.name;if(body.email)updateData.email=body.email;if(body.gsmNumber!==void 0)updateData.gsmNumber=body.gsmNumber;if(body.address!==void 0)updateData.address=body.address;if(body.iban!==void 0)updateData.iban=body.iban;if(body.contactName!==void 0)updateData.contactName=body.contactName;if(body.contactSurname!==void 0)updateData.contactSurname=body.contactSurname;if(body.identityNumber!==void 0)updateData.identityNumber=body.identityNumber;if(body.taxOffice!==void 0)updateData.taxOffice=body.taxOffice;if(body.taxNumber!==void 0)updateData.taxNumber=body.taxNumber;if(body.legalCompanyTitle!==void 0)updateData.legalCompanyTitle=body.legalCompanyTitle;if(body.currency!==void 0)updateData.currency=body.currency;if(body.commissionRate!==void 0&&smIsGodmin)updateData.commissionRate=body.commissionRate;if(body.status!==void 0&&smIsGodmin)updateData.status=body.status;let[updated]=await database.update(smTable).set(updateData).where(eq59(smTable.id,ctx.params.id)).returning();return{success:!0,data:updated}}catch{return ctx.set.status=500,{success:!1,error:"Failed to update sub-merchant"}}}),app.get("/sub-merchants",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let smListGodmin=hasGodminRole(ctx.request);return{success:!0,data:{items:await database.select().from(smTable).where(smListGodmin?eq59(smTable.isActive,!0):and21(eq59(smTable.isActive,!0),eq59(smTable.userId,userId))).orderBy(smTable.createdAt)}}}catch{return ctx.set.status=500,{success:!1,error:"Failed to list sub-merchants"}}}),app.get("/sub-merchants/:id",async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId)return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let[item]=await database.select().from(smTable).where(eq59(smTable.id,ctx.params.id)).limit(1);if(!item)return ctx.set.status=404,{success:!1,error:"Sub-merchant not found"};if(String(item.userId)!==String(userId)&&!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden"};return{success:!0,data:item}}catch{return ctx.set.status=500,{success:!1,error:"Failed to get sub-merchant"}}}),app.post("/splits/:splitId/approve",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};if(!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden: operator privileges required"};try{let[split]=await database.select().from(csTable).where(eq59(csTable.id,ctx.params.splitId)).limit(1);if(!split)return ctx.set.status=404,{success:!1,error:"Split not found"};if(split.status!=="pending")return ctx.set.status=400,{success:!1,error:`Split already ${split.status}`};if(split.providerSplitId){let result=await provider.approveSplit({locale:defaultLocale,paymentTransactionId:split.providerSplitId});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Provider approval failed",errorCode:result.errorCode}}let[updated]=await database.update(csTable).set({status:"approved",approvedAt:new Date}).where(eq59(csTable.id,ctx.params.splitId)).returning();return logger2.info("[Payment] Split approved",{splitId:ctx.params.splitId}),{success:!0,data:updated}}catch{return ctx.set.status=500,{success:!1,error:"Failed to approve split"}}}),app.post("/splits/:splitId/disapprove",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};if(!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden: operator privileges required"};try{let[split]=await database.select().from(csTable).where(eq59(csTable.id,ctx.params.splitId)).limit(1);if(!split)return ctx.set.status=404,{success:!1,error:"Split not found"};if(split.status!=="pending")return ctx.set.status=400,{success:!1,error:`Split already ${split.status}`};if(split.providerSplitId){let result=await provider.disapproveSplit({locale:defaultLocale,paymentTransactionId:split.providerSplitId});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Provider disapproval failed",errorCode:result.errorCode}}let[updated]=await database.update(csTable).set({status:"disapproved",disapprovedAt:new Date}).where(eq59(csTable.id,ctx.params.splitId)).returning();return logger2.info("[Payment] Split disapproved",{splitId:ctx.params.splitId}),{success:!0,data:updated}}catch{return ctx.set.status=500,{success:!1,error:"Failed to disapprove split"}}}),app.get("/splits",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};if(!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden: operator privileges required"};try{let url=new URL(ctx.request.url),transactionId=url.searchParams.get("transactionId"),subMerchantId=url.searchParams.get("subMerchantId"),query=database.select().from(csTable);if(transactionId&&subMerchantId)query=query.where(and21(eq59(csTable.transactionId,transactionId),eq59(csTable.subMerchantId,subMerchantId)));else if(transactionId)query=query.where(eq59(csTable.transactionId,transactionId));else if(subMerchantId)query=query.where(eq59(csTable.subMerchantId,subMerchantId));return{success:!0,data:{items:await query.orderBy(csTable.createdAt)}}}catch{return ctx.set.status=500,{success:!1,error:"Failed to list splits"}}});return app.get("/balance",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let result=await provider.getBalance();if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to get balance"};return{success:!0,data:{available:result.available,pending:result.pending,connectReserved:result.connectReserved}}}catch{return ctx.set.status=500,{success:!1,error:"Failed to get balance"}}}),app.post("/payouts",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};if(!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden: operator privileges required"};try{let body=ctx.body,payoutAmt=validateAmount(body.amount,"amount");if(!payoutAmt.ok)return ctx.set.status=400,{success:!1,error:payoutAmt.error};if(!isValidCurrency(body.currency))return ctx.set.status=400,{success:!1,error:"currency must be a 3-letter code"};let result=await provider.createPayout({amount:payoutAmt.value,currency:body.currency??defaultCurrency,destination:body.destination,description:body.description,metadata:body.metadata,method:body.method,sourceType:body.sourceType,statementDescriptor:body.statementDescriptor});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to create payout"};return{success:!0,data:result}}catch{return ctx.set.status=500,{success:!1,error:"Failed to create payout"}}}),app.get("/payouts",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let url=new URL(ctx.request.url),result=await provider.listPayouts({status:url.searchParams.get("status")??void 0,destination:url.searchParams.get("destination")??void 0,limit:url.searchParams.get("limit")?Number(url.searchParams.get("limit")):void 0,startingAfter:url.searchParams.get("startingAfter")??void 0});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to list payouts"};return{success:!0,data:{payouts:result.payouts,hasMore:result.hasMore}}}catch{return ctx.set.status=500,{success:!1,error:"Failed to list payouts"}}}),app.get("/payouts/:id",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let result=await provider.getPayout({providerPayoutId:ctx.params.id});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to get payout"};return{success:!0,data:result}}catch{return ctx.set.status=500,{success:!1,error:"Failed to get payout"}}}),app.post("/payouts/:id/cancel",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};if(!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden: operator privileges required"};try{let result=await provider.cancelPayout({providerPayoutId:ctx.params.id});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to cancel payout"};return{success:!0,data:result}}catch{return ctx.set.status=500,{success:!1,error:"Failed to cancel payout"}}}),app.post("/transfers",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};if(!hasGodminRole(ctx.request))return ctx.set.status=403,{success:!1,error:"Forbidden: operator privileges required"};try{let body=ctx.body,transferAmt=validateAmount(body.amount,"amount");if(!transferAmt.ok)return ctx.set.status=400,{success:!1,error:transferAmt.error};if(!isValidCurrency(body.currency))return ctx.set.status=400,{success:!1,error:"currency must be a 3-letter code"};let result=await provider.createTransfer({amount:transferAmt.value,currency:body.currency??defaultCurrency,destination:body.destination,description:body.description,metadata:body.metadata,sourceTransaction:body.sourceTransaction,transferGroup:body.transferGroup});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to create transfer"};return{success:!0,data:result}}catch{return ctx.set.status=500,{success:!1,error:"Failed to create transfer"}}}),app.get("/transfers",async(ctx)=>{if(!ctx.request.headers.get("x-user-id"))return ctx.set.status=401,{success:!1,error:"Unauthorized"};try{let url=new URL(ctx.request.url),result=await provider.listTransfers({destination:url.searchParams.get("destination")??void 0,transferGroup:url.searchParams.get("transferGroup")??void 0,limit:url.searchParams.get("limit")?Number(url.searchParams.get("limit")):void 0,startingAfter:url.searchParams.get("startingAfter")??void 0});if(!result.success)return ctx.set.status=400,{success:!1,error:result.errorMessage??"Failed to list transfers"};return{success:!0,data:{transfers:result.transfers,hasMore:result.hasMore}}}catch{return ctx.set.status=500,{success:!1,error:"Failed to list transfers"}}}),app.options("/callback",()=>{return new Response(null,{headers:{"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET,POST,OPTIONS","Access-Control-Allow-Headers":"Content-Type"}})}),registerStripeWebhookRoute(app,{provider,webhookSecret:config.webhookSecret,db:database,webhookLogsTable:whTable,transactionsTable:txTable,getPayoutService:config.getPayoutService,logger:logger2}),app};var init_payment=__esm(()=>{init_adminGuard();init_webhook()});var requireUser=(ctx)=>ctx.request.headers.get("x-user-id"),isAdmin=(ctx)=>decodeHeaderList(ctx.request.headers.get("x-user-roles")).some((r2)=>isGodminRole(r2)),canReadOwnerLedger=(ctx,ownerType,ownerId)=>{if(isAdmin(ctx))return!0;let userId=ctx.request.headers.get("x-user-id");return!!userId&&ownerType==="user"&&!!ownerId&&ownerId===userId},failResponse=(ctx,status,message)=>{return ctx.set.status=status,{success:!1,message,data:null}};var init_types22=__esm(()=>{init_Authorization()});import{Elysia as Elysia48,t as t40}from"elysia";function createPayoutRoutes(config){let base=`${config.basePath}/marketplace`,app=new Elysia48;return app.post(`${base}/payout-requests`,async(ctx)=>{let svc=config.getPayoutService();if(!svc)return failResponse(ctx,503,"Marketplace not available");let userId=requireUser(ctx);if(!userId)return failResponse(ctx,401,"Authentication required");let body=ctx.body;if(!canReadOwnerLedger(ctx,body.recipientOwnerType,body.recipientOwnerId))return failResponse(ctx,403,"Forbidden: cannot request a payout for another owner's balance");try{return{success:!0,message:"Payout requested",data:await svc.requestPayout({...body,requestedBy:userId})}}catch(err){return failResponse(ctx,400,err instanceof Error?err.message:"Failed")}},{body:t40.Object({recipientOwnerId:t40.String(),recipientOwnerType:t40.Optional(t40.String()),amount:t40.Number(),currency:t40.Optional(t40.String()),destination:t40.Optional(t40.String()),requestedBy:t40.Optional(t40.String())}),detail:{tags:["Payments Marketplace"],summary:"Request a payout"}}),app.get(`${base}/payout-requests`,async(ctx)=>{let svc=config.getPayoutService();if(!svc)return failResponse(ctx,503,"Marketplace not available");let userId=requireUser(ctx);if(!userId)return failResponse(ctx,401,"Authentication required");let url=new URL(ctx.request.url),requestedOwnerId=url.searchParams.get("recipientOwnerId")??void 0,recipientOwnerId=isAdmin(ctx)?requestedOwnerId:userId,items=await svc.listPayoutRequests({recipientOwnerId,status:url.searchParams.get("status")??void 0});return{success:!0,message:`Found ${items.length} payout requests`,data:{items}}}),app.get(`${base}/payout-requests/:id`,async(ctx)=>{let svc=config.getPayoutService();if(!svc)return failResponse(ctx,503,"Marketplace not available");if(!requireUser(ctx))return failResponse(ctx,401,"Authentication required");let record3=await svc.getPayoutRequest(ctx.params.id);if(!record3)return failResponse(ctx,404,"Payout request not found");let r2=record3;if(!canReadOwnerLedger(ctx,r2.recipientOwnerType,r2.recipientOwnerId))return failResponse(ctx,404,"Payout request not found");return{success:!0,message:"Payout request",data:record3}}),app.post(`${base}/payout-requests/:id/approve`,async(ctx)=>{let svc=config.getPayoutService();if(!svc)return failResponse(ctx,503,"Marketplace not available");let userId=requireUser(ctx);if(!userId)return failResponse(ctx,401,"Authentication required");if(!isAdmin(ctx))return failResponse(ctx,403,"Forbidden: operator privileges required");try{let record3=await svc.approvePayout(ctx.params.id,{deciderId:userId});if(!record3)return failResponse(ctx,404,"Payout request not found");return{success:!0,message:"Payout approved",data:record3}}catch(err){return failResponse(ctx,400,err instanceof Error?err.message:"Failed")}}),app.post(`${base}/payout-requests/:id/reject`,async(ctx)=>{let svc=config.getPayoutService();if(!svc)return failResponse(ctx,503,"Marketplace not available");let userId=requireUser(ctx);if(!userId)return failResponse(ctx,401,"Authentication required");if(!isAdmin(ctx))return failResponse(ctx,403,"Forbidden: operator privileges required");let record3=await svc.rejectPayout(ctx.params.id,userId);if(!record3)return failResponse(ctx,404,"Payout request not found");return{success:!0,message:"Payout rejected",data:record3}}),app.post(`${base}/disputes`,async(ctx)=>{let svc=config.getPayoutService();if(!svc)return failResponse(ctx,503,"Marketplace not available");if(!requireUser(ctx))return failResponse(ctx,401,"Authentication required");if(!isAdmin(ctx))return failResponse(ctx,403,"Forbidden: operator privileges required");let body=ctx.body;return{success:!0,message:"Dispute opened",data:await svc.openDispute(body)}},{body:t40.Object({provider:t40.String(),transactionId:t40.Optional(t40.String()),providerDisputeId:t40.Optional(t40.String()),ownerType:t40.Optional(t40.String()),ownerId:t40.Optional(t40.String()),amount:t40.Optional(t40.Number()),currency:t40.Optional(t40.String()),reason:t40.Optional(t40.String())}),detail:{tags:["Payments Marketplace"],summary:"Open a dispute"}}),app.get(`${base}/disputes`,async(ctx)=>{let svc=config.getPayoutService();if(!svc)return failResponse(ctx,503,"Marketplace not available");let userId=requireUser(ctx);if(!userId)return failResponse(ctx,401,"Authentication required");let url=new URL(ctx.request.url),requestedOwnerId=url.searchParams.get("ownerId")??void 0,ownerId=isAdmin(ctx)?requestedOwnerId:userId,items=await svc.listDisputes({ownerId,status:url.searchParams.get("status")??void 0});return{success:!0,message:`Found ${items.length} disputes`,data:{items}}}),app.post(`${base}/disputes/:id/resolve`,async(ctx)=>{let svc=config.getPayoutService();if(!svc)return failResponse(ctx,503,"Marketplace not available");if(!requireUser(ctx))return failResponse(ctx,401,"Authentication required");if(!isAdmin(ctx))return failResponse(ctx,403,"Forbidden: operator privileges required");let body=ctx.body,record3=await svc.resolveDispute(ctx.params.id,body.outcome);if(!record3)return failResponse(ctx,404,"Dispute not found");return{success:!0,message:"Dispute resolved",data:record3}},{body:t40.Object({outcome:t40.Union([t40.Literal("won"),t40.Literal("lost"),t40.Literal("accepted"),t40.Literal("cancelled")])}),detail:{tags:["Payments Marketplace"],summary:"Resolve a dispute"}}),app}var init_payouts=__esm(()=>{init_types22()});import{Elysia as Elysia49,t as t41}from"elysia";function createSplitRoutes(config){let base=`${config.basePath}/marketplace`,app=new Elysia49;return app.post(`${base}/splits`,async(ctx)=>{let svc=config.getMarketplaceService();if(!svc)return failResponse(ctx,503,"Marketplace not available");if(!requireUser(ctx))return failResponse(ctx,401,"Authentication required");if(!isAdmin(ctx))return failResponse(ctx,403,"Forbidden: operator privileges required");let body=ctx.body;try{return{success:!0,message:"Split recorded",data:await svc.recordSplit(body)}}catch(err){return failResponse(ctx,400,err instanceof Error?err.message:"Failed")}},{body:t41.Object({recipientOwnerId:t41.String(),recipientOwnerType:t41.Optional(t41.String()),provider:t41.String(),grossAmount:t41.Number(),providerFeeAmount:t41.Optional(t41.Number()),platformFeeAmount:t41.Number(),currency:t41.Optional(t41.String()),transactionId:t41.Optional(t41.String()),sourceType:t41.Optional(t41.String()),sourceId:t41.Optional(t41.String()),settlementDelayDays:t41.Optional(t41.Number()),reserveRate:t41.Optional(t41.Number()),isNewSeller:t41.Optional(t41.Boolean())}),detail:{tags:["Payments Marketplace"],summary:"Record a payment split"}}),app.get(`${base}/splits`,async(ctx)=>{let svc=config.getMarketplaceService();if(!svc)return failResponse(ctx,503,"Marketplace not available");let userId=requireUser(ctx);if(!userId)return failResponse(ctx,401,"Authentication required");let url=new URL(ctx.request.url),requestedOwnerId=url.searchParams.get("recipientOwnerId")??void 0,recipientOwnerId=isAdmin(ctx)?requestedOwnerId:userId,items=await svc.listSplits({recipientOwnerId,status:url.searchParams.get("status")??void 0});return{success:!0,message:`Found ${items.length} splits`,data:{items}}}),app.get(`${base}/balance/:ownerId`,async(ctx)=>{let svc=config.getMarketplaceService();if(!svc)return failResponse(ctx,503,"Marketplace not available");if(!requireUser(ctx))return failResponse(ctx,401,"Authentication required");let url=new URL(ctx.request.url),ownerType=url.searchParams.get("ownerType")??"seller",ownerId=ctx.params.ownerId;if(!canReadOwnerLedger(ctx,ownerType,ownerId))return failResponse(ctx,403,"Forbidden: cannot read another owner's balance");return{success:!0,message:"Balance",data:await svc.getBalance(ownerType,ownerId,url.searchParams.get("currency")??void 0)}}),app.post(`${base}/reserves/:id/release`,async(ctx)=>{let svc=config.getMarketplaceService();if(!svc)return failResponse(ctx,503,"Marketplace not available");if(!requireUser(ctx))return failResponse(ctx,401,"Authentication required");if(!isAdmin(ctx))return failResponse(ctx,403,"Forbidden: operator privileges required");if(!await svc.releaseReserve(ctx.params.id))return failResponse(ctx,400,"Reserve not found or not held");return{success:!0,message:"Reserve released",data:{released:!0}}}),app.get(`${base}/settlement-policy`,async(ctx)=>{let svc=config.getMarketplaceService();if(!svc)return failResponse(ctx,503,"Marketplace not available");if(!requireUser(ctx))return failResponse(ctx,401,"Authentication required");let url=new URL(ctx.request.url),ownerType=url.searchParams.get("ownerType")??"tenant",ownerId=url.searchParams.get("ownerId")??"";if(!canReadOwnerLedger(ctx,ownerType,ownerId))return failResponse(ctx,403,"Forbidden: cannot read this settlement policy");return{success:!0,message:"Settlement policy",data:await svc.getSettlementPolicy(ownerType,ownerId)}}),app.post(`${base}/settlement-policy`,async(ctx)=>{let svc=config.getMarketplaceService();if(!svc)return failResponse(ctx,503,"Marketplace not available");if(!requireUser(ctx))return failResponse(ctx,401,"Authentication required");if(!isAdmin(ctx))return failResponse(ctx,403,"Forbidden: operator privileges required");let body=ctx.body;return{success:!0,message:"Settlement policy saved",data:await svc.upsertSettlementPolicy(body)}},{body:t41.Object({ownerType:t41.String(),ownerId:t41.String(),defaultDelayDays:t41.Optional(t41.Number()),newSellerDelayDays:t41.Optional(t41.Number()),reserveRate:t41.Optional(t41.Number()),reserveDays:t41.Optional(t41.Number()),minimumPayoutAmount:t41.Optional(t41.Number()),currency:t41.Optional(t41.String()),earlyPayoutEnabled:t41.Optional(t41.Boolean())}),detail:{tags:["Payments Marketplace"],summary:"Upsert settlement policy"}}),app}var init_splits=__esm(()=>{init_types22()});var exports_marketplace={};__export(exports_marketplace,{createMarketplaceRoutes:()=>createMarketplaceRoutes});function createMarketplaceRoutes(app,config){return app.use(createSplitRoutes(config)),app.use(createPayoutRoutes(config)),app}var init_marketplace=__esm(()=>{init_payouts();init_splits()});var exports_schemaReconcile={};__export(exports_schemaReconcile,{undeclaredTables:()=>undeclaredTables,reconcileMissingColumns:()=>reconcileMissingColumns,readActualSchema:()=>readActualSchema,planRepair:()=>planRepair,findDrift:()=>findDrift,expectedFromTables:()=>expectedFromTables,describeRepair:()=>describeRepair,createMissingTables:()=>createMissingTables,addColumnStatement:()=>addColumnStatement});import{getTableColumns,sql as sql12}from"drizzle-orm";function findDrift(expected,actual){let missingTables=[],missingColumns=[];for(let table of expected){let have=actual[table.name];if(!have){missingTables.push(table.name);continue}for(let column of table.columns)if(!have.has(column.name))missingColumns.push({table:table.name,column})}return{missingTables,missingColumns}}function addColumnStatement(schema3,table,column){if(column.notNull&&!column.hasDefault)return null;return[`alter table "${schema3}"."${table}"`,`add column if not exists "${column.name}" ${column.sqlType}`].join(" ")}function planRepair(schema3,drift){let statements=[],unsafe3=[];for(let{table,column}of drift.missingColumns){let statement=addColumnStatement(schema3,table,column);if(statement)statements.push(statement);else unsafe3.push({table,column:column.name,why:"declared NOT NULL with no default, and the table already has rows to fill"})}return{statements,unsafe:unsafe3,missingTables:drift.missingTables,createdTables:[],undeclaredTables:[]}}function undeclaredTables(expected,actual){let declared=new Set(expected.map((t42)=>t42.name));return Object.keys(actual).filter((name2)=>!declared.has(name2)).sort()}function isAlreadyExists(error3){let code=error3?.code;if(typeof code==="string"&&ALREADY_EXISTS.has(code))return!0;let message=error3 instanceof Error?error3.message:String(error3);return/already exists/i.test(message)}async function createMissingTables(options){let{run,tables,missing,schemaObject,logger:logger2,timeoutMs=60000}=options;if(missing.length===0)return{applied:0,errors:[]};let wanted=new Set(missing),imports={};for(let[key2,table]of Object.entries(tables)){if(!table||typeof table!=="object")continue;let name2=tableNameOf(table);if(name2&&wanted.has(name2))imports[key2]=table}if(schemaObject)imports.__nucleusSchema=schemaObject;let statements;try{let{generateDrizzleJson,generateMigration}=await import("drizzle-kit/api"),realExit=process.exit;try{process.exit=(code)=>{throw Error(`drizzle-kit called process.exit(${code??0}) while generating table DDL`)},statements=await withDeadline(generateMigration(generateDrizzleJson({}),generateDrizzleJson(imports)),timeoutMs,`generating CREATE TABLE statements did not finish within ${timeoutMs}ms`)}finally{process.exit=realExit}}catch(error3){let message=error3 instanceof Error?error3.message:String(error3);return logger2.error(`[Schema] CREATE TABLE statements could not be generated: ${message}`),{applied:0,errors:[message]}}let applied=0,errors3=[];for(let statement of statements)try{await run(statement),applied+=1}catch(error3){if(isAlreadyExists(error3))continue;let message=error3 instanceof Error?error3.message:String(error3);errors3.push(message),logger2.error(`[Schema] could not apply generated DDL: ${statement} \u2014 ${message}`)}return{applied,errors:errors3}}function describeRepair(plan,applied){let lines=[];if(applied>0)lines.push(`[Schema] The push applied nothing, so ${applied} missing column(s) were added directly. `+"This is additive only \u2014 nothing was dropped or altered.");if(plan.createdTables.length>0)lines.push(`[Schema] ${plan.createdTables.length} table(s) the push did not create were created directly: ${plan.createdTables.join(", ")}. Verified present in the database afterwards, not assumed from the statements that ran.`);if(plan.missingTables.length>0){if(lines.push(`[Schema] ${plan.missingTables.length} table(s) the code expects still do not exist: ${plan.missingTables.join(", ")}. Every read of these will fail. The additive repair tried `+"and could not create them \u2014 this needs a human."),plan.undeclaredTables.length>0)lines.push(`[Schema] The push is ambiguous because the database has ${plan.undeclaredTables.length} table(s) the model does not declare: ${plan.undeclaredTables.join(", ")}. drizzle-kit cannot tell a new table from a rename of one of these, and cannot ask without a TTY. Drop the stale one, or declare it, and the push stops aborting.`)}for(let item of plan.unsafe)lines.push(`[Schema] "${item.table}"."${item.column}" could not be added: ${item.why}. Give the column a default, or add it by hand with a backfill.`);return lines}function expectedFromTables(tables){let out=[];for(let table of Object.values(tables)){if(!table||typeof table!=="object")continue;let columns;try{columns=getTableColumns(table)}catch{continue}let first=Object.values(columns)[0],name2=tableNameOf(table);if(!name2||!first)continue;out.push({name:name2,columns:Object.values(columns).map((column)=>{let c=column;return{name:c.name,sqlType:typeof c.getSQLType==="function"?c.getSQLType():"text",notNull:c.notNull===!0,hasDefault:c.hasDefault===!0}})})}return out}function tableNameOf(table){for(let key2 of Object.getOwnPropertySymbols(table))if(String(key2).includes("Name")&&!String(key2).includes("Schema")){let value2=table[key2];if(typeof value2==="string"&&value2.length>0)return value2}return null}async function readActualSchema(execute,schema3){let result=await execute(`select table_name, column_name from information_schema.columns where table_schema = '${schema3.replace(/'/g,"''")}'`),rows=Array.isArray(result)?result:result.rows??[],actual={};for(let row of rows){if(!row.table_name||!row.column_name)continue;(actual[row.table_name]??=new Set).add(row.column_name)}return actual}async function reconcileMissingColumns(options){let{db,schema:schema3,tables,logger:logger2,schemaObject}=options,run=(statement)=>db.execute(sql12.raw(statement));try{let expected=expectedFromTables(tables);if(expected.length===0)return null;let actual=await readActualSchema(run,schema3),drift=findDrift(expected,actual),plan=planRepair(schema3,drift);if(plan.undeclaredTables=undeclaredTables(expected,actual),drift.missingTables.length>0){await createMissingTables({run,tables,missing:drift.missingTables,schemaObject,logger:logger2});let after=await readActualSchema(run,schema3);plan.createdTables=drift.missingTables.filter((name2)=>after[name2]),plan.missingTables=drift.missingTables.filter((name2)=>!after[name2])}let applied=0;for(let statement of plan.statements)try{await run(statement),applied+=1}catch(error3){logger2.error(`[Schema] could not add a missing column: ${statement} \u2014 ${error3 instanceof Error?error3.message:String(error3)}`)}for(let line of describeRepair(plan,applied))if(plan.missingTables.length>0||plan.unsafe.length>0)logger2.error(line);else logger2.info(line);return{applied,plan}}catch(error3){return logger2.error(`[Schema] the additive repair could not run: ${error3 instanceof Error?error3.message:String(error3)}`),null}}var ALREADY_EXISTS;var init_schemaReconcile=__esm(()=>{ALREADY_EXISTS=new Set(["42P06","42P07","42710","42723","23505"])});var exports_relaxSessionExpiry={};__export(exports_relaxSessionExpiry,{relaxSessionExpiryIfNever:()=>relaxSessionExpiryIfNever});async function relaxSessionExpiryIfNever(params){let{db,sql:sql13,schemaName,lifetimeSeconds:lifetimeSeconds2,logger:logger2}=params,tableName=params.tableName??"user_sessions";if(lifetimeSeconds2!==null)return{action:"skipped",reason:"lifetime-is-bounded"};if(!SAFE_IDENTIFIER.test(schemaName)||!SAFE_IDENTIFIER.test(tableName))return logger2?.warn(`[Schema] Refusing to touch "${schemaName}"."${tableName}" \u2014 the name has characters that cannot be safely quoted.`),{action:"skipped",reason:"unsafe-identifier"};try{let current=await db.execute(sql13`
|
|
532
|
+
select is_nullable from information_schema.columns
|
|
533
|
+
where table_schema = ${schemaName}
|
|
534
|
+
and table_name = ${tableName}
|
|
535
|
+
and column_name = 'expires_at'
|
|
536
|
+
`),first=((Array.isArray(current)?current:current?.rows)??[])[0];if(!first)return{action:"already-nullable"};if(first.is_nullable==="YES")return{action:"already-nullable"};return await db.execute(sql13.raw(`ALTER TABLE "${schemaName}"."${tableName}" ALTER COLUMN "expires_at" DROP NOT NULL`)),logger2?.info(`[Schema] "${schemaName}"."${tableName}".expires_at may now be empty \u2014 this install runs sessions that never expire, and a session with no expiry is a row with no expiry.`),{action:"relaxed"}}catch(error3){let reason=error3 instanceof Error?error3.message:String(error3);return logger2?.warn(`[Schema] Could not let "${schemaName}"."${tableName}".expires_at be empty: ${reason}. Sign-in will fail with "Missing required field: expires_at" until this column allows nulls.`),{action:"failed",reason}}}var SAFE_IDENTIFIER;var init_relaxSessionExpiry=__esm(()=>{SAFE_IDENTIFIER=/^[A-Za-z_][A-Za-z0-9_]*$/});function normSegment(input){return input.toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/_+/g,"_").replace(/^_|_$/g,"")}function normPath(path8){return normSegment(path8.replace(/\{[^}]+\}/g,(m2)=>m2.slice(1,-1)))}function shortHash(input){let h=5381;for(let i=0;i<input.length;i++)h=(h*33^input.charCodeAt(i))>>>0;return h.toString(36)}function capAction(action,max=100){if(action.length<=max)return action;let suffix=`_${shortHash(action)}`;return action.slice(0,Math.max(1,max-suffix.length))+suffix}function resourceFromPath(path8){let segs=path8.split("/").filter(Boolean).filter((s)=>!s.startsWith("{"));for(let s of segs){if(s==="api"||/^v\d+$/i.test(s))continue;return normSegment(s)}return normSegment(segs[0]??"root")}function matchesExclude(path8,patterns3){if(!patterns3?.length)return!1;for(let raw of patterns3){let p=raw.trim();if(!p)continue;if(p.endsWith("/*")){let prefix=p.slice(0,-2);if(path8===prefix||path8.startsWith(`${prefix}/`))return!0}else if(p.endsWith("*")){if(path8.startsWith(p.slice(0,-1)))return!0}else if(path8===p)return!0}return!1}function parseOpenApiToClaims(serviceId,doc,opts={}){let sid=normSegment(serviceId);if(!sid)throw Error("endpointDiscovery: serviceId is empty after normalization");if(RESERVED_SERVICE_IDS.has(sid))throw Error(`endpointDiscovery: serviceId "${serviceId}" collides with an HTTP-method claim prefix; pick another id`);let specs=[],seen=new Set,paths=doc.paths??{};for(let[path8,ops]of Object.entries(paths)){if(!ops||matchesExclude(path8,opts.exclude))continue;for(let method of HTTP_METHODS2){let op=ops[method];if(!op)continue;let tag=(op.tags?.[0]?normSegment(op.tags[0]):"")||resourceFromPath(path8),opToken=(op.operationId?normSegment(op.operationId):"")||`${method}_${normPath(path8)}`,action=capAction(`${sid}.${tag||"root"}.${opToken||method}`);if(seen.has(action)){action=capAction(`${action}_${shortHash(`${method} ${path8}`)}`);while(seen.has(action))action=capAction(`${action}_${shortHash(action)}`)}seen.add(action),specs.push({action,path:path8,method:method.toUpperCase(),description:op.summary||op.description||`${method.toUpperCase()} ${path8}`})}}return specs}function diffClaims(existing,specs){let specByAction=new Map(specs.map((s)=>[s.action,s])),existByAction=new Map(existing.map((e)=>[e.action,e]));return{toInsert:specs.filter((s)=>!existByAction.has(s.action)),toReactivate:specs.filter((s)=>existByAction.get(s.action)?.isActive===!1),toDeactivate:existing.filter((e)=>e.isActive&&!specByAction.has(e.action)),unchanged:specs.filter((s)=>existByAction.get(s.action)?.isActive===!0)}}async function fetchOpenApi(baseUrl,openapiPath,fetchImpl=fetch){let url=`${baseUrl.replace(/\/$/,"")}${openapiPath.startsWith("/")?"":"/"}${openapiPath}`,res=await fetchImpl(url);if(!res.ok)throw Error(`endpointDiscovery: OpenAPI fetch failed ${res.status} for ${url}`);return await res.json()}var HTTP_METHODS2,RESERVED_SERVICE_IDS;var init_EndpointDiscovery=__esm(()=>{HTTP_METHODS2=["get","post","put","patch","delete"],RESERVED_SERVICE_IDS=new Set(["get","post","put","patch","delete","toggle","bulk"])});var exports_seed={};__export(exports_seed,{seedDiscoveredClaims:()=>seedDiscoveredClaims,runEndpointDiscovery:()=>runEndpointDiscovery,getRouteManifest:()=>getRouteManifest,getRoleClaimsManifest:()=>getRoleClaimsManifest});import{eq as eq60,like as like2}from"drizzle-orm";function col16(table,name2){return table[name2]}async function seedDiscoveredClaims(db,claimsTable,serviceId,specs,logger2){let actionCol=col16(claimsTable,"action"),prefix=specs[0]?.action.split(".")[0]??serviceId.toLowerCase(),existing=(await db.select().from(claimsTable).where(like2(actionCol,`${prefix}.%`))).map((r2)=>({action:String(r2.action),isActive:r2.isActive!==!1,path:String(r2.path??""),method:String(r2.method??""),description:String(r2.description??"")})),plan=diffClaims(existing,specs);for(let s of plan.toInsert)await db.insert(claimsTable).values({action:s.action,path:s.path,method:s.method,description:s.description});for(let s of plan.toReactivate)await db.update(claimsTable).set({isActive:!0,path:s.path,method:s.method,description:s.description}).where(eq60(actionCol,s.action));for(let e of plan.toDeactivate)await db.update(claimsTable).set({isActive:!1}).where(eq60(actionCol,e.action));let summary={added:plan.toInsert.length,reactivated:plan.toReactivate.length,deactivated:plan.toDeactivate.length,unchanged:plan.unchanged.length,total:specs.length};return logger2.info(`[Discovery] Reconciled "${serviceId}"`,summary),summary}async function runEndpointDiscovery(db,schemaTables,config,logger2,fetchImpl=fetch){let claimsTable=schemaTables.claims,services=config.services??[],results=[];if(!claimsTable)return logger2.warn("[Discovery] No claims table in schema; skipping endpoint discovery"),{services:[]};for(let svc of services)try{let doc=await fetchOpenApi(svc.baseUrl,svc.openapi??"/openapi.json",fetchImpl),specs=parseOpenApiToClaims(svc.id,doc,{exclude:svc.exclude}),summary=await seedDiscoveredClaims(db,claimsTable,svc.id,specs,logger2);results.push({id:svc.id,...summary})}catch(err){let message=err instanceof Error?err.message:String(err);logger2.error(`[Discovery] Service "${svc.id}" discovery failed`,{error:message}),results.push({id:svc.id,added:0,reactivated:0,deactivated:0,unchanged:0,total:0,error:message})}return{services:results}}async function getRouteManifest(db,claimsTable,serviceId){return(await db.select().from(claimsTable).where(like2(col16(claimsTable,"action"),`${serviceId.toLowerCase()}.%`))).filter((r2)=>r2.isActive!==!1).map((r2)=>({action:String(r2.action),path:String(r2.path??""),method:String(r2.method??"")}))}async function getRoleClaimsManifest(db,schemaTables,serviceId){let{roles:rolesTable,claims:claimsTable}=schemaTables,roleClaimsTable=schemaTables.roleClaims??schemaTables.role_claims;if(!rolesTable||!claimsTable||!roleClaimsTable)return{};let sid=serviceId.toLowerCase(),claimRows=await db.select().from(claimsTable),claimIdToAction=new Map;for(let c of claimRows){if(c.isActive===!1)continue;let action=String(c.action??"");if(action===sid||action.startsWith(`${sid}.`))claimIdToAction.set(String(c.id),action)}if(claimIdToAction.size===0)return{};let roleRows=await db.select().from(rolesTable),roleIdToName=new Map;for(let r2 of roleRows)roleIdToName.set(String(r2.id),String(r2.name??""));let rcRows=await db.select().from(roleClaimsTable),out={};for(let rc of rcRows){if(rc.isActive===!1)continue;let action=claimIdToAction.get(String(rc.claimId??rc.claim_id)),roleName=roleIdToName.get(String(rc.roleId??rc.role_id));if(!action||!roleName)continue;(out[roleName]??=[]).push(action)}return out}var init_seed=__esm(()=>{init_EndpointDiscovery()});var OPS_BY_TYPE;var init_types23=__esm(()=>{OPS_BY_TYPE={int:["gt","gte","lt","lte","eq","ne"],boolean:["eq","ne"],string:["eq","ne"]}});function isRecord(v){return typeof v==="object"&&v!==null}function guardActionFromName(name2){let brace=name2.indexOf("{");return(brace>=0?name2.slice(0,brace):name2).replace(/:$/,"")}function parseGuardCatalogEntry(entry){if(!isRecord(entry))return null;let name2=typeof entry.name==="string"?entry.name.trim():"";if(!name2)return null;let valueType=entry.value;if(typeof valueType!=="string"||!VALUE_TYPES.includes(valueType))return null;let action=guardActionFromName(name2);if(!action)return null;return{action,policy:{kind:"guard",keyTemplate:name2,valueType}}}function parseGuardPolicy(raw){if(!isRecord(raw)||raw.kind!=="guard")return null;if(typeof raw.keyTemplate!=="string"||!raw.keyTemplate)return null;let vt=raw.valueType;if(typeof vt!=="string"||!VALUE_TYPES.includes(vt))return null;return{kind:"guard",keyTemplate:raw.keyTemplate,valueType:vt}}function resolveGuardKey(keyTemplate,ctx){return keyTemplate.replaceAll("{userId}",ctx.userId).replaceAll("{tenant}",ctx.tenant??"default")}function coerceThreshold(value2,type4){if(type4==="int"){if(value2==null)return null;if(typeof value2==="boolean"||typeof value2==="symbol")return null;if(typeof value2==="string"&&value2.trim()==="")return null;if(typeof value2==="object")return null;let n2=Number(value2);return Number.isFinite(n2)?n2:null}if(type4==="boolean"){if(typeof value2==="boolean")return value2;if(value2==="true"||value2===1||value2==="1")return!0;if(value2==="false"||value2===0||value2==="0")return!1;return null}return value2==null?null:String(value2)}function parseGuardCondition(scope,valueType){let raw=scope;if(typeof scope==="string")try{raw=JSON.parse(scope)}catch{return null}if(!isRecord(raw))return null;let op=raw.op;if(typeof op!=="string"||!OPS_BY_TYPE[valueType].includes(op))return null;let value2=coerceThreshold(raw.value,valueType);if(value2===null)return null;let invalidates=Array.isArray(raw.invalidates)?raw.invalidates.filter((a12)=>typeof a12==="string"&&a12.length>0):[];return{op,value:value2,invalidates}}function coerceStateValue(raw,type4){if(raw==null)return null;let v=isRecord(raw)&&"data"in raw?raw.data:raw;if(v==null)return null;if(typeof v==="object")return null;if(type4==="int"&&typeof v==="string"&&v.trim()==="")return null;return coerceThreshold(v,type4)}function guardConditionHolds(rawValue,valueType,condition){let actual=coerceStateValue(rawValue,valueType);if(actual===null)return!1;let target2=condition.value;switch(condition.op){case"gt":return actual>target2;case"gte":return actual>=target2;case"lt":return actual<target2;case"lte":return actual<=target2;case"eq":return actual===target2;case"ne":return actual!==target2;default:return!1}}function parseClaimGuardCatalog(entries){if(!entries?.length)return[];let out=[],seen=new Set;for(let e of entries){let parsed=parseGuardCatalogEntry(e);if(parsed&&!seen.has(parsed.action))seen.add(parsed.action),out.push(parsed)}return out}var VALUE_TYPES;var init_evaluate=__esm(()=>{init_types23();VALUE_TYPES=["int","boolean","string"]});async function resolveClaimGuards(db,schemaTables,userId,read,ctx={}){let claimsTable=schemaTables.claims,roleClaimsTable=schemaTables.roleClaims??schemaTables.role_claims,userRolesTable=schemaTables.userRoles??schemaTables.user_roles;if(!claimsTable||!roleClaimsTable||!userRolesTable)return EMPTY;let claimRows=await db.select().from(claimsTable),guardByClaimId=new Map;for(let c of claimRows){if(c.isActive===!1)continue;let policy=parseGuardPolicy(c.policy);if(policy)guardByClaimId.set(String(c.id),{action:String(c.action??""),policy})}if(guardByClaimId.size===0)return EMPTY;let urRows=await db.select().from(userRolesTable),roleIds=new Set(urRows.filter((r2)=>r2.isActive!==!1&&String(r2.userId??r2.user_id)===userId).map((r2)=>String(r2.roleId??r2.role_id)));if(roleIds.size===0)return EMPTY;let rcRows=await db.select().from(roleClaimsTable),guards=[],suppressed=new Set,firedGuards=[],stateCache=new Map;for(let rc of rcRows){if(rc.isActive===!1)continue;if(!roleIds.has(String(rc.roleId??rc.role_id)))continue;let guard4=guardByClaimId.get(String(rc.claimId??rc.claim_id));if(!guard4)continue;let condition=parseGuardCondition(rc.scope,guard4.policy.valueType);if(!condition)continue;let key2=resolveGuardKey(guard4.policy.keyTemplate,{userId,tenant:ctx.tenant}),value2;if(stateCache.has(key2))value2=stateCache.get(key2);else value2=await read(key2).catch(()=>null),stateCache.set(key2,value2);let holds=guardConditionHolds(value2,guard4.policy.valueType,condition),current=normalizeCurrent(value2,guard4.policy.valueType);if(guards.push({action:guard4.action,key:key2,valueType:guard4.policy.valueType,op:condition.op,threshold:condition.value,current,invalidates:condition.invalidates,holds}),holds&&condition.invalidates.length>0){for(let a12 of condition.invalidates)suppressed.add(a12);firedGuards.push({action:guard4.action,key:key2,invalidates:condition.invalidates})}}return{guards,suppressedClaims:[...suppressed],firedGuards}}function normalizeCurrent(raw,type4){if(raw==null)return null;let v=typeof raw==="object"&&raw!==null&&"data"in raw?raw.data:raw;if(v==null)return null;if(type4==="int"){let n2=Number(v);return Number.isFinite(n2)?n2:null}if(type4==="boolean")return v===!0||v==="true"||v===1||v==="1";return String(v)}var EMPTY;var init_resolve=__esm(()=>{init_evaluate();EMPTY={guards:[],suppressedClaims:[],firedGuards:[]}});import{eq as eq61}from"drizzle-orm";async function seedClaimGuards(db,schemaTables,claimGuards,logger2){let claimsTable=schemaTables.claims;if(!claimsTable)return{created:0,updated:0,deactivated:0};let actionCol=claimsTable.action,desired=parseClaimGuardCatalog(claimGuards),desiredByAction=new Map(desired.map((d)=>[d.action,d.policy])),existing=await db.select().from(claimsTable),existingGuardActions=new Set,result={created:0,updated:0,deactivated:0};for(let row of existing){if(!parseGuardPolicy(row.policy))continue;let action=String(row.action??"");existingGuardActions.add(action);let want=desiredByAction.get(action);if(!want){if(row.isActive!==!1)await db.update(claimsTable).set({isActive:!1}).where(eq61(actionCol,action)),result.deactivated++;continue}let current=row.policy;if(JSON.stringify(current)!==JSON.stringify(want)||row.isActive===!1)await db.update(claimsTable).set({policy:want,isActive:!0,path:want.keyTemplate,method:"GUARD"}).where(eq61(actionCol,action)),result.updated++}for(let{action,policy}of desired){if(existingGuardActions.has(action))continue;await db.insert(claimsTable).values({action,description:`ClaimGuard [${policy.valueType}] key=${policy.keyTemplate}`,path:policy.keyTemplate,method:"GUARD",policy,isActive:!0}),result.created++}return logger2?.info?.(`[Authorization] ClaimGuards seeded (created=${result.created}, updated=${result.updated}, deactivated=${result.deactivated})`),result}var init_seed2=__esm(()=>{init_evaluate()});var exports_ClaimGuard={};__export(exports_ClaimGuard,{seedClaimGuards:()=>seedClaimGuards,resolveGuardKey:()=>resolveGuardKey,resolveClaimGuards:()=>resolveClaimGuards,parseGuardPolicy:()=>parseGuardPolicy,parseGuardCondition:()=>parseGuardCondition,parseGuardCatalogEntry:()=>parseGuardCatalogEntry,parseClaimGuardCatalog:()=>parseClaimGuardCatalog,guardConditionHolds:()=>guardConditionHolds,guardActionFromName:()=>guardActionFromName,OPS_BY_TYPE:()=>OPS_BY_TYPE});var init_ClaimGuard=__esm(()=>{init_evaluate();init_resolve();init_seed2();init_types23()});var exports_dbStorage={};__export(exports_dbStorage,{createDbWebAuthnStorage:()=>createDbWebAuthnStorage});import{and as and22,eq as eq62,isNull as isNull4}from"drizzle-orm";function rowToRecord(row){return{id:row.id,userId:row.userId,credentialId:row.credentialId,publicKey:row.publicKey,counter:typeof row.counter==="bigint"?Number(row.counter):Number(row.counter??0),transports:parseTransports(row.transports),deviceType:parseDeviceType(row.deviceType),backedUp:row.backedUp,aaguid:row.aaguid,authenticatorAttachment:row.authenticatorAttachment==="platform"||row.authenticatorAttachment==="cross-platform"?row.authenticatorAttachment:null,nickname:row.nickname,lastUsedAt:row.lastUsedAt,revokedAt:row.revokedAt,createdAt:row.createdAt}}function col17(table,key2){return table[key2]}function createDbWebAuthnStorage(deps){let{db,resolveTable}=deps,credentialsName="webauthnCredentials",challengesName="webauthnChallenges";return{storeChallenge:async(challenge,schemaName)=>{let table=resolveTable("webauthnChallenges",schemaName);if(!table)return;await db.insert(table).values({userId:challenge.userId??null,challenge:challenge.challenge,challengeType:challenge.challengeType,expiresAt:challenge.expiresAt})},consumeChallenge:async(challenge,challengeType,schemaName)=>{let table=resolveTable("webauthnChallenges",schemaName);if(!table)return null;let row=(await db.update(table).set({consumedAt:new Date}).where(and22(eq62(col17(table,"challenge"),challenge),eq62(col17(table,"challengeType"),challengeType),isNull4(col17(table,"consumedAt")))).returning())[0];if(!row)return null;return{challenge:row.challenge,challengeType:row.challengeType,userId:row.userId,expiresAt:row.expiresAt}},listCredentialsByUser:async(userId,schemaName)=>{let table=resolveTable("webauthnCredentials",schemaName);if(!table)return[];return(await db.select().from(table).where(eq62(col17(table,"userId"),userId))).map(rowToRecord)},findCredentialById:async(credentialId,schemaName)=>{let table=resolveTable("webauthnCredentials",schemaName);if(!table)return null;let rows=await db.select().from(table).where(eq62(col17(table,"credentialId"),credentialId)).limit(1);return rows[0]?rowToRecord(rows[0]):null},insertCredential:async(record3,schemaName)=>{let table=resolveTable("webauthnCredentials",schemaName);if(!table)throw Error("webauthn_credentials table not configured");let row=(await db.insert(table).values({userId:record3.userId,credentialId:record3.credentialId,publicKey:record3.publicKey,counter:record3.counter,transports:record3.transports??null,deviceType:record3.deviceType??null,backedUp:record3.backedUp,aaguid:record3.aaguid??null,authenticatorAttachment:record3.authenticatorAttachment??null,nickname:record3.nickname??null}).returning())[0];if(!row)throw Error("Failed to insert webauthn credential");return rowToRecord(row)},updateCredentialCounter:async(credentialId,counter,schemaName)=>{let table=resolveTable("webauthnCredentials",schemaName);if(!table)return;await db.update(table).set({counter,lastUsedAt:new Date}).where(eq62(col17(table,"credentialId"),credentialId))},revokeCredential:async(credentialId,userId,schemaName)=>{let table=resolveTable("webauthnCredentials",schemaName);if(!table)return!1;return(await db.update(table).set({revokedAt:new Date}).where(and22(eq62(col17(table,"credentialId"),credentialId),eq62(col17(table,"userId"),userId))).returning()).length>0},renameCredential:async(credentialId,userId,nickname,schemaName)=>{let table=resolveTable("webauthnCredentials",schemaName);if(!table)return!1;return(await db.update(table).set({nickname}).where(and22(eq62(col17(table,"credentialId"),credentialId),eq62(col17(table,"userId"),userId))).returning()).length>0}}}var init_dbStorage=()=>{};function isValidUploadId(id){return typeof id==="string"&&/^[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$/i.test(id)}function offsetVerdict(input){let{declaredOffset,actualOffset,chunkBytes,totalSize}=input;if(!Number.isFinite(declaredOffset)||declaredOffset<0)return{ok:!1,reason:"offset_mismatch",expected:actualOffset};if(declaredOffset!==actualOffset)return{ok:!1,reason:"offset_mismatch",expected:actualOffset};if(actualOffset+chunkBytes>totalSize)return{ok:!1,reason:"too_long",expected:actualOffset};return{ok:!0}}function isComplete(actualOffset,totalSize){return actualOffset===totalSize&&totalSize>0}function sessionRefusal(input){let{session,callerId,fingerprint,now}=input;if(!session)return"not_found";if(!callerId||session.owner!==callerId)return"not_yours";if(now-session.createdAt>86400000)return"expired";if(fingerprint!=null&&fingerprint!==session.fingerprint)return"wrong_file";return null}function isExpired(session,now){return now-session.createdAt>86400000}function sessionStatus(session,offset){return{uploadId:session.id,offset,size:session.size,originalName:session.originalName,complete:isComplete(offset,session.size)}}var SESSION_TTL_MS=86400000,CHUNK_SIZE_BYTES=8388608,MAX_CHUNK_BYTES=33554432;import{randomUUID as randomUUID8}from"crypto";import{mkdir as mkdir8,open as open2,readdir as readdir3,readFile as readFile2,rm as rm2,stat as stat8,writeFile as writeFile2}from"fs/promises";import path8 from"path";function createResumableStore(basePath){let root=path8.join(basePath,UPLOAD_DIR);function pathsFor(id){if(!isValidUploadId(id))return null;let part=path8.join(root,`${id}.part`),meta=path8.join(root,`${id}.json`);if(!isPathWithinBase(root,part)||!isPathWithinBase(root,meta))return null;return{part,meta}}async function create4(input,now){await mkdir8(root,{recursive:!0});let session={...input,id:randomUUID8(),createdAt:now},paths=pathsFor(session.id);if(!paths)throw Error("Generated upload id was rejected by its own validator");return await writeFile2(paths.meta,JSON.stringify(session),"utf8"),await writeFile2(paths.part,""),session}async function read(id){let paths=pathsFor(id);if(!paths)return null;try{let raw=await readFile2(paths.meta,"utf8"),parsed=JSON.parse(raw);if(!parsed||typeof parsed.owner!=="string"||typeof parsed.size!=="number")return null;return parsed}catch{return null}}async function offsetOf(id){let paths=pathsFor(id);if(!paths)return null;try{return(await stat8(paths.part)).size}catch{return null}}async function writeAt(id,offset,chunk){let paths=pathsFor(id);if(!paths)return null;let handle=await open2(paths.part,"r+");try{await handle.write(chunk,0,chunk.byteLength,offset)}finally{await handle.close()}return(await stat8(paths.part)).size}async function readAssembled(id){let paths=pathsFor(id);if(!paths)return null;try{return await readFile2(paths.part)}catch{return null}}function partPath(id){return pathsFor(id)?.part??null}async function discardMeta(id){let paths=pathsFor(id);if(!paths)return;await rm2(paths.meta,{force:!0})}async function discard2(id){let paths=pathsFor(id);if(!paths)return;await rm2(paths.part,{force:!0}),await rm2(paths.meta,{force:!0})}async function sweep(now){let removed=0,entries;try{entries=await readdir3(root)}catch{return 0}for(let entry of entries){if(!entry.endsWith(".json"))continue;let id=entry.slice(0,-5);try{let session=await read(id);if(session&&!isExpired(session,now))continue;await discard2(id),removed+=1}catch{}}return removed}return{create:create4,read,offsetOf,writeAt,readAssembled,partPath,discard:discard2,discardMeta,sweep,root}}var UPLOAD_DIR=".uploads";var init_store3=__esm(()=>{init_helpers2()});var exports_resumable={};__export(exports_resumable,{createResumableRoutes:()=>createResumableRoutes,SESSION_TTL_MS:()=>SESSION_TTL_MS,CHUNK_SIZE_BYTES:()=>CHUNK_SIZE_BYTES});import{Elysia as Elysia50,t as t42}from"elysia";function toBytes(body){if(body instanceof Uint8Array)return body;if(body instanceof ArrayBuffer)return new Uint8Array(body);if(ArrayBuffer.isView(body))return new Uint8Array(body.buffer,body.byteOffset,body.byteLength);if(typeof body==="string")return new TextEncoder().encode(body);return new Uint8Array(0)}function createResumableRoutes(config){let{basePath,storage,logger:logger2,getUserId:getUserId3,canUpload,register}=config,store=createResumableStore(basePath),plugin=new Elysia50({prefix:"/uploads"}),openSession=async(id,request,fingerprint)=>{let userId=getUserId3(request);if(!await canUpload(request))return{ok:!1,status:403,message:"You are not allowed to upload files."};let session=isValidUploadId(id)?await store.read(id):null,refusal=sessionRefusal({session,callerId:userId,fingerprint,now:Date.now()});if(refusal)return{ok:!1,status:REFUSAL_STATUS[refusal],message:REFUSAL_MESSAGE[refusal]};return{ok:!0,session,userId}};return plugin.post("/",async({body,request,set:set2})=>{let userId=getUserId3(request);if(!userId)return set2.status=401,{success:!1,message:"Sign in to upload."};if(!await canUpload(request))return set2.status=403,{success:!1,message:"You are not allowed to upload files."};if(!Number.isFinite(body.size)||body.size<=0)return set2.status=400,{success:!1,message:"A size is required to start an upload."};if(body.size>storage.maxFileSizeBytes)return set2.status=413,{success:!1,message:`This file is larger than the ${Math.round(storage.maxFileSizeBytes/1048576)} MB limit.`};if(storage.blockedMimeTypes?.includes(body.mimeType))return set2.status=415,{success:!1,message:"This kind of file cannot be uploaded."};if(storage.allowedMimeTypes?.length&&!storage.allowedMimeTypes.includes(body.mimeType))return set2.status=415,{success:!1,message:"This kind of file cannot be uploaded."};let session=await store.create({owner:userId,originalName:body.originalName,size:body.size,mimeType:body.mimeType,type:body.type??"file",fingerprint:body.fingerprint},Date.now());return set2.status=201,{success:!0,data:sessionStatus(session,0)}},{body:t42.Object({originalName:t42.String({minLength:1,maxLength:500}),size:t42.Number(),mimeType:t42.String({maxLength:200}),type:t42.Optional(t42.String({maxLength:40})),fingerprint:t42.String({minLength:1,maxLength:200})}),detail:{tags:["Storage"],summary:"Start a resumable upload"}}),plugin.get("/:id",async({params,request,set:set2})=>{let opened=await openSession(params.id,request);if(!opened.ok)return set2.status=opened.status,{success:!1,message:opened.message};let offset=await store.offsetOf(params.id)??0;return{success:!0,data:sessionStatus(opened.session,offset)}}),plugin.patch("/:id",async({params,request,body,set:set2})=>{let fingerprint=request.headers.get("upload-fingerprint"),opened=await openSession(params.id,request,fingerprint);if(!opened.ok)return set2.status=opened.status,{success:!1,message:opened.message};let declared=Number(request.headers.get("upload-offset")),actual=await store.offsetOf(params.id)??0,chunk=toBytes(body);if(chunk.byteLength>MAX_CHUNK_BYTES)return set2.status=413,{success:!1,message:`A single piece may not exceed ${MAX_CHUNK_BYTES/1048576} MB.`,data:{offset:actual}};let verdict=offsetVerdict({declaredOffset:declared,actualOffset:actual,chunkBytes:chunk.byteLength,totalSize:opened.session.size});if(!verdict.ok)return set2.status=409,{success:!1,message:verdict.reason==="too_long"?"This piece would take the file past the size it was started with.":"This piece does not continue where the file ends.",data:{offset:verdict.expected}};let offset=await store.writeAt(params.id,actual,chunk);if(offset===null)return set2.status=500,{success:!1,message:"The piece could not be written."};return{success:!0,data:sessionStatus(opened.session,offset)}},{detail:{tags:["Storage"],summary:"Append a piece"}}),plugin.post("/:id/complete",async({params,request,set:set2})=>{let opened=await openSession(params.id,request);if(!opened.ok)return set2.status=opened.status,{success:!1,message:opened.message};let offset=await store.offsetOf(params.id)??0;if(!isComplete(offset,opened.session.size))return set2.status=409,{success:!1,message:"The file is not complete yet.",data:sessionStatus(opened.session,offset)};let partPath=store.partPath(params.id);if(!partPath)return set2.status=500,{success:!1,message:"The assembled file could not be found."};let registered=await register({partPath,size:offset,originalName:opened.session.originalName,mimeType:opened.session.mimeType,type:opened.session.type,userId:opened.userId});if(!registered)return set2.status=500,{success:!1,message:"The file could not be registered. Try completing again."};return await store.discardMeta(params.id),logger2.info(`[Storage] Resumable upload finished: ${opened.session.originalName} (${offset} bytes)`),{success:!0,data:{id:registered.id}}}),plugin.delete("/:id",async({params,request,set:set2})=>{let opened=await openSession(params.id,request);if(!opened.ok)return set2.status=opened.status,{success:!1,message:opened.message};return await store.discard(params.id),{success:!0,data:{discarded:!0}}}),{plugin,sweep:(now)=>store.sweep(now)}}var REFUSAL_STATUS,REFUSAL_MESSAGE;var init_resumable=__esm(()=>{init_store3();REFUSAL_STATUS={not_found:404,not_yours:404,expired:410,wrong_file:409},REFUSAL_MESSAGE={not_found:"No such upload.",not_yours:"No such upload.",expired:"This upload was abandoned and has been cleaned up. Start it again.",wrong_file:"This is a different file from the one this upload started with."}});var exports_authorization={};__export(exports_authorization,{createAuthorizationDiscoveryRoutes:()=>createAuthorizationDiscoveryRoutes});import{timingSafeEqual as timingSafeEqual4}from"crypto";import{Elysia as Elysia51}from"elysia";function tokensMatch2(a12,b){let ba=Buffer.from(a12),bb=Buffer.from(b);if(ba.length!==bb.length)return!1;return timingSafeEqual4(ba,bb)}function createAuthorizationDiscoveryRoutes(cfg){let{db,schemaTables,logger:logger2,discovery,readState}=cfg,token=discovery.token||process.env.NUCLEUS_DISCOVERY_TOKEN,claimsTable=schemaTables.claims,manifestAuthorized=(request)=>{if(hasGodminRole(request))return!0;if(token){let presented=request.headers.get("x-discovery-token")??"";return tokensMatch2(presented,token)}return!1},routes=new Elysia51;routes.post("/authorization/discover",async({request,set:set2})=>{if(!hasGodminRole(request))return fail6(set2,403,"Forbidden: endpoint discovery requires godmin");if(!discovery.enabled)return fail6(set2,400,"endpointDiscovery is not enabled");return{success:!0,message:"Discovery completed",data:await runEndpointDiscovery(db,schemaTables,discovery,logger2)}}),routes.get("/authorization/route-manifest",async({request,query,set:set2})=>{if(!manifestAuthorized(request))return fail6(set2,403,"Forbidden: godmin or a valid x-discovery-token required");if(!claimsTable)return fail6(set2,503,"Claims table unavailable");let service=query.service;if(service){let rows=await getRouteManifest(db,claimsTable,service);return{success:!0,data:{service,routes:rows}}}let all={};for(let svc of discovery.services??[])all[svc.id]=await getRouteManifest(db,claimsTable,svc.id);return{success:!0,data:all}}),routes.get("/authorization/role-claims-manifest",async({request,query,set:set2})=>{if(!manifestAuthorized(request))return fail6(set2,403,"Forbidden: godmin or a valid x-discovery-token required");let service=query.service;if(!service)return fail6(set2,400,"service query param required");let map=await getRoleClaimsManifest(db,schemaTables,service);return{success:!0,data:{service,roleClaims:map}}});let authorizeGuardRead=(request,query,set2)=>{let callerId=request.headers.get("x-user-id")??"",isGodmin4=hasGodminRole(request),requested=query.userId;if(requested&&requested!==callerId&&!isGodmin4)return{error:fail6(set2,403,"Forbidden: only godmin can read another user's guards")};let targetUserId=requested&&isGodmin4?requested:callerId;if(!targetUserId)return{error:fail6(set2,401,"Unauthorized: no user context")};return{userId:targetUserId}},guardsHandler=async({request,query,set:set2})=>{let auth=authorizeGuardRead(request,query,set2);if("error"in auth)return auth.error;let tenant=request.headers.get("x-tenant-id")??void 0;if(!readState)return{success:!0,data:{userId:auth.userId,guards:[]}};let{guards}=await resolveClaimGuards(db,schemaTables,auth.userId,readState,{tenant});return{success:!0,data:{userId:auth.userId,guards}}};return routes.get("/authorization/guards",guardsHandler),routes.get("/authorization/quotas",guardsHandler),routes.get("/authorization/suppressed-claims",async({request,query,set:set2})=>{let auth=authorizeGuardRead(request,query,set2);if("error"in auth)return auth.error;if(!readState)return{success:!0,data:{userId:auth.userId,suppressedClaims:[],firedGuards:[]}};let tenant=request.headers.get("x-tenant-id")??void 0,{suppressedClaims,firedGuards}=await resolveClaimGuards(db,schemaTables,auth.userId,readState,{tenant});return{success:!0,data:{userId:auth.userId,suppressedClaims,firedGuards}}}),routes}var fail6=(set2,status,message)=>{return set2.status=status,{success:!1,message,data:null}};var init_authorization=__esm(()=>{init_ClaimGuard();init_seed();init_adminGuard()});var import_reflect_metadata2=__toESM(require_Reflect(),1);import{batch,createStore}from"h-state";import{useEffectEvent}from"react";function createInitialState(endpoints){let state={};for(let key of Object.keys(endpoints))state[key]={isPending:!1,data:null,error:null,code:null};return state}function createApiHook(endpoints,factory){let{useStore}=createStore(createInitialState(endpoints),{_callEndpoint:(store)=>async(endpointKey,options)=>{if(!store[endpointKey])return;batch(()=>{store[endpointKey].isPending=!0,store[endpointKey].error=null});try{let response=await factory(endpointKey,options.payload);if(batch(()=>{if(store[endpointKey].isPending=!1,store[endpointKey].code=response.code??null,response.isSuccess&&response.data!==void 0)store[endpointKey].data=response.data,store[endpointKey].error=null;else store[endpointKey].error=response.errors??null}),response.isSuccess)options.onAfterHandle?.(response.data??response);else options.onErrorHandle?.(response.errors??{message:"Request failed"},response.code)}catch(err){batch(()=>{store[endpointKey].isPending=!1,store[endpointKey].error={message:err instanceof Error?err.message:"Unknown error"}}),options.onErrorHandle?.({message:err instanceof Error?err.message:"Unknown error"},null)}}});return function(){let store=useStore(),callEndpoint=useEffectEvent((endpointKey,options)=>{store._callEndpoint(endpointKey,options)}),actions={};for(let key of Object.keys(endpoints)){let startFn=(options)=>{callEndpoint(key,options)};actions[key]={state:store[key],start:startFn}}return actions}}var system_tables_default={$schema:"../schemas/nucleus.tables.schema.json",tables:[{table_name:"users",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"email",type:"varchar",length:255},{name:"password",type:"varchar",length:255},{name:"verified_at",type:"timestamp"},{name:"email_verification_token",type:"varchar",length:255},{name:"email_verification_token_expires_at",type:"timestamp"},{name:"email_verification_sent_at",type:"timestamp"},{name:"email_verification_attempts",type:"integer",default:0},{name:"last_login_at",type:"timestamp"},{name:"login_count",type:"integer",default:0},{name:"is_locked",type:"boolean",default:!1},{name:"locked_until",type:"timestamp"},{name:"failed_login_attempts",type:"integer",default:0},{name:"is_god",type:"boolean",default:!1},{name:"cohort_id",type:"uuid",references:{table:"user_cohorts",column:"id",onDelete:"set null"}},{name:"email_verified",type:"boolean",default:!1}],indexes:[{columns:["email"],unique:!0},{columns:["email","is_active"]},{columns:["last_login_at"]},{columns:["is_locked","locked_until"]}]},{table_name:"profiles",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id"}},{name:"first_name",type:"varchar",length:100,notNull:!0},{name:"last_name",type:"varchar",length:100,notNull:!0}],indexes:[{columns:["user_id"],unique:!0},{columns:["first_name","last_name"]}]},{table_name:"roles",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"name",type:"varchar",length:100,notNull:!0},{name:"description",type:"varchar",length:500}],indexes:[{columns:["name"],unique:!0}]},{table_name:"claims",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"action",type:"varchar",length:100,notNull:!0},{name:"description",type:"varchar",length:500},{name:"path",type:"varchar",length:200,notNull:!0},{name:"method",type:"varchar",length:10,notNull:!0},{name:"policy",type:"jsonb"}],indexes:[{columns:["action"],unique:!0},{columns:["path","method"]}]},{table_name:"user_roles",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"role_id",type:"uuid",notNull:!0,references:{table:"roles",column:"id",onDelete:"cascade"}}],indexes:[{columns:["user_id"]},{columns:["role_id"]}],constraints:{unique:[{name:"unique_user_role",columns:["user_id","role_id"]}]}},{table_name:"role_claims",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"role_id",type:"uuid",notNull:!0,references:{table:"roles",column:"id",onDelete:"cascade"}},{name:"claim_id",type:"uuid",notNull:!0,references:{table:"claims",column:"id",onDelete:"cascade"}},{name:"scope",type:"text"}],indexes:[{columns:["role_id"]},{columns:["claim_id"]},{columns:["role_id","claim_id","scope"]}]},{table_name:"files",feature_set:["storage"],add_base_columns:!0,is_form_data:!0,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"name",type:"varchar",length:255,notNull:!0},{name:"original_name",type:"varchar",length:255,notNull:!0},{name:"type",type:"varchar",length:50,enumValues:["image","document","video","audio","profile_picture"]},{name:"path",type:"varchar",length:500,notNull:!0},{name:"size",type:"bigint",mode:"number",notNull:!0},{name:"mime_type",type:"varchar",length:100,notNull:!0},{name:"extension",type:"varchar",length:10,notNull:!0},{name:"uploaded_by",type:"uuid",references:{table:"users",column:"id"}}],indexes:[{columns:["type"]},{columns:["uploaded_by"]},{columns:["size"]}]},{table_name:"addresses",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"owner_type",type:"varchar",length:50,notNull:!0,enumValues:["user","company","contact"]},{name:"owner_id",type:"uuid",notNull:!0},{name:"name",type:"varchar",length:100,notNull:!0},{name:"street",type:"varchar",length:255},{name:"city",type:"varchar",length:100},{name:"state",type:"varchar",length:50},{name:"zip",type:"varchar",length:20},{name:"country",type:"varchar",length:50,default:"US"},{name:"latitude",type:"decimal",precision:10,scale:8},{name:"longitude",type:"decimal",precision:11,scale:8},{name:"neighborhood",type:"varchar",length:100},{name:"apartment",type:"varchar",length:50},{name:"province",type:"varchar",length:100},{name:"district",type:"varchar",length:100},{name:"type",type:"varchar",length:50}],indexes:[{columns:["city","state"]},{columns:["latitude","longitude"]},{columns:["type"]},{columns:["owner_type","owner_id"]}]},{table_name:"phones",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"owner_type",type:"varchar",length:50,notNull:!0,enumValues:["user","company","contact"]},{name:"owner_id",type:"uuid",notNull:!0},{name:"name",type:"varchar",length:100,notNull:!0},{name:"type",type:"varchar",length:50,enumValues:["mobile","office","fax"]},{name:"number",type:"varchar",length:20,notNull:!0},{name:"country_code",type:"varchar",length:10,notNull:!0,default:"+1"},{name:"extension",type:"varchar",length:10}],indexes:[{columns:["number"]},{columns:["type"]},{columns:["owner_type","owner_id"]}]},{table_name:"notifications",feature_set:["notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",notNull:!0},{name:"title",type:"varchar",length:255,notNull:!0},{name:"body",type:"varchar",length:1000},{name:"entity_name",type:"varchar",length:100},{name:"entity_id",type:"uuid"},{name:"type",type:"varchar",length:50,notNull:!0,default:"system",enumValues:["verification","system","custom"]},{name:"source",type:"varchar",length:100},{name:"is_seen",type:"boolean",notNull:!0,default:!1},{name:"seen_at",type:"timestamptz"}],indexes:[{columns:["user_id","created_at"]},{columns:["is_seen"]},{columns:["type"]},{columns:["user_id","type","is_seen"]}]},{table_name:"tenants",feature_set:["multi-tenant"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:[],columns:[{name:"subdomain",type:"varchar",length:100,notNull:!0,unique:!0},{name:"schema_name",type:"varchar",length:100,notNull:!0,unique:!0},{name:"company_id",type:"uuid",notNull:!0},{name:"company_name",type:"varchar",length:255},{name:"god_admin_email",type:"varchar",length:255,notNull:!0},{name:"status",type:"varchar",length:20,notNull:!0,default:"provisioning"},{name:"plan",type:"varchar",length:50,default:"free"},{name:"domain",type:"varchar",length:255},{name:"settings",type:"jsonb",default:"{}"},{name:"trusted_sources",type:"jsonb",default:"[]"},{name:"max_users",type:"integer"},{name:"provisioned_at",type:"timestamptz"},{name:"suspended_at",type:"timestamptz"},{name:"suspended_reason",type:"text"}],indexes:[{columns:["status"]}]},{table_name:"tenant_events",feature_set:["multi-tenant"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],columns:[{name:"tenant_id",type:"uuid",notNull:!0,references:{table:"tenants",column:"id",onDelete:"cascade"}},{name:"event_type",type:"varchar",length:50,notNull:!0},{name:"event_data",type:"jsonb",default:"{}"},{name:"performed_by",type:"varchar",length:255},{name:"ip_address",type:"varchar",length:45}],indexes:[{columns:["tenant_id"]},{columns:["event_type"]}]},{table_name:"tenant_features",feature_set:["multi-tenant"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:[],columns:[{name:"tenant_id",type:"uuid",notNull:!0,references:{table:"tenants",column:"id",onDelete:"cascade"}},{name:"feature_name",type:"varchar",length:100,notNull:!0},{name:"enabled",type:"boolean",notNull:!0,default:!0},{name:"config",type:"jsonb",default:"{}"}],indexes:[{columns:["tenant_id","feature_name"],unique:!0},{columns:["feature_name"]}]},{table_name:"domain_hostnames",feature_set:["domains"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:["PUT"],group_name:"Domains",columns:[{name:"owner_type",type:"varchar",length:20,notNull:!0,default:"tenant",comment:"tenant | organization | user | external"},{name:"owner_id",type:"uuid",notNull:!0,comment:"Product-defined owner reference (e.g. band id, org id)"},{name:"tenant_id",type:"uuid",references:{table:"tenants",column:"id",onDelete:"cascade"},comment:"Tenant this hostname routes to; null for non-tenant owners"},{name:"schema_name",type:"varchar",length:100,comment:"Resolved tenant schema for routing"},{name:"hostname",type:"varchar",length:255,notNull:!0,comment:"Original hostname as entered by the user"},{name:"normalized_hostname",type:"varchar",length:255,notNull:!0,unique:!0,comment:"Lowercased, punycode, port-stripped hostname used for matching"},{name:"hostname_kind",type:"varchar",length:20,notNull:!0,default:"apex",comment:"platform_subdomain | apex | www | subdomain"},{name:"status",type:"varchar",length:20,notNull:!0,default:"pending_verification",comment:"draft | pending_verification | verifying | active | failed | disabled | archived"},{name:"routing_status",type:"varchar",length:20,notNull:!0,default:"inactive",comment:"inactive | pending | active | failed"},{name:"certificate_status",type:"varchar",length:20,notNull:!0,default:"pending",comment:"not_required | pending | active | failed"},{name:"verification_status",type:"varchar",length:20,notNull:!0,default:"pending",comment:"pending | verified | failed | expired"},{name:"provider",type:"varchar",length:30,notNull:!0,default:"manual_dns",comment:"manual_dns | cloudflare_for_saas | cloudflare_registrar"},{name:"provider_hostname_id",type:"varchar",length:255},{name:"dns_target",type:"varchar",length:255,comment:"CNAME / A target the customer must point at"},{name:"is_primary",type:"boolean",notNull:!0,default:!1},{name:"redirect_to_hostname_id",type:"uuid",comment:"When set, this hostname 301-redirects to another hostname (e.g. apex to www)"},{name:"activated_at",type:"timestamptz"},{name:"disabled_at",type:"timestamptz"},{name:"failure_reason",type:"text"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["tenant_id"]},{columns:["schema_name"]},{columns:["status"]},{columns:["owner_type","owner_id"]},{columns:["provider","provider_hostname_id"]}]},{table_name:"domain_registrations",feature_set:["domains"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:["PUT"],group_name:"Domains",columns:[{name:"owner_type",type:"varchar",length:20,notNull:!0,default:"tenant"},{name:"owner_id",type:"uuid",notNull:!0},{name:"tenant_id",type:"uuid",references:{table:"tenants",column:"id",onDelete:"set null"}},{name:"requested_domain",type:"varchar",length:255,notNull:!0},{name:"registered_domain",type:"varchar",length:255},{name:"provider",type:"varchar",length:30,notNull:!0,default:"cloudflare_registrar"},{name:"provider_registration_id",type:"varchar",length:255},{name:"registrant_owner_type",type:"varchar",length:20,notNull:!0,default:"customer",comment:"customer | platform"},{name:"registrant_contact_snapshot",type:"jsonb",default:"{}"},{name:"status",type:"varchar",length:30,notNull:!0,default:"draft",comment:"draft | availability_checked | awaiting_payment | registering | active | failed | transfer_requested | transferred_out | cancelled | expired"},{name:"price_amount",type:"numeric",precision:12,scale:2},{name:"currency",type:"varchar",length:10},{name:"renewal_date",type:"timestamptz"},{name:"auto_renew",type:"boolean",notNull:!0,default:!0},{name:"terms_version",type:"varchar",length:50},{name:"terms_accepted_at",type:"timestamptz"},{name:"failure_reason",type:"text"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["owner_type","owner_id"]},{columns:["tenant_id"]},{columns:["status"]}]},{table_name:"domain_verification_challenges",feature_set:["domains"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],group_name:"Domains",columns:[{name:"domain_hostname_id",type:"uuid",notNull:!0,references:{table:"domainHostnames",column:"id",onDelete:"cascade"}},{name:"challenge_type",type:"varchar",length:30,notNull:!0,default:"ownership_validation",comment:"hostname_validation | certificate_validation | ownership_validation"},{name:"record_type",type:"varchar",length:10,notNull:!0,default:"TXT",comment:"TXT | CNAME | A | AAAA | HTTP"},{name:"record_name",type:"varchar",length:255,notNull:!0},{name:"record_value",type:"text",notNull:!0},{name:"expected_target",type:"varchar",length:255},{name:"status",type:"varchar",length:20,notNull:!0,default:"pending",comment:"pending | verified | failed | expired"},{name:"expires_at",type:"timestamptz"},{name:"verified_at",type:"timestamptz"},{name:"failure_reason",type:"text"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["domain_hostname_id"]},{columns:["status"]}]},{table_name:"domain_provider_records",feature_set:["domains"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],group_name:"Domains",columns:[{name:"domain_hostname_id",type:"uuid",notNull:!0,references:{table:"domainHostnames",column:"id",onDelete:"cascade"}},{name:"provider",type:"varchar",length:30,notNull:!0},{name:"provider_resource_type",type:"varchar",length:30,notNull:!0,comment:"custom_hostname | certificate | validation | zone | dns_record | registration"},{name:"provider_resource_id",type:"varchar",length:255},{name:"provider_status",type:"varchar",length:50},{name:"last_synced_at",type:"timestamptz"},{name:"raw_status",type:"jsonb",default:"{}"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["domain_hostname_id"]},{columns:["provider","provider_resource_id"]}]},{table_name:"domain_events",feature_set:["domains"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],group_name:"Domains",columns:[{name:"domain_hostname_id",type:"uuid",references:{table:"domainHostnames",column:"id",onDelete:"cascade"}},{name:"domain_registration_id",type:"uuid",references:{table:"domainRegistrations",column:"id",onDelete:"cascade"}},{name:"event_type",type:"varchar",length:50,notNull:!0},{name:"actor_type",type:"varchar",length:20},{name:"actor_id",type:"varchar",length:255},{name:"message",type:"text"},{name:"ip_address",type:"varchar",length:45},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["domain_hostname_id"]},{columns:["event_type"]}]},{table_name:"verifications",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"instance_id",type:"uuid",notNull:!0,references:{table:"verificationInstances",column:"id",onDelete:"cascade"}},{name:"requirement_id",type:"uuid",notNull:!0,references:{table:"verificationRequirements",column:"id"}},{name:"verifier_id",type:"uuid",notNull:!0,references:{table:"users",column:"id"}},{name:"signature_id",type:"uuid",references:{table:"files",column:"id"}},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"entity_id",type:"uuid",notNull:!0},{name:"step_order",type:"integer",notNull:!0,default:1},{name:"decision",type:"varchar",length:50,notNull:!0,default:"pending",enumValues:["approved","rejected","pending"]},{name:"reason",type:"text"},{name:"diff",type:"jsonb"}],indexes:[{columns:["instance_id"]},{columns:["requirement_id"]},{columns:["verifier_id"]},{columns:["entity_name","entity_id"]},{columns:["entity_name","entity_id","step_order"]},{columns:["decision"]}]},{table_name:"verificationRequirements",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"instance_id",type:"uuid",notNull:!0,references:{table:"verificationInstances",column:"id",onDelete:"cascade"}},{name:"step_node_id",type:"varchar",length:100,notNull:!0},{name:"verifier_node_id",type:"varchar",length:100,notNull:!0},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"entity_id",type:"uuid",notNull:!0},{name:"verifier_type",type:"varchar",length:30,notNull:!0,enumValues:["user","role"]},{name:"verifier_user_id",type:"uuid"},{name:"verifier_role",type:"varchar",length:100},{name:"require_signature",type:"boolean",notNull:!0,default:!1},{name:"all_must_approve",type:"boolean",notNull:!0,default:!1},{name:"step_order",type:"integer",notNull:!0,default:1},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","approved","rejected"]}],indexes:[{columns:["instance_id"]},{columns:["instance_id","step_order"]},{columns:["entity_name","entity_id"]},{columns:["verifier_user_id"]},{columns:["status"]}]},{table_name:"verificationFlows",feature_set:["authentication","verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"name",type:"varchar",length:255,notNull:!0},{name:"description",type:"text"},{name:"trigger_on",type:"varchar",length:50,notNull:!0,default:"update",enumValues:["create","update","delete","manual"]},{name:"trigger_fields",type:"jsonb"},{name:"is_draft",type:"boolean",notNull:!0,default:!0},{name:"published_at",type:"timestamptz"},{name:"viewport",type:"jsonb"}],indexes:[{columns:["entity_name"]},{columns:["entity_name","trigger_on"]},{columns:["is_draft"]}]},{table_name:"verificationSteps",feature_set:["authentication","verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"node_id",type:"varchar",length:100,notNull:!0},{name:"node_type",type:"varchar",length:50,notNull:!0,default:"step",enumValues:["step","verifier","notification"]},{name:"step_order",type:"integer",notNull:!0,default:1},{name:"name",type:"varchar",length:255},{name:"description",type:"text"},{name:"position_x",type:"numeric",notNull:!0,default:0},{name:"position_y",type:"numeric",notNull:!0,default:0},{name:"width",type:"numeric"},{name:"height",type:"numeric"},{name:"style",type:"jsonb"},{name:"data",type:"jsonb"}],indexes:[{columns:["flow_id"]},{columns:["entity_name"]},{columns:["flow_id","node_id"],unique:!0},{columns:["entity_name","step_order"]}]},{table_name:"verificationEdges",feature_set:["authentication","verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"edge_id",type:"varchar",length:100,notNull:!0},{name:"source_node_id",type:"varchar",length:100,notNull:!0},{name:"target_node_id",type:"varchar",length:100,notNull:!0},{name:"source_handle",type:"varchar",length:50},{name:"target_handle",type:"varchar",length:50},{name:"edge_type",type:"varchar",length:50,default:"default",enumValues:["default","conditional","success","failure"]},{name:"label",type:"varchar",length:255},{name:"condition",type:"jsonb"},{name:"style",type:"jsonb"},{name:"animated",type:"boolean",default:!1}],indexes:[{columns:["flow_id"]},{columns:["flow_id","edge_id"],unique:!0},{columns:["source_node_id"]},{columns:["target_node_id"]}]},{table_name:"verificationNotificationRules",feature_set:["verification","notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"node_id",type:"varchar",length:100,notNull:!0},{name:"trigger",type:"varchar",length:50,notNull:!0,enumValues:["on_flow_started","on_step_reached","on_approved","on_rejected","on_flow_completed"]},{name:"title_template",type:"varchar",length:255},{name:"body_template",type:"text"},{name:"starts_at",type:"timestamptz"},{name:"expires_at",type:"timestamptz"}],indexes:[{columns:["flow_id"]},{columns:["flow_id","node_id"],unique:!0},{columns:["trigger"]}]},{table_name:"verificationNotificationRecipients",feature_set:["verification","notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"rule_id",type:"uuid",notNull:!0,references:{table:"verificationNotificationRules",column:"id",onDelete:"cascade"}},{name:"recipient_type",type:"varchar",length:30,notNull:!0,enumValues:["user","role","all_verifiers","step_verifier","entity_creator"]},{name:"recipient_user_id",type:"uuid"},{name:"recipient_role",type:"varchar",length:100}],indexes:[{columns:["rule_id"]},{columns:["recipient_type"]}]},{table_name:"verificationVerifierConfigs",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"node_id",type:"varchar",length:100,notNull:!0},{name:"verifier_type",type:"varchar",length:30,notNull:!0,enumValues:["user","role"]},{name:"verifier_user_id",type:"uuid"},{name:"verifier_role",type:"varchar",length:100},{name:"require_signature",type:"boolean",notNull:!0,default:!1},{name:"all_must_approve",type:"boolean",notNull:!0,default:!1}],indexes:[{columns:["flow_id"]},{columns:["flow_id","node_id"],unique:!0},{columns:["verifier_type"]}]},{table_name:"verificationInstances",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id"}},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"entity_id",type:"uuid",notNull:!0},{name:"started_by",type:"uuid",references:{table:"users",column:"id"}},{name:"status",type:"varchar",length:30,notNull:!0,default:"active",enumValues:["active","completed","rejected","cancelled"]},{name:"current_step_order",type:"integer",notNull:!0,default:1},{name:"started_at",type:"timestamptz",notNull:!0,defaultRaw:"now()"},{name:"completed_at",type:"timestamptz"}],indexes:[{columns:["flow_id"]},{columns:["entity_name","entity_id"]},{columns:["entity_name","entity_id","status"]},{columns:["status"]},{columns:["started_by"]}]},{table_name:"verificationNotificationChannels",feature_set:["verification","notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"rule_id",type:"uuid",notNull:!0,references:{table:"verificationNotificationRules",column:"id",onDelete:"cascade"}},{name:"channel",type:"varchar",length:30,notNull:!0,enumValues:["portal","email","sms","telegram","webhook"]}],indexes:[{columns:["rule_id"]},{columns:["rule_id","channel"],unique:!0},{columns:["channel"]}]},{table_name:"user_cohorts",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"name",type:"varchar",length:255,notNull:!0},{name:"description",type:"text"},{name:"created_by",type:"uuid",references:{table:"users",column:"id",onDelete:"set null"}},{name:"expires_at",type:"timestamptz"},{name:"user_count",type:"integer",notNull:!0,default:0},{name:"metadata",type:"jsonb",default:"{}"}]},{table_name:"user_sessions",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,group_name:"Authentication",available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"token_hash",type:"varchar",length:255,notNull:!0},{name:"refresh_token_hash",type:"varchar",length:255},{name:"device_fingerprint",type:"varchar",length:255},{name:"device_name",type:"varchar",length:100},{name:"device_type",type:"varchar",length:50,enumValues:["desktop","mobile","tablet","unknown"]},{name:"browser_name",type:"varchar",length:50},{name:"browser_version",type:"varchar",length:20},{name:"os_name",type:"varchar",length:50},{name:"os_version",type:"varchar",length:20},{name:"ip_address",type:"varchar",length:45,notNull:!0},{name:"location_country",type:"varchar",length:100},{name:"location_city",type:"varchar",length:100},{name:"location_coordinates",type:"varchar",length:50},{name:"last_activity_at",type:"timestamptz",notNull:!0,defaultRaw:"now()"},{name:"expires_at",type:"timestamptz",notNull:!1},{name:"revoked_at",type:"timestamptz"},{name:"revoked_reason",type:"varchar",length:100,enumValues:["user_logout","user_revoked","admin_revoked","security_concern","password_changed","expired","replaced"]},{name:"is_current",type:"boolean",notNull:!0,default:!1},{name:"login_method",type:"varchar",length:50,enumValues:["password","oauth_google","oauth_github","oauth_microsoft","magic_link","sso","api_key"]},{name:"remember_me",type:"boolean",notNull:!0,default:!1},{name:"trust_score",type:"integer",default:100},{name:"approval_status",type:"varchar",length:20,default:"approved",enumValues:["approved","pending","rejected"]},{name:"approval_token",type:"varchar",length:64},{name:"approval_requested_at",type:"timestamptz"},{name:"approval_responded_at",type:"timestamptz"}],indexes:[{columns:["user_id"]},{columns:["token_hash"],unique:!0},{columns:["refresh_token_hash"]},{columns:["user_id","is_active"]},{columns:["expires_at"]},{columns:["device_fingerprint"]},{columns:["ip_address"]},{columns:["last_activity_at"]},{columns:["approval_status"]},{columns:["approval_token"]}]},{table_name:"trusted_devices",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,group_name:"Authentication",available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"token_hash",type:"varchar",length:64,notNull:!0},{name:"status",type:"varchar",length:20,notNull:!0,default:"pending",enumValues:["pending","trusted","revoked"]},{name:"origin_session_id",type:"uuid"},{name:"label",type:"varchar",length:120},{name:"device_fingerprint",type:"varchar",length:255},{name:"first_seen_ip",type:"varchar",length:45},{name:"last_seen_ip",type:"varchar",length:45},{name:"last_seen_at",type:"timestamptz"},{name:"expires_at",type:"timestamptz"},{name:"revoked_at",type:"timestamptz"},{name:"revoked_reason",type:"varchar",length:30,enumValues:["user_revoked","password_reset","logout","admin_revoked","expired","replaced"]}],indexes:[{columns:["token_hash"],unique:!0},{columns:["user_id"]},{columns:["user_id","status"]},{columns:["origin_session_id"]},{columns:["expires_at"]}]},{table_name:"password_reset_tokens",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,group_name:"Authentication",requires:["email"],available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"token_hash",type:"varchar",length:255,notNull:!0},{name:"expires_at",type:"timestamptz",notNull:!0},{name:"used_at",type:"timestamptz"}],indexes:[{columns:["token_hash"],unique:!0},{columns:["user_id"]},{columns:["expires_at"]}]},{table_name:"magic_link_tokens",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,group_name:"Authentication",requires:["email"],available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"email",type:"varchar",length:255,notNull:!0},{name:"token_hash",type:"varchar",length:255,notNull:!0},{name:"expires_at",type:"timestamptz",notNull:!0},{name:"used_at",type:"timestamptz"}],indexes:[{columns:["token_hash"],unique:!0},{columns:["user_id"]},{columns:["email"]},{columns:["expires_at"]}]},{table_name:"webauthn_credentials",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,group_name:"Authentication",requires:[],available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"credential_id",type:"text",notNull:!0},{name:"public_key",type:"text",notNull:!0},{name:"counter",type:"bigint",mode:"number",notNull:!0,defaultValue:0},{name:"transports",type:"jsonb"},{name:"device_type",type:"varchar",length:32},{name:"backed_up",type:"boolean",notNull:!0,defaultValue:!1},{name:"aaguid",type:"varchar",length:64},{name:"authenticator_attachment",type:"varchar",length:32},{name:"nickname",type:"varchar",length:128},{name:"last_used_at",type:"timestamptz"},{name:"revoked_at",type:"timestamptz"}],indexes:[{columns:["credential_id"],unique:!0},{columns:["user_id"]}]},{table_name:"webauthn_challenges",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,group_name:"Authentication",requires:[],available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE","GET"],columns:[{name:"user_id",type:"uuid",references:{table:"users",column:"id",onDelete:"cascade"}},{name:"challenge",type:"text",notNull:!0},{name:"challenge_type",type:"varchar",length:32,notNull:!0},{name:"expires_at",type:"timestamptz",notNull:!0},{name:"consumed_at",type:"timestamptz"}],indexes:[{columns:["challenge"],unique:!0},{columns:["user_id"]},{columns:["expires_at"]}]},{table_name:"audit_logs",feature_set:["audit"],add_base_columns:!1,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","DELETE","PATCH","TOGGLE","VERIFICATION"],columns:[{name:"id",type:"uuid",primaryKey:!0,defaultRaw:"gen_random_uuid()"},{name:"entity_id",type:"uuid"},{name:"entity_name",type:"text",notNull:!0},{name:"operation_type",type:"text",notNull:!0},{name:"user_id",type:"uuid"},{name:"ip_address",type:"text"},{name:"user_agent",type:"text"},{name:"summary",type:"text"},{name:"severity",type:"text",default:"info"},{name:"category",type:"text"},{name:"occurrence_count",type:"integer",default:1},{name:"last_occurrence_at",type:"timestamp"},{name:"old_values",type:"jsonb"},{name:"new_values",type:"jsonb"},{name:"created_at",type:"timestamp",notNull:!0,defaultRaw:"now()"},{name:"path",type:"text"},{name:"query",type:"text"}],indexes:[{columns:["entity_id"]},{columns:["entity_name"]},{columns:["user_id"]},{columns:["created_at"]},{columns:["severity"]},{columns:["category"]}]},{table_name:"monitoring_metrics",feature_set:["monitoring"],add_base_columns:!1,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","DELETE","PATCH","TOGGLE","VERIFICATION"],columns:[{name:"id",type:"uuid",primaryKey:!0,defaultRaw:"gen_random_uuid()"},{name:"metric_type",type:"text",notNull:!0},{name:"metric_name",type:"text",notNull:!0},{name:"value",type:"doublePrecision",notNull:!0},{name:"tags",type:"jsonb"},{name:"recorded_at",type:"timestamp",notNull:!0}],indexes:[{columns:["metric_type"]},{columns:["metric_name"]},{columns:["recorded_at"]}]},{table_name:"oauth_accounts",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!1,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"provider",type:"varchar",length:50,notNull:!0,enumValues:["google","github","microsoft","discord","facebook","twitter","apple","custom"]},{name:"provider_account_id",type:"varchar",length:255,notNull:!0},{name:"provider_email",type:"varchar",length:255},{name:"provider_name",type:"varchar",length:255},{name:"provider_avatar_url",type:"text"},{name:"access_token",type:"text"},{name:"refresh_token",type:"text"},{name:"token_expires_at",type:"timestamp"},{name:"scope",type:"text"},{name:"raw_profile",type:"jsonb"},{name:"is_primary",type:"boolean",notNull:!0,default:!1},{name:"last_used_at",type:"timestamp"}],indexes:[{columns:["user_id"]},{columns:["provider","provider_account_id"],unique:!0},{columns:["provider_email"]},{columns:["user_id","provider"]}],constraints:{unique:[{name:"unique_provider_account",columns:["provider","provider_account_id"]}]}},{table_name:"api_keys",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH"],bulk_endpoints_enabled:!1,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"name",type:"varchar",length:255,notNull:!0},{name:"description",type:"text"},{name:"key_hash",type:"varchar",length:255,notNull:!0},{name:"key_preview",type:"varchar",length:20,notNull:!0},{name:"owner_type",type:"varchar",length:30,notNull:!0,default:"personal",enumValues:["personal","application"]},{name:"application_name",type:"varchar",length:255},{name:"allowed_roles",type:"jsonb",notNull:!0,default:"[]"},{name:"allowed_claims",type:"jsonb",notNull:!0,default:"[]"},{name:"allowed_scopes",type:"jsonb",notNull:!0,default:"[]"},{name:"expires_at",type:"timestamptz"},{name:"last_used_at",type:"timestamptz"},{name:"last_used_ip",type:"varchar",length:45},{name:"usage_count",type:"integer",notNull:!0,default:0},{name:"revoked_at",type:"timestamptz"},{name:"revoked_reason",type:"varchar",length:255}],indexes:[{columns:["key_hash"],unique:!0},{columns:["user_id"]},{columns:["user_id","is_active"]},{columns:["owner_type"]},{columns:["expires_at"]},{columns:["last_used_at"]}]},{table_name:"backup_logs",feature_set:["backup"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main","all"],excluded_schemas:[],excluded_methods:["PUT","PATCH"],columns:[{name:"backup_name",type:"varchar",length:255,notNull:!0},{name:"file_name",type:"varchar",length:500,notNull:!0},{name:"schema_name",type:"varchar",length:100,notNull:!0},{name:"format",type:"varchar",length:20,notNull:!0,default:"json"},{name:"status",type:"varchar",length:20,notNull:!0,default:"pending"},{name:"trigger",type:"varchar",length:20,notNull:!0,default:"manual"},{name:"size_bytes",type:"integer"},{name:"table_count",type:"integer"},{name:"row_count",type:"integer"},{name:"included_tables",type:"jsonb",default:"[]"},{name:"excluded_tables",type:"jsonb",default:"[]"},{name:"error_message",type:"text"},{name:"started_at",type:"timestamp"},{name:"completed_at",type:"timestamp"},{name:"performed_by",type:"varchar",length:255},{name:"cron_expression",type:"varchar",length:100},{name:"retention_days",type:"integer"}],indexes:[{columns:["schema_name"]},{columns:["status"]},{columns:["trigger"]},{columns:["created_at"]}]},{table_name:"payment_transactions",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"user_id",type:"uuid",references:{table:"users",column:"id"}},{name:"order_id",type:"varchar",length:255},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_transaction_id",type:"varchar",length:255},{name:"provider_payment_id",type:"varchar",length:255},{name:"payment_method",type:"varchar",length:50},{name:"amount",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"currency",type:"varchar",length:10,notNull:!0,default:"TRY"},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","processing","completed","failed","refunded","partially_refunded","cancelled"]},{name:"status_code",type:"integer"},{name:"status_message",type:"text"},{name:"card_last_four",type:"varchar",length:4},{name:"card_type",type:"varchar",length:50},{name:"card_association",type:"varchar",length:50},{name:"installment",type:"integer",default:1},{name:"is_three_d_secure",type:"boolean",default:!1},{name:"provider_response",type:"jsonb",default:"{}"},{name:"metadata",type:"jsonb",default:"{}"},{name:"refunded_amount",type:"numeric",precision:12,scale:2,default:0},{name:"refunded_at",type:"timestamptz"},{name:"completed_at",type:"timestamptz"},{name:"failed_at",type:"timestamptz"},{name:"ip_address",type:"varchar",length:45}],indexes:[{columns:["user_id"]},{columns:["order_id"]},{columns:["provider"]},{columns:["provider_payment_id"]},{columns:["status"]},{columns:["user_id","status"]}]},{table_name:"payment_methods",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"type",type:"varchar",length:30,notNull:!0,default:"card",enumValues:["card","bank_account","wallet"]},{name:"alias",type:"varchar",length:100},{name:"card_last_four",type:"varchar",length:4},{name:"card_type",type:"varchar",length:50},{name:"card_association",type:"varchar",length:50},{name:"card_family",type:"varchar",length:100},{name:"card_bank_name",type:"varchar",length:100},{name:"provider_card_user_key",type:"varchar",length:255},{name:"provider_card_token",type:"varchar",length:255},{name:"bin_number",type:"varchar",length:8},{name:"is_default",type:"boolean",default:!1},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["user_id"]},{columns:["provider"]},{columns:["user_id","is_default"]},{columns:["provider_card_user_key"]}]},{table_name:"payment_webhook_logs",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["PUT","PATCH","DELETE"],columns:[{name:"provider",type:"varchar",length:50,notNull:!0},{name:"event_type",type:"varchar",length:100,notNull:!0},{name:"provider_payment_id",type:"varchar",length:255},{name:"raw_payload",type:"jsonb",notNull:!0},{name:"processed",type:"boolean",default:!1},{name:"processing_result",type:"jsonb"},{name:"error_message",type:"text"},{name:"ip_address",type:"varchar",length:45},{name:"idempotency_key",type:"varchar",length:255}],indexes:[{columns:["provider"]},{columns:["event_type"]},{columns:["provider_payment_id"]},{columns:["processed"]},{columns:["idempotency_key"],unique:!0}]},{table_name:"payment_sub_merchants",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",references:{table:"users",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_sub_merchant_key",type:"varchar",length:255},{name:"external_id",type:"varchar",length:255},{name:"type",type:"varchar",length:50,notNull:!0,default:"personal",enumValues:["personal","private_company","limited_or_joint_stock_company"]},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","active","suspended","rejected"]},{name:"name",type:"varchar",length:255,notNull:!0},{name:"email",type:"varchar",length:255,notNull:!0},{name:"gsm_number",type:"varchar",length:20},{name:"address",type:"text"},{name:"iban",type:"varchar",length:50},{name:"contact_name",type:"varchar",length:100},{name:"contact_surname",type:"varchar",length:100},{name:"identity_number",type:"varchar",length:20},{name:"tax_office",type:"varchar",length:100},{name:"tax_number",type:"varchar",length:20},{name:"legal_company_title",type:"varchar",length:255},{name:"currency",type:"varchar",length:10,default:"TRY"},{name:"commission_rate",type:"numeric",precision:5,scale:2,default:0},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["user_id"]},{columns:["provider"]},{columns:["provider_sub_merchant_key"]},{columns:["external_id"]},{columns:["status"]},{columns:["email"]}]},{table_name:"payment_commission_splits",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"transaction_id",type:"uuid",notNull:!0,references:{table:"payment_transactions",column:"id",onDelete:"cascade"}},{name:"sub_merchant_id",type:"uuid",notNull:!0,references:{table:"payment_sub_merchants",column:"id"}},{name:"basket_item_id",type:"varchar",length:255},{name:"item_price",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"sub_merchant_price",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"platform_commission",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"commission_rate",type:"numeric",precision:5,scale:2,default:0},{name:"provider_split_id",type:"varchar",length:255},{name:"currency",type:"varchar",length:10,notNull:!0,default:"TRY"},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","approved","disapproved","refunded"]},{name:"approved_at",type:"timestamptz"},{name:"disapproved_at",type:"timestamptz"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["transaction_id"]},{columns:["sub_merchant_id"]},{columns:["status"]},{columns:["transaction_id","sub_merchant_id"]},{columns:["provider_split_id"]}]},{table_name:"payment_products",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_product_id",type:"varchar",length:255},{name:"name",type:"varchar",length:255,notNull:!0},{name:"description",type:"text"},{name:"type",type:"varchar",length:30,default:"service",enumValues:["service","good"]},{name:"status",type:"varchar",length:30,notNull:!0,default:"active",enumValues:["active","archived","draft"]},{name:"images",type:"jsonb",default:"[]"},{name:"unit_label",type:"varchar",length:50},{name:"url",type:"varchar",length:500},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["provider"]},{columns:["provider_product_id"]},{columns:["name"]},{columns:["status"]},{columns:["type"]}]},{table_name:"payment_prices",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"product_id",type:"uuid",notNull:!0,references:{table:"payment_products",column:"id",onDelete:"cascade"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_price_id",type:"varchar",length:255},{name:"currency",type:"varchar",length:10,notNull:!0,default:"USD"},{name:"unit_amount",type:"integer",notNull:!0,default:0},{name:"unit_amount_decimal",type:"varchar",length:30},{name:"type",type:"varchar",length:30,notNull:!0,default:"one_time",enumValues:["one_time","recurring"]},{name:"billing_scheme",type:"varchar",length:30,default:"per_unit",enumValues:["per_unit","tiered"]},{name:"nickname",type:"varchar",length:255},{name:"recurring_interval",type:"varchar",length:20,enumValues:["day","week","month","year"]},{name:"recurring_interval_count",type:"integer",default:1},{name:"recurring_usage_type",type:"varchar",length:20,default:"licensed",enumValues:["licensed","metered"]},{name:"recurring_aggregate_usage",type:"varchar",length:30,enumValues:["sum","last_during_period","last_ever","max"]},{name:"transform_quantity_divide_by",type:"integer"},{name:"transform_quantity_round",type:"varchar",length:10,enumValues:["up","down"]},{name:"status",type:"varchar",length:30,notNull:!0,default:"active",enumValues:["active","archived"]},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["product_id"]},{columns:["provider"]},{columns:["provider_price_id"]},{columns:["type"]},{columns:["currency"]},{columns:["status"]},{columns:["product_id","status"]}]},{table_name:"payment_customers",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",references:{table:"users",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_customer_id",type:"varchar",length:255,notNull:!0},{name:"email",type:"varchar",length:255,notNull:!0},{name:"name",type:"varchar",length:255},{name:"phone",type:"varchar",length:50},{name:"description",type:"text"},{name:"address",type:"jsonb",default:"{}"},{name:"tax_id_type",type:"varchar",length:50},{name:"tax_id_value",type:"varchar",length:100},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["user_id"]},{columns:["provider"]},{columns:["provider_customer_id"]},{columns:["email"]},{columns:["user_id","provider"],unique:!0}]},{table_name:"payment_subscriptions",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"customer_id",type:"uuid",notNull:!0,references:{table:"payment_customers",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_subscription_id",type:"varchar",length:255},{name:"status",type:"varchar",length:30,notNull:!0,default:"incomplete",enumValues:["active","past_due","unpaid","canceled","incomplete","incomplete_expired","trialing","paused"]},{name:"collection_method",type:"varchar",length:30,default:"charge_automatically",enumValues:["charge_automatically","send_invoice"]},{name:"current_period_start",type:"timestamptz"},{name:"current_period_end",type:"timestamptz"},{name:"cancel_at_period_end",type:"boolean",default:!1},{name:"canceled_at",type:"timestamptz"},{name:"trial_start",type:"timestamptz"},{name:"trial_end",type:"timestamptz"},{name:"items",type:"jsonb",default:"[]"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["customer_id"]},{columns:["provider"]},{columns:["provider_subscription_id"]},{columns:["status"]},{columns:["customer_id","status"]}]},{table_name:"payment_invoices",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"customer_id",type:"uuid",notNull:!0,references:{table:"payment_customers",column:"id"}},{name:"subscription_id",type:"uuid",references:{table:"payment_subscriptions",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_invoice_id",type:"varchar",length:255},{name:"status",type:"varchar",length:30,notNull:!0,default:"draft",enumValues:["draft","open","paid","uncollectible","void"]},{name:"collection_method",type:"varchar",length:30,default:"charge_automatically",enumValues:["charge_automatically","send_invoice"]},{name:"currency",type:"varchar",length:10,notNull:!0,default:"USD"},{name:"amount_due",type:"integer",default:0},{name:"amount_paid",type:"integer",default:0},{name:"amount_remaining",type:"integer",default:0},{name:"description",type:"text"},{name:"hosted_invoice_url",type:"varchar",length:1000},{name:"invoice_pdf",type:"varchar",length:1000},{name:"due_date",type:"timestamptz"},{name:"days_until_due",type:"integer"},{name:"period_start",type:"timestamptz"},{name:"period_end",type:"timestamptz"},{name:"paid_at",type:"timestamptz"},{name:"voided_at",type:"timestamptz"},{name:"lines",type:"jsonb",default:"[]"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["customer_id"]},{columns:["subscription_id"]},{columns:["provider"]},{columns:["provider_invoice_id"]},{columns:["status"]},{columns:["customer_id","status"]}]},{table_name:"chat_conversations",feature_set:["authentication","chat"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"type",type:"varchar",length:20,notNull:!0,default:"direct",enumValues:["direct","group"]},{name:"title",type:"varchar",length:255},{name:"description",type:"text"},{name:"avatar_file_id",type:"uuid"},{name:"direct_key",type:"varchar",length:255},{name:"last_message_at",type:"timestamptz"},{name:"last_message_preview",type:"varchar",length:500},{name:"last_message_sender_id",type:"uuid",references:{table:"users",column:"id",onDelete:"set null"}}],indexes:[{columns:["direct_key"],unique:!0},{columns:["type"]},{columns:["last_message_at"]}]},{table_name:"chat_participants",feature_set:["authentication","chat"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"conversation_id",type:"uuid",notNull:!0,references:{table:"chat_conversations",column:"id",onDelete:"cascade"}},{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"role",type:"varchar",length:20,notNull:!0,default:"member",enumValues:["member","admin","owner"]},{name:"last_read_message_id",type:"uuid"},{name:"last_read_at",type:"timestamptz"},{name:"unread_count",type:"integer",notNull:!0,default:0},{name:"muted",type:"boolean",notNull:!0,default:!1},{name:"muted_until",type:"timestamptz"},{name:"notifications_enabled",type:"boolean",notNull:!0,default:!0},{name:"left_at",type:"timestamptz"}],indexes:[{columns:["user_id"]},{columns:["conversation_id"]}],constraints:{unique:[{name:"unique_conversation_participant",columns:["conversation_id","user_id"]}]}},{table_name:"chat_messages",feature_set:["authentication","chat"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"conversation_id",type:"uuid",notNull:!0,references:{table:"chat_conversations",column:"id",onDelete:"cascade"}},{name:"sender_id",type:"uuid",references:{table:"users",column:"id",onDelete:"set null"}},{name:"content",type:"text"},{name:"content_type",type:"varchar",length:20,notNull:!0,default:"text",enumValues:["text","image","file","video","audio","system"]},{name:"reply_to_id",type:"uuid",references:{table:"chat_messages",column:"id",onDelete:"set null"}},{name:"metadata",type:"jsonb",default:"{}"},{name:"client_message_id",type:"varchar",length:100},{name:"edited_at",type:"timestamptz"},{name:"deleted_at",type:"timestamptz"}],indexes:[{columns:["conversation_id","created_at"]},{columns:["sender_id"]},{columns:["reply_to_id"]}]},{table_name:"chat_message_attachments",feature_set:["authentication","chat","storage"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"message_id",type:"uuid",notNull:!0,references:{table:"chat_messages",column:"id",onDelete:"cascade"}},{name:"conversation_id",type:"uuid",notNull:!0,references:{table:"chat_conversations",column:"id",onDelete:"cascade"}},{name:"file_id",type:"uuid",notNull:!0,references:{table:"files",column:"id",onDelete:"cascade"}},{name:"kind",type:"varchar",length:20,notNull:!0,default:"file",enumValues:["image","video","audio","file"]},{name:"original_name",type:"varchar",length:255},{name:"mime_type",type:"varchar",length:100},{name:"size",type:"bigint",mode:"number"},{name:"width",type:"integer"},{name:"height",type:"integer"},{name:"duration",type:"integer"}],indexes:[{columns:["message_id"]},{columns:["conversation_id"]},{columns:["file_id"]}]},{table_name:"payment_splits",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],group_name:"Payments Marketplace",columns:[{name:"transaction_id",type:"uuid",references:{table:"paymentTransactions",column:"id",onDelete:"set null"}},{name:"recipient_owner_type",type:"varchar",length:20,notNull:!0,default:"seller",comment:"seller | platform | tenant | user"},{name:"recipient_owner_id",type:"uuid",notNull:!0},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"gross_amount",type:"bigint",mode:"number",notNull:!0,comment:"Minor units"},{name:"provider_fee_amount",type:"bigint",mode:"number",notNull:!0,default:0},{name:"platform_fee_amount",type:"bigint",mode:"number",notNull:!0,default:0},{name:"reserve_amount",type:"bigint",mode:"number",notNull:!0,default:0},{name:"net_payable_amount",type:"bigint",mode:"number",notNull:!0},{name:"currency",type:"varchar",length:10,notNull:!0},{name:"available_for_payout_at",type:"timestamptz"},{name:"status",type:"varchar",length:20,notNull:!0,default:"pending",comment:"pending | available | payout_requested | paid | held | refunded | disputed | cancelled"},{name:"source_type",type:"varchar",length:50},{name:"source_id",type:"varchar",length:255},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["recipient_owner_type","recipient_owner_id"]},{columns:["status"]},{columns:["transaction_id"]}]},{table_name:"payment_ledger_entries",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],group_name:"Payments Marketplace",columns:[{name:"account",type:"varchar",length:40,notNull:!0,comment:"platform_revenue | provider_fee | seller_payable | reserve | refund_liability | dispute_liability | payout_in_transit | payout_completed"},{name:"owner_type",type:"varchar",length:20},{name:"owner_id",type:"uuid"},{name:"direction",type:"varchar",length:6,notNull:!0,comment:"debit | credit"},{name:"amount",type:"bigint",mode:"number",notNull:!0,comment:"Minor units"},{name:"currency",type:"varchar",length:10,notNull:!0},{name:"entry_type",type:"varchar",length:40,notNull:!0,comment:"split | refund | payout | reserve_hold | reserve_release | dispute | adjustment"},{name:"reference_type",type:"varchar",length:50},{name:"reference_id",type:"varchar",length:255},{name:"split_id",type:"uuid",references:{table:"paymentSplits",column:"id",onDelete:"set null"}},{name:"description",type:"text"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["account"]},{columns:["owner_type","owner_id"]},{columns:["entry_type"]},{columns:["reference_type","reference_id"]}]},{table_name:"payment_settlement_policies",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],group_name:"Payments Marketplace",columns:[{name:"owner_type",type:"varchar",length:20,notNull:!0,default:"tenant",comment:"tenant | seller"},{name:"owner_id",type:"uuid",notNull:!0},{name:"default_delay_days",type:"integer",notNull:!0,default:7},{name:"new_seller_delay_days",type:"integer",notNull:!0,default:14},{name:"reserve_rate",type:"numeric",precision:5,scale:4,notNull:!0,default:0,comment:"Fraction 0..1 held as reserve"},{name:"reserve_days",type:"integer",notNull:!0,default:0},{name:"minimum_payout_amount",type:"bigint",mode:"number",notNull:!0,default:0},{name:"currency",type:"varchar",length:10},{name:"early_payout_enabled",type:"boolean",notNull:!0,default:!1},{name:"status",type:"varchar",length:20,notNull:!0,default:"active"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["owner_type","owner_id"],unique:!0}]},{table_name:"payment_reserves",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],group_name:"Payments Marketplace",columns:[{name:"owner_type",type:"varchar",length:20,notNull:!0,default:"seller"},{name:"owner_id",type:"uuid",notNull:!0},{name:"split_id",type:"uuid",references:{table:"paymentSplits",column:"id",onDelete:"set null"}},{name:"amount",type:"bigint",mode:"number",notNull:!0},{name:"currency",type:"varchar",length:10,notNull:!0},{name:"reason",type:"varchar",length:30,notNull:!0,default:"refund_window",comment:"refund_window | chargeback_risk | new_seller | manual_hold | dispute | compliance_review"},{name:"status",type:"varchar",length:20,notNull:!0,default:"held",comment:"held | released | consumed | cancelled"},{name:"release_at",type:"timestamptz"},{name:"released_at",type:"timestamptz"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["owner_type","owner_id"]},{columns:["status"]},{columns:["release_at"]}]},{table_name:"payment_payout_requests",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["PUT"],group_name:"Payments Marketplace",columns:[{name:"recipient_owner_type",type:"varchar",length:20,notNull:!0,default:"seller"},{name:"recipient_owner_id",type:"uuid",notNull:!0},{name:"amount",type:"bigint",mode:"number",notNull:!0},{name:"currency",type:"varchar",length:10,notNull:!0},{name:"status",type:"varchar",length:20,notNull:!0,default:"pending",comment:"pending | approved | rejected | processing | completed | failed | cancelled"},{name:"provider",type:"varchar",length:50},{name:"provider_payout_id",type:"varchar",length:255},{name:"provider_transfer_id",type:"varchar",length:255},{name:"destination",type:"varchar",length:255},{name:"requested_by",type:"uuid"},{name:"decided_by",type:"uuid"},{name:"decided_at",type:"timestamptz"},{name:"completed_at",type:"timestamptz"},{name:"failure_reason",type:"text"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["recipient_owner_type","recipient_owner_id"]},{columns:["status"]}]},{table_name:"payment_disputes",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["PUT"],group_name:"Payments Marketplace",columns:[{name:"transaction_id",type:"uuid",references:{table:"paymentTransactions",column:"id",onDelete:"set null"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_dispute_id",type:"varchar",length:255},{name:"owner_type",type:"varchar",length:20},{name:"owner_id",type:"uuid"},{name:"amount",type:"bigint",mode:"number"},{name:"currency",type:"varchar",length:10},{name:"reason",type:"varchar",length:100},{name:"status",type:"varchar",length:30,notNull:!0,default:"open",comment:"open | under_review | won | lost | accepted | cancelled"},{name:"evidence_due_at",type:"timestamptz"},{name:"resolved_at",type:"timestamptz"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["provider","provider_dispute_id"]},{columns:["status"]},{columns:["owner_type","owner_id"]},{columns:["transaction_id"]}]},{table_name:"nucleus_secrets",feature_set:["secrets"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["GET","POST","PUT","PATCH","DELETE","TOGGLE"],bulk_endpoints_enabled:!1,group_name:"Secrets",columns:[{name:"scope",type:"varchar",length:200,notNull:!0,comment:"Config dot-path that owns the credential, e.g. authentication.oauth.providers.microsoft"},{name:"key",type:"varchar",length:120,notNull:!0,comment:"Leaf key under that path, e.g. clientSecret"},{name:"value_enc",type:"text",notNull:!0,comment:"AES-256-GCM envelope v1:iv:tag:ciphertext \u2014 never returned by any route"},{name:"previous_enc",type:"text",comment:"Value replaced by the last rotation, retained for one-step rollback"},{name:"preview",type:"varchar",length:80},{name:"kind",type:"varchar",length:30,notNull:!0,default:"text",enumValues:["text","password","json","connection_string","pem"]},{name:"description",type:"varchar",length:500},{name:"version",type:"integer",notNull:!0,default:1},{name:"rotated_at",type:"timestamptz"},{name:"last_used_at",type:"timestamptz"}],indexes:[{columns:["scope","key"],unique:!0},{columns:["scope"]}]},{table_name:"integration_sources",feature_set:["integrations"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!1,group_name:"Integrations",columns:[{name:"name",type:"varchar",length:150,notNull:!0},{name:"slug",type:"varchar",length:150,notNull:!0,comment:"Stable machine name; referenced by exports and by operators in logs"},{name:"base_url",type:"varchar",length:500,notNull:!0,comment:"Any scheme, host and port \u2014 https, plain http, in-cluster DNS, IP. HTTPS is NOT required and must never be enforced: reaching a service inside the same cluster over http is a legitimate deployment."},{name:"description",type:"text"},{name:"enabled",type:"boolean",default:!0},{name:"auth_type",type:"varchar",length:20,notNull:!0,default:"none",enumValues:["none","bearer","api_key","basic","oauth2"]},{name:"auth_token_encrypted",type:"text",sensitive:!0,comment:"Static credential (bearer / api key / basic blob), encrypted at rest"},{name:"auth_token_hint",type:"varchar",length:24},{name:"auth_header_name",type:"varchar",length:80,default:"Authorization"},{name:"auth_query_param",type:"varchar",length:80,comment:"When set, an api_key credential travels as this query parameter instead of a header"},{name:"extra_headers",type:"jsonb",default:{}},{name:"token_url",type:"varchar",length:500},{name:"oauth_grant_type",type:"varchar",length:40,default:"password",enumValues:["password","client_credentials"]},{name:"oauth_client_id",type:"varchar",length:200},{name:"oauth_client_secret_encrypted",type:"text",sensitive:!0},{name:"oauth_client_secret_hint",type:"varchar",length:24},{name:"oauth_username",type:"varchar",length:200},{name:"oauth_password_encrypted",type:"text",sensitive:!0},{name:"oauth_password_hint",type:"varchar",length:24},{name:"oauth_scope",type:"varchar",length:300},{name:"oauth_client_auth",type:"varchar",length:20,default:"basic",enumValues:["basic","body"]},{name:"tls_verify",type:"boolean",notNull:!0,default:!0,comment:"Per-source certificate verification. Turning it off applies to THIS source's connections only \u2014 never to the process, which is what a NODE_TLS_REJECT_UNAUTHORIZED toggle would do."},{name:"timeout_ms",type:"integer",notNull:!0,default:30000},{name:"spec_url",type:"varchar",length:500,comment:"Optional API description document (OpenAPI/Swagger/Postman/Bruno). Discovery is a convenience: every endpoint can always be defined by hand instead."},{name:"spec_format",type:"varchar",length:20,default:"manual",enumValues:["manual","openapi","swagger","postman","bruno","har"]}],constraints:{unique:[{name:"uniq_integration_source_slug",columns:["slug"]}]},indexes:[{columns:["enabled"]}]},{table_name:"integration_endpoints",feature_set:["integrations"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!1,group_name:"Integrations",columns:[{name:"source_id",type:"uuid",notNull:!0,references:{table:"integrationSources",column:"id",onDelete:"cascade"}},{name:"tag",type:"varchar",length:120,notNull:!0},{name:"name",type:"varchar",length:200},{name:"method",type:"varchar",length:10,notNull:!0,default:"GET",enumValues:["GET","POST","PUT","PATCH","DELETE"]},{name:"path",type:"varchar",length:500,notNull:!0,comment:"Appended to the source base URL. May carry {brace} or :colon path tokens, whose values come from param_bindings."},{name:"description",type:"text"},{name:"query_params",type:"jsonb",default:{}},{name:"request_body",type:"jsonb",default:{}},{name:"param_bindings",type:"jsonb",default:[],comment:"Where each path/query parameter comes from: a static value, another endpoint's records (fan-out), or a column of one of our own tables."},{name:"pagination",type:"jsonb",default:{},comment:"Explicitly chosen paging profile (none/page_number/offset/cursor/link_header). Never guessed \u2014 a wrong guess silently imports one page."},{name:"response_root_path",type:"varchar",length:200},{name:"tree_children_path",type:"varchar",length:200,comment:"Field holding a record's children when the source answers with a shape rather than a list \u2014 each node then becomes its own row and knows its parent"},{name:"sample_response",type:"jsonb",default:{},comment:"A few real records captured by a live test, so the mapping screen still shows fields when the source is unreachable"},{name:"enabled",type:"boolean",default:!0}],indexes:[{columns:["source_id"]},{columns:["source_id","tag"]}]},{table_name:"integration_mappings",feature_set:["integrations"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!1,group_name:"Integrations",columns:[{name:"endpoint_id",type:"uuid",notNull:!0,references:{table:"integrationEndpoints",column:"id",onDelete:"cascade"}},{name:"name",type:"varchar",length:200,notNull:!0},{name:"target_entity",type:"varchar",length:120,notNull:!0,comment:"snake_case table name this mapping writes into"},{name:"field_mappings",type:"jsonb",notNull:!0,default:[]},{name:"reference_checks",type:"jsonb",notNull:!0,default:[],comment:"Columns whose value must already exist in another entity, and what to do when it does not."},{name:"dedup_source_field",type:"varchar",length:200},{name:"dedup_target_field",type:"varchar",length:200,comment:"Target column that identifies the same record across runs. Without it nothing can be matched and every run appends."},{name:"write_mode",type:"varchar",length:20,notNull:!0,default:"upsert",enumValues:["upsert","append","replace"],comment:"replace is the destructive wipe-and-rewrite; it is no longer the default and is gated by the completeness check."},{name:"missing_record_policy",type:"varchar",length:20,notNull:!0,default:"ignore",enumValues:["ignore","deactivate","delete"],comment:"What happens to a row that exists here but no longer in the source. deactivate is the right answer for most HR data and could not be expressed before."},{name:"missing_record_column",type:"varchar",length:120},{name:"missing_record_value",type:"varchar",length:200},{name:"origin_column",type:"varchar",length:120,comment:"Column this mapping stamps on rows it owns. Set it when the target table ALSO holds rows people create by hand: without it every hand-made row looks like one the source stopped carrying, and the first run with a removal policy deletes them all."},{name:"origin_value",type:"varchar",length:120,comment:"The value written into origin_column. Rows carrying it are the only removal candidates."},{name:"max_removal_share",type:"numeric",comment:"Share of the target table (0-1) above which an UNATTENDED run refuses to remove. A scheduled run passes through neither the preview nor a confirmation, so this is the only thing between a wrong plan and the table. 0 or null disables."},{name:"password_target_column",type:"varchar",length:100,comment:"Column that receives the shared opening password given at run time. The password itself is never stored."},{name:"account_rule",type:"jsonb",comment:"Creates a login alongside each imported record, in the same transaction, and links it. The password belongs to the run, never to this row."},{name:"schedule_cron",type:"varchar",length:120},{name:"schedule_timezone",type:"varchar",length:64,comment:"IANA zone the cron expression is read in. Without it a nightly job drifts with the container's clock."},{name:"schedule_enabled",type:"boolean",notNull:!0,default:!1},{name:"last_run_at",type:"timestamptz"},{name:"enabled",type:"boolean",default:!0}],indexes:[{columns:["endpoint_id"]},{columns:["target_entity"]},{columns:["schedule_enabled"]}]},{table_name:"integration_runs",feature_set:["integrations"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],bulk_endpoints_enabled:!1,group_name:"Integrations",columns:[{name:"mapping_id",type:"uuid",references:{table:"integrationMappings",column:"id",onDelete:"set null"},comment:"Nullable and NOT cascaded: deleting a mapping must not erase the record that it once rewrote a table."},{name:"target_entity",type:"varchar",length:120},{name:"write_mode",type:"varchar",length:20,enumValues:["upsert","append","replace"]},{name:"status",type:"varchar",length:20,notNull:!0,default:"queued",enumValues:["queued","running","succeeded","failed","cancelled","reverted"],comment:"There is deliberately no 'partial': a run either applied in full or not at all."},{name:"trigger",type:"varchar",length:20,notNull:!0,default:"manual",enumValues:["manual","schedule","api"]},{name:"total_fetched",type:"integer",notNull:!0,default:0},{name:"source_reported_total",type:"integer",comment:"What the source said it had. When this and total_fetched disagree, a destructive run refuses to start."},{name:"created_count",type:"integer",notNull:!0,default:0},{name:"references_created_count",type:"integer",notNull:!0,default:0,comment:"Rows this run added to OTHER tables so its records could point at them."},{name:"accounts_created_count",type:"integer",notNull:!0,default:0,comment:"Logins this run created so its records could be signed in to."},{name:"updated_count",type:"integer",notNull:!0,default:0},{name:"skipped_count",type:"integer",notNull:!0,default:0},{name:"deleted_count",type:"integer",notNull:!0,default:0},{name:"deactivated_count",type:"integer",notNull:!0,default:0},{name:"error_count",type:"integer",notNull:!0,default:0},{name:"external_call_count",type:"integer",notNull:!0,default:0},{name:"issues",type:"jsonb",default:[]},{name:"errors",type:"jsonb",default:[]},{name:"cancel_requested",type:"boolean",notNull:!0,default:!1,comment:"Set by the cancel endpoint; the engine checks it at every batch boundary. A dropped HTTP connection is NOT a cancellation."},{name:"started_at",type:"timestamptz"},{name:"finished_at",type:"timestamptz"},{name:"pre_images_expire_at",type:"timestamptz",comment:"After this, the run can no longer be reverted and the UI says so rather than offering a button that quietly does nothing."},{name:"reverted_at",type:"timestamptz"},{name:"reverted_by",type:"uuid",references:{table:"users",column:"id"}},{name:"reverted_run_id",type:"uuid"}],indexes:[{columns:["mapping_id"]},{columns:["status"]},{columns:["target_entity"]},{columns:["created_at"]}]},{table_name:"integration_run_items",feature_set:["integrations"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],bulk_endpoints_enabled:!1,group_name:"Integrations",columns:[{name:"run_id",type:"uuid",notNull:!0,references:{table:"integrationRuns",column:"id",onDelete:"cascade"}},{name:"target_entity",type:"varchar",length:120,notNull:!0},{name:"row_id",type:"uuid"},{name:"action",type:"varchar",length:20,notNull:!0,enumValues:["create","update","delete","deactivate"]},{name:"before",type:"jsonb",comment:"The row as it stood before this run touched it. This is what makes a successful run reversible; the bulk delete path already produced these rows and threw them away."},{name:"after",type:"jsonb"}],indexes:[{columns:["run_id"]},{columns:["run_id","action"]},{columns:["target_entity","row_id"]}]}]};var AUTH_ENDPOINT_CONFIGS={login:{key:"LOGIN",method:"POST",defaultRoute:"/auth/login",defaultIsPublic:!0,_payload:void 0,_success:void 0,_error:void 0},register:{key:"REGISTER",method:"POST",defaultRoute:"/auth/register",defaultIsPublic:!0,_payload:void 0,_success:void 0,_error:void 0},logout:{key:"LOGOUT",method:"POST",defaultRoute:"/auth/logout",defaultIsPublic:!1,_payload:void 0,_success:void 0,_error:void 0},refresh:{key:"REFRESH",method:"POST",defaultRoute:"/auth/refresh",defaultIsPublic:!1,_payload:void 0,_success:void 0,_error:void 0},me:{key:"ME",method:"GET",defaultRoute:"/auth/me",defaultIsPublic:!1,_payload:void 0,_success:void 0,_error:void 0},passwordChange:{key:"PASSWORD_CHANGE",method:"POST",defaultRoute:"/auth/password-change",defaultIsPublic:!1,_payload:void 0,_success:void 0,_error:void 0},passwordSet:{key:"PASSWORD_SET",method:"POST",defaultRoute:"/auth/password-set",defaultIsPublic:!1,_payload:void 0,_success:void 0,_error:void 0},passwordReset:{key:"PASSWORD_RESET_REQUEST",method:"POST",defaultRoute:"/auth/password-reset",defaultIsPublic:!0,subEndpoints:[{key:"PASSWORD_RESET_REQUEST",method:"POST",suffix:"/request",_payload:void 0,_success:void 0,_error:void 0},{key:"PASSWORD_RESET_CONFIRM",method:"POST",suffix:"/confirm",_payload:void 0,_success:void 0,_error:void 0}]},sessions:{key:"SESSIONS",method:"GET",defaultRoute:"/auth/sessions",defaultIsPublic:!1,subEndpoints:[{key:"SESSIONS",method:"GET",suffix:"",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_CURRENT",method:"GET",suffix:"/current",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_STATS",method:"GET",suffix:"/stats",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_PENDING",method:"GET",suffix:"/pending",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_REVOKE",method:"DELETE",suffix:"/:sessionId",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_REVOKE_ALL",method:"DELETE",suffix:"/all",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_ADMIN_LIST",method:"GET",suffix:"/admin/:userId",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_ADMIN_REVOKE",method:"DELETE",suffix:"/admin/:userId",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_APPROVE",method:"POST",suffix:"/approve",_payload:void 0,_success:void 0,_error:void 0},{key:"SESSIONS_REJECT",method:"POST",suffix:"/reject",_payload:void 0,_success:void 0,_error:void 0}]},magicLink:{key:"MAGIC_LINK",method:"POST",defaultRoute:"/auth/magic-link",defaultIsPublic:!0,subEndpoints:[{key:"MAGIC_LINK",method:"POST",suffix:"",_payload:void 0,_success:void 0,_error:void 0},{key:"MAGIC_LINK_VERIFY",method:"GET",suffix:"/verify",routeKey:"verifyRoute",_payload:void 0,_success:void 0,_error:void 0}]},invite:{key:"INVITE",method:"POST",defaultRoute:"/auth/invite",defaultIsPublic:!1,subEndpoints:[{key:"INVITE",method:"POST",suffix:"",_payload:void 0,_success:void 0,_error:void 0},{key:"INVITE_VERIFY",method:"POST",suffix:"/verify",_payload:void 0,_success:void 0,_error:void 0}]},emailVerification:{key:"VERIFY_EMAIL",method:"GET",defaultRoute:"/verify-email",defaultIsPublic:!0,subEndpoints:[{key:"VERIFY_EMAIL",method:"GET",suffix:"",_payload:void 0,_success:void 0,_error:void 0},{key:"RESEND_VERIFICATION",method:"POST",suffix:"",routeKey:"resendRoute",defaultRoute:"/resend-verification",_payload:void 0,_success:void 0,_error:void 0}]},captcha:{key:"CAPTCHA",method:"GET",defaultRoute:"/auth/captcha",defaultIsPublic:!0,subEndpoints:[{key:"CAPTCHA_GENERATE",method:"GET",suffix:"/generate",_payload:void 0,_success:void 0,_error:void 0},{key:"CAPTCHA_VALIDATE",method:"POST",suffix:"/validate",_payload:void 0,_success:void 0,_error:void 0}]},oauth:{key:"OAUTH_PROVIDERS",method:"GET",defaultRoute:"/auth/oauth/providers",defaultIsPublic:!0,subEndpoints:[{key:"OAUTH_PROVIDERS",method:"GET",suffix:"/providers",_payload:void 0,_success:void 0,_error:void 0},{key:"OAUTH_REDIRECT",method:"GET",suffix:"/:provider",_payload:void 0,_success:void 0,_error:void 0},{key:"OAUTH_ACCOUNTS",method:"GET",suffix:"/accounts",_payload:void 0,_success:void 0,_error:void 0},{key:"OAUTH_UNLINK",method:"DELETE",suffix:"/unlink/:provider",_payload:void 0,_success:void 0,_error:void 0}]},webauthn:{key:"WEBAUTHN",method:"POST",defaultRoute:"/auth/webauthn",defaultIsPublic:!1,subEndpoints:[{key:"WEBAUTHN_REGISTER_OPTIONS",method:"POST",suffix:"/register/options",_payload:void 0,_success:void 0,_error:void 0},{key:"WEBAUTHN_REGISTER_VERIFY",method:"POST",suffix:"/register/verify",_payload:void 0,_success:void 0,_error:void 0},{key:"WEBAUTHN_AUTH_OPTIONS",method:"POST",suffix:"/authenticate/options",_payload:void 0,_success:void 0,_error:void 0},{key:"WEBAUTHN_AUTH_VERIFY",method:"POST",suffix:"/authenticate/verify",_payload:void 0,_success:void 0,_error:void 0},{key:"WEBAUTHN_LIST",method:"GET",suffix:"/credentials",_payload:void 0,_success:void 0,_error:void 0},{key:"WEBAUTHN_REVOKE",method:"DELETE",suffix:"/credentials/:credentialId",_payload:void 0,_success:void 0,_error:void 0},{key:"WEBAUTHN_RENAME",method:"PATCH",suffix:"/credentials/:credentialId",_payload:void 0,_success:void 0,_error:void 0}]},apiKeys:{key:"API_KEYS",method:"GET",defaultRoute:"/auth/api-keys",defaultIsPublic:!1,subEndpoints:[{key:"API_KEYS_CREATE",method:"POST",suffix:"",_payload:void 0,_success:void 0,_error:void 0},{key:"API_KEYS_LIST",method:"GET",suffix:"",_payload:void 0,_success:void 0,_error:void 0},{key:"API_KEYS_DETAIL",method:"GET",suffix:"/:id",_payload:void 0,_success:void 0,_error:void 0},{key:"API_KEYS_UPDATE",method:"PATCH",suffix:"/:id",_payload:void 0,_success:void 0,_error:void 0},{key:"API_KEYS_REVOKE",method:"DELETE",suffix:"/:id",_payload:void 0,_success:void 0,_error:void 0}]}},AUTH_ENDPOINTS={LOGIN:{method:"POST",path:"/auth/login",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},REGISTER:{method:"POST",path:"/auth/register",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},LOGOUT:{method:"POST",path:"/auth/logout",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},REFRESH:{method:"POST",path:"/auth/refresh",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},ME:{method:"GET",path:"/auth/me",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PASSWORD_CHANGE:{method:"POST",path:"/auth/password/change",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PASSWORD_SET:{method:"POST",path:"/auth/password/set",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PASSWORD_RESET_REQUEST:{method:"POST",path:"/auth/password/reset-request",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},PASSWORD_RESET_CONFIRM:{method:"POST",path:"/auth/password/reset-confirm",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},SESSIONS:{method:"GET",path:"/auth/sessions",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},SESSIONS_CURRENT:{method:"GET",path:"/auth/sessions/current",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},SESSIONS_STATS:{method:"GET",path:"/auth/sessions/stats",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},SESSIONS_PENDING:{method:"GET",path:"/auth/sessions/pending",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},SESSIONS_REVOKE:{method:"POST",path:"/auth/sessions/revoke",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},SESSIONS_REVOKE_ALL:{method:"POST",path:"/auth/sessions/revoke-all",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},SESSIONS_ADMIN_LIST:{method:"GET",path:"/auth/sessions/admin/:userId",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},SESSIONS_ADMIN_REVOKE:{method:"DELETE",path:"/auth/sessions/admin/:userId",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},SESSIONS_APPROVE:{method:"POST",path:"/auth/sessions/approve",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},SESSIONS_REJECT:{method:"POST",path:"/auth/sessions/reject",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},MAGIC_LINK:{method:"POST",path:"/auth/magic-link",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},MAGIC_LINK_VERIFY:{method:"POST",path:"/auth/magic-link/verify",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},INVITE:{method:"POST",path:"/auth/invite",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},INVITE_VERIFY:{method:"POST",path:"/auth/invite/verify",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},VERIFY_EMAIL:{method:"POST",path:"/auth/verify-email",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},RESEND_VERIFICATION:{method:"POST",path:"/auth/resend-verification",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},CAPTCHA_GENERATE:{method:"POST",path:"/auth/captcha/generate",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},CAPTCHA_VALIDATE:{method:"POST",path:"/auth/captcha/validate",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},WEBAUTHN_REGISTER_OPTIONS:{method:"POST",path:"/auth/webauthn/register/options",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},WEBAUTHN_REGISTER_VERIFY:{method:"POST",path:"/auth/webauthn/register/verify",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},WEBAUTHN_AUTH_OPTIONS:{method:"POST",path:"/auth/webauthn/authenticate/options",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},WEBAUTHN_AUTH_VERIFY:{method:"POST",path:"/auth/webauthn/authenticate/verify",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},WEBAUTHN_LIST:{method:"GET",path:"/auth/webauthn/credentials",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},WEBAUTHN_REVOKE:{method:"DELETE",path:"/auth/webauthn/credentials/:credentialId",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},WEBAUTHN_RENAME:{method:"PATCH",path:"/auth/webauthn/credentials/:credentialId",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},ADMIN_IMPERSONATE:{method:"POST",path:"/auth/admin/impersonate",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},ADMIN_IMPERSONATE_STOP:{method:"POST",path:"/auth/admin/impersonate/stop",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},ADMIN_CHANGE_USER_ID:{method:"POST",path:"/auth/admin/change-user-id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},ADMIN_CREATE_USER:{method:"POST",path:"/auth/admin/create-user",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},ADMIN_HARD_DELETE_USER:{method:"DELETE",path:"/auth/admin/hard-delete/:userId",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},API_KEYS_CREATE:{method:"POST",path:"/auth/api-keys",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},API_KEYS_LIST:{method:"GET",path:"/auth/api-keys",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},API_KEYS_DETAIL:{method:"GET",path:"/auth/api-keys/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},API_KEYS_UPDATE:{method:"PUT",path:"/auth/api-keys/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},API_KEYS_REVOKE:{method:"DELETE",path:"/auth/api-keys/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0}},CONFIG_ENDPOINTS={CONFIG_GET:{method:"GET",path:"/nucleus/config",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CONFIG_SECTIONS:{method:"GET",path:"/nucleus/config/sections",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CONFIG_SECTION_GET:{method:"GET",path:"/nucleus/config/:section",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CONFIG_SECTION_UPDATE:{method:"PATCH",path:"/nucleus/config/:section",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CONFIG_ENV:{method:"GET",path:"/nucleus/config/env",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CONFIG_OVERRIDES_GET:{method:"GET",path:"/nucleus/config/overrides",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CONFIG_OVERRIDES_CLEAR:{method:"DELETE",path:"/nucleus/config/overrides",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CONFIG_RESTART:{method:"POST",path:"/nucleus/config/restart",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0}},VERIFICATION_ENDPOINTS={VERIFICATION_STATUS:{method:"GET",path:"/verification/status/:entity_name/:entity_id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},VERIFICATION_DECIDE:{method:"POST",path:"/verification/decide/:entity_name/:entity_id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},VERIFICATION_PENDING:{method:"GET",path:"/verification/pending",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},VERIFICATION_HISTORY:{method:"GET",path:"/verification/history/:entity_name/:entity_id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},VERIFICATION_START:{method:"POST",path:"/verification/start",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},VERIFICATION_START_FOR_ENTITY:{method:"POST",path:"/verification/start-for-entity",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},VERIFICATION_ENTITY_STATUSES:{method:"GET",path:"/verification/entity-statuses/:entity_name",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},FLOW_LIST:{method:"GET",path:"/verification/flows",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},FLOW_GET:{method:"GET",path:"/verification/flows/:flow_id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},FLOW_SAVE:{method:"POST",path:"/verification/flows",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},FLOW_PUBLISH:{method:"POST",path:"/verification/flows/:flow_id/publish",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},FLOW_DELETE:{method:"DELETE",path:"/verification/flows/:flow_id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},NOTIFICATION_LIST:{method:"GET",path:"/notifications",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},NOTIFICATION_UNSEEN_COUNT:{method:"GET",path:"/notifications/unseen-count",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},NOTIFICATION_MARK_SEEN:{method:"POST",path:"/notifications/:notification_id/seen",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},NOTIFICATION_MARK_ALL_SEEN:{method:"POST",path:"/notifications/seen-all",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0}},CHAT_ENDPOINTS={CHAT_LIST_CONVERSATIONS:{method:"GET",path:"/chat/conversations",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CHAT_CREATE_CONVERSATION:{method:"POST",path:"/chat/conversations",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CHAT_GET_CONVERSATION:{method:"GET",path:"/chat/conversations/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CHAT_GET_MESSAGES:{method:"GET",path:"/chat/conversations/:id/messages",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CHAT_SEND_MESSAGE:{method:"POST",path:"/chat/conversations/:id/messages",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CHAT_MARK_READ:{method:"POST",path:"/chat/conversations/:id/read",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CHAT_TYPING:{method:"POST",path:"/chat/conversations/:id/typing",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CHAT_ADD_PARTICIPANTS:{method:"POST",path:"/chat/conversations/:id/participants",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CHAT_REMOVE_PARTICIPANT:{method:"DELETE",path:"/chat/conversations/:id/participants/:userId",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CHAT_EDIT_MESSAGE:{method:"PATCH",path:"/chat/messages/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},CHAT_DELETE_MESSAGE:{method:"DELETE",path:"/chat/messages/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0}},MONITORING_ENDPOINTS={MONITORING_HEALTH_CHECK:{method:"GET",path:"/monitoring/health",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},MONITORING_GET_SETTINGS:{method:"GET",path:"/monitoring/settings",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},MONITORING_CHANGE_SETTINGS:{method:"PATCH",path:"/monitoring/settings",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},MONITORING_GET_LOGS:{method:"GET",path:"/monitoring/logs",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0}},PAYMENT_ENDPOINTS={PAYMENT_INITIALIZE:{method:"POST",path:"/payments/initialize",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_TRANSACTIONS:{method:"GET",path:"/payments/transactions",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_TRANSACTION_DETAIL:{method:"GET",path:"/payments/transactions/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_BIN_QUERY:{method:"POST",path:"/payments/bin-query",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_DETAIL:{method:"POST",path:"/payments/payment-detail",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_REFUND:{method:"POST",path:"/payments/refund",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_SAVE_CARD:{method:"POST",path:"/payments/cards/save",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_LIST_CARDS:{method:"GET",path:"/payments/cards",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_DELETE_CARD:{method:"DELETE",path:"/payments/cards/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_SYNC_CARDS:{method:"POST",path:"/payments/cards/sync",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_REGISTER_SUB_MERCHANT:{method:"POST",path:"/payments/sub-merchants",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_UPDATE_SUB_MERCHANT:{method:"PUT",path:"/payments/sub-merchants/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_LIST_SUB_MERCHANTS:{method:"GET",path:"/payments/sub-merchants",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_GET_SUB_MERCHANT:{method:"GET",path:"/payments/sub-merchants/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_LIST_SPLITS:{method:"GET",path:"/payments/splits",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_APPROVE_SPLIT:{method:"POST",path:"/payments/splits/:splitId/approve",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_DISAPPROVE_SPLIT:{method:"POST",path:"/payments/splits/:splitId/disapprove",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_CREATE_PRODUCT:{method:"POST",path:"/payments/products",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_UPDATE_PRODUCT:{method:"PUT",path:"/payments/products/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_LIST_PRODUCTS:{method:"GET",path:"/payments/products",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_GET_PRODUCT:{method:"GET",path:"/payments/products/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_ARCHIVE_PRODUCT:{method:"DELETE",path:"/payments/products/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_CREATE_PRICE:{method:"POST",path:"/payments/prices",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_UPDATE_PRICE:{method:"PUT",path:"/payments/prices/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_LIST_PRICES:{method:"GET",path:"/payments/prices",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_GET_PRICE:{method:"GET",path:"/payments/prices/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_ARCHIVE_PRICE:{method:"DELETE",path:"/payments/prices/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_CREATE_CUSTOMER:{method:"POST",path:"/payments/customers",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_UPDATE_CUSTOMER:{method:"PUT",path:"/payments/customers/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_LIST_CUSTOMERS:{method:"GET",path:"/payments/customers",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_GET_CUSTOMER:{method:"GET",path:"/payments/customers/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_DELETE_CUSTOMER:{method:"DELETE",path:"/payments/customers/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_CREATE_SUBSCRIPTION:{method:"POST",path:"/payments/subscriptions",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_UPDATE_SUBSCRIPTION:{method:"PUT",path:"/payments/subscriptions/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_CANCEL_SUBSCRIPTION:{method:"POST",path:"/payments/subscriptions/:id/cancel",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_LIST_SUBSCRIPTIONS:{method:"GET",path:"/payments/subscriptions",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_GET_SUBSCRIPTION:{method:"GET",path:"/payments/subscriptions/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_REPORT_USAGE:{method:"POST",path:"/payments/usage-records",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_LIST_USAGE_SUMMARIES:{method:"GET",path:"/payments/usage-records/:subscriptionItemId/summaries",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_CREATE_INVOICE:{method:"POST",path:"/payments/invoices",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_FINALIZE_INVOICE:{method:"POST",path:"/payments/invoices/:id/finalize",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_SEND_INVOICE:{method:"POST",path:"/payments/invoices/:id/send",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_VOID_INVOICE:{method:"POST",path:"/payments/invoices/:id/void",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_PAY_INVOICE:{method:"POST",path:"/payments/invoices/:id/pay",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_LIST_INVOICES:{method:"GET",path:"/payments/invoices",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_GET_INVOICE:{method:"GET",path:"/payments/invoices/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_GET_BALANCE:{method:"GET",path:"/payments/balance",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_CREATE_PAYOUT:{method:"POST",path:"/payments/payouts",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_LIST_PAYOUTS:{method:"GET",path:"/payments/payouts",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_GET_PAYOUT:{method:"GET",path:"/payments/payouts/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_CANCEL_PAYOUT:{method:"POST",path:"/payments/payouts/:id/cancel",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_CREATE_TRANSFER:{method:"POST",path:"/payments/transfers",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_LIST_TRANSFERS:{method:"GET",path:"/payments/transfers",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0}},TENANT_ENDPOINTS={TENANT_CHECK_SUBDOMAIN:{method:"GET",path:"/tenants/check-subdomain/:subdomain",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},TENANT_PROVISION:{method:"POST",path:"/tenants/provision",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},TENANT_LIST:{method:"GET",path:"/tenants",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},TENANT_DETAIL:{method:"GET",path:"/tenants/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},TENANT_SUSPEND:{method:"POST",path:"/tenants/:id/suspend",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},TENANT_REACTIVATE:{method:"POST",path:"/tenants/:id/reactivate",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},TENANT_SELF_SIGNUP:{method:"POST",path:"/tenants/self-signup",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0}},DOMAIN_ENDPOINTS={DOMAIN_RESOLVE:{method:"GET",path:"/domains/resolve",isPublic:!0,_payload:void 0,_success:void 0,_error:void 0},DOMAIN_CREATE_HOSTNAME:{method:"POST",path:"/domains/hostnames",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},DOMAIN_LIST_HOSTNAMES:{method:"GET",path:"/domains/hostnames",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},DOMAIN_GET_HOSTNAME:{method:"GET",path:"/domains/hostnames/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},DOMAIN_HOSTNAME_INSTRUCTIONS:{method:"GET",path:"/domains/hostnames/:id/instructions",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},DOMAIN_VERIFY_HOSTNAME:{method:"POST",path:"/domains/hostnames/:id/verify",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},DOMAIN_ACTIVATE_HOSTNAME:{method:"POST",path:"/domains/hostnames/:id/activate",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},DOMAIN_DISABLE_HOSTNAME:{method:"POST",path:"/domains/hostnames/:id/disable",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},DOMAIN_MAKE_PRIMARY:{method:"POST",path:"/domains/hostnames/:id/make-primary",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},DOMAIN_REFRESH_HOSTNAME:{method:"POST",path:"/domains/hostnames/:id/refresh-status",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},DOMAIN_CREATE_REGISTRATION:{method:"POST",path:"/domains/registrations",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},DOMAIN_LIST_REGISTRATIONS:{method:"GET",path:"/domains/registrations",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},DOMAIN_GET_REGISTRATION:{method:"GET",path:"/domains/registrations/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},DOMAIN_CANCEL_REGISTRATION:{method:"POST",path:"/domains/registrations/:id/cancel",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},DOMAIN_TRANSFER_OUT:{method:"POST",path:"/domains/registrations/:id/transfer-out",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0}},MARKETPLACE_ENDPOINTS={PAYMENT_MARKETPLACE_RECORD_SPLIT:{method:"POST",path:"/payment/marketplace/splits",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_MARKETPLACE_LIST_SPLITS:{method:"GET",path:"/payment/marketplace/splits",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_MARKETPLACE_BALANCE:{method:"GET",path:"/payment/marketplace/balance/:ownerId",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_MARKETPLACE_RELEASE_RESERVE:{method:"POST",path:"/payment/marketplace/reserves/:id/release",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_MARKETPLACE_GET_SETTLEMENT_POLICY:{method:"GET",path:"/payment/marketplace/settlement-policy",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_MARKETPLACE_UPSERT_SETTLEMENT_POLICY:{method:"POST",path:"/payment/marketplace/settlement-policy",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_MARKETPLACE_REQUEST_PAYOUT:{method:"POST",path:"/payment/marketplace/payout-requests",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_MARKETPLACE_LIST_PAYOUTS:{method:"GET",path:"/payment/marketplace/payout-requests",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_MARKETPLACE_GET_PAYOUT:{method:"GET",path:"/payment/marketplace/payout-requests/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_MARKETPLACE_APPROVE_PAYOUT:{method:"POST",path:"/payment/marketplace/payout-requests/:id/approve",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_MARKETPLACE_REJECT_PAYOUT:{method:"POST",path:"/payment/marketplace/payout-requests/:id/reject",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_MARKETPLACE_OPEN_DISPUTE:{method:"POST",path:"/payment/marketplace/disputes",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_MARKETPLACE_LIST_DISPUTES:{method:"GET",path:"/payment/marketplace/disputes",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},PAYMENT_MARKETPLACE_RESOLVE_DISPUTE:{method:"POST",path:"/payment/marketplace/disputes/:id/resolve",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0}},COHORT_ENDPOINTS={ADMIN_LIST_COHORTS:{method:"GET",path:"/auth/admin/cohorts",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},ADMIN_GET_COHORT:{method:"GET",path:"/auth/admin/cohorts/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},ADMIN_CREATE_COHORT:{method:"POST",path:"/auth/admin/cohorts",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},ADMIN_UPDATE_COHORT:{method:"PATCH",path:"/auth/admin/cohorts/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},ADMIN_DELETE_COHORT:{method:"DELETE",path:"/auth/admin/cohorts/:id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},ADMIN_COHORT_BULK_CREATE:{method:"POST",path:"/auth/admin/cohorts/:id/bulk-create",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},ADMIN_COHORT_DEACTIVATE:{method:"POST",path:"/auth/admin/cohorts/:id/deactivate-users",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},ADMIN_COHORT_ACTIVATE:{method:"POST",path:"/auth/admin/cohorts/:id/activate-users",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},ADMIN_COHORT_DELETE_USERS:{method:"POST",path:"/auth/admin/cohorts/:id/delete-users",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},ADMIN_COHORT_EXPORT:{method:"GET",path:"/auth/admin/cohorts/:id/export",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0}};var SYSTEM_TABLE_NAMES=["profiles","addresses","phones","files","users","roles","claims","user_roles","role_claims","audit_logs","monitoring_metrics","integration_sources","integration_endpoints","integration_mappings","integration_runs","integration_run_items"],systemTables=system_tables_default.tables.filter((t)=>SYSTEM_TABLE_NAMES.includes(t.table_name));function toUpperSnakeCase(str){return str.replace(/([a-z])([A-Z])/g,"$1_$2").replace(/[\s-]+/g,"_").toUpperCase()}function snakeToCamelCase(str){return str.replace(/_([a-z])/g,(_,letter)=>letter.toUpperCase())}function singularize(str){if(str.endsWith("ies"))return`${str.slice(0,-3)}y`;if(str.endsWith("ses"))return`${str.slice(0,-2)}`;if(str.endsWith("s"))return str.slice(0,-1);return str}function generateEntityEndpointKey(tableName,method){let upperName=toUpperSnakeCase(tableName),singularName=toUpperSnakeCase(singularize(tableName));switch(method){case"GET":return`GET_${upperName}`;case"POST":return`ADD_${singularName}`;case"PUT":return`UPDATE_${singularName}`;case"PATCH":return`PATCH_${singularName}`;case"DELETE":return`DELETE_${singularName}`}}function generateBulkEndpointKey(tableName,method){let upperName=toUpperSnakeCase(tableName);switch(method){case"POST":return`BULK_ADD_${upperName}`;case"PUT":return`BULK_UPDATE_${upperName}`;case"DELETE":return`BULK_DELETE_${upperName}`}}function isMethodExcluded(table,method){if(!table.excluded_methods)return!1;let methodMap={GET:"GET",POST:"POST",PUT:"PUT",PATCH:"PATCH",DELETE:"DELETE"};return table.excluded_methods.includes(methodMap[method])}function generateEndpointsFromConfig(config){let endpoints={};for(let table of config.entities){let tableName=table.table_name,basePath=`/${snakeToCamelCase(tableName)}`,sid=table.serviceId;if(!isMethodExcluded(table,"GET")){endpoints[generateEntityEndpointKey(tableName,"GET")]={method:"GET",path:basePath,isPublic:table.is_public?.GET??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0};let singularName=toUpperSnakeCase(singularize(tableName));endpoints[`GET_${singularName}_BY_ID`]={method:"GET",path:`${basePath}/:id`,isPublic:table.is_public?.GET??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0},endpoints[`GET_${toUpperSnakeCase(tableName)}_DISTINCT`]={method:"GET",path:`${basePath}/distinct/:field`,isPublic:table.is_public?.GET??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0}}if(!isMethodExcluded(table,"POST"))endpoints[generateEntityEndpointKey(tableName,"POST")]={method:"POST",path:basePath,isPublic:table.is_public?.POST??!1,isFormData:table.is_form_data,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0};if(!isMethodExcluded(table,"PUT"))endpoints[generateEntityEndpointKey(tableName,"PUT")]={method:"PUT",path:`${basePath}/:id`,isPublic:table.is_public?.PUT??!1,isFormData:table.is_form_data,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0};if(!isMethodExcluded(table,"PATCH"))endpoints[generateEntityEndpointKey(tableName,"PATCH")]={method:"PATCH",path:`${basePath}/:id`,isPublic:table.is_public?.PATCH??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0};if(!isMethodExcluded(table,"DELETE"))endpoints[generateEntityEndpointKey(tableName,"DELETE")]={method:"DELETE",path:`${basePath}/:id`,isPublic:table.is_public?.DELETE??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0};if(table.bulk_endpoints_enabled){if(!isMethodExcluded(table,"POST"))endpoints[generateBulkEndpointKey(tableName,"POST")]={method:"POST",path:`${basePath}/bulk`,isPublic:table.is_public?.POST??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0};if(!isMethodExcluded(table,"PUT"))endpoints[generateBulkEndpointKey(tableName,"PUT")]={method:"PUT",path:`${basePath}/bulk`,isPublic:table.is_public?.PUT??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0};if(!isMethodExcluded(table,"DELETE"))endpoints[generateBulkEndpointKey(tableName,"DELETE")]={method:"DELETE",path:`${basePath}/bulk`,isPublic:table.is_public?.DELETE??!1,serviceId:sid,_payload:void 0,_success:void 0,_error:void 0}}}return endpoints}function generateAuthEndpoints(config){let endpoints={},auth=config.authentication;if(!auth?.enabled)return endpoints;for(let[featureKey,endpointConfig]of Object.entries(AUTH_ENDPOINT_CONFIGS)){let feature=auth[featureKey];if(!feature?.enabled)continue;let feat=feature,baseRoute=feat.route||endpointConfig.defaultRoute,isPublic=feat.isPublic??endpointConfig.defaultIsPublic;if("subEndpoints"in endpointConfig&&endpointConfig.subEndpoints)for(let sub of endpointConfig.subEndpoints){let subRoute="routeKey"in sub&&sub.routeKey&&feature[sub.routeKey]?String(feature[sub.routeKey]):("defaultRoute"in sub)&&sub.defaultRoute?String(sub.defaultRoute):`${baseRoute}${sub.suffix}`;endpoints[sub.key]={method:sub.method,path:subRoute,isPublic:sub.key==="MAGIC_LINK_VERIFY"?!0:isPublic,_payload:sub._payload,_success:sub._success,_error:sub._error}}else if("_payload"in endpointConfig)endpoints[endpointConfig.key]={method:endpointConfig.method,path:baseRoute,isPublic,_payload:endpointConfig._payload,_success:endpointConfig._success,_error:endpointConfig._error}}return endpoints}function generateSystemTableEndpoints(){let endpoints={};for(let table of systemTables){let tableName=table.table_name,basePath=`/${snakeToCamelCase(tableName)}`,isFormData=tableName==="files";endpoints[generateEntityEndpointKey(tableName,"GET")]={method:"GET",path:basePath,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0};let singularName=toUpperSnakeCase(singularize(tableName));if(endpoints[`GET_${singularName}_BY_ID`]={method:"GET",path:`${basePath}/:id`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},!isMethodExcluded(table,"POST"))endpoints[generateEntityEndpointKey(tableName,"POST")]={method:"POST",path:basePath,isPublic:!1,isFormData,_payload:void 0,_success:void 0,_error:void 0};if(!isMethodExcluded(table,"PUT"))endpoints[generateEntityEndpointKey(tableName,"PUT")]={method:"PUT",path:`${basePath}/:id`,isPublic:!1,isFormData,_payload:void 0,_success:void 0,_error:void 0};if(!isMethodExcluded(table,"PATCH"))endpoints[generateEntityEndpointKey(tableName,"PATCH")]={method:"PATCH",path:`${basePath}/:id`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0};if(!isMethodExcluded(table,"DELETE"))endpoints[generateEntityEndpointKey(tableName,"DELETE")]={method:"DELETE",path:`${basePath}/:id`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0};if(table.bulk_endpoints_enabled)endpoints[generateBulkEndpointKey(tableName,"POST")]={method:"POST",path:`${basePath}/bulk`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints[generateBulkEndpointKey(tableName,"PUT")]={method:"PUT",path:`${basePath}/bulk`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints[generateBulkEndpointKey(tableName,"DELETE")]={method:"DELETE",path:`${basePath}/bulk`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0}}return endpoints}function generateMonitoringEndpoints(config){if(!config.liveMonitoring?.enabled)return{};return{...MONITORING_ENDPOINTS}}function generateAdminEndpoints(config){let endpoints={};if(!config.authentication?.enabled)return endpoints;return endpoints.ADMIN_IMPERSONATE={method:"POST",path:"/auth/admin/impersonate",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.ADMIN_IMPERSONATE_STOP={method:"POST",path:"/auth/admin/impersonate/stop",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.ADMIN_CHANGE_USER_ID={method:"POST",path:"/auth/admin/change-user-id",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.ADMIN_CREATE_USER={method:"POST",path:"/auth/admin/create-user",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.ADMIN_HARD_DELETE_USER={method:"DELETE",path:"/auth/admin/hard-delete/:userId",isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints}function generateCohortEndpoints(config){let auth=config.authentication;if(!auth?.enabled||!auth.cohorts?.enabled)return{};return{...COHORT_ENDPOINTS}}function generateVerificationEndpoints(config){let endpoints={},verification=config.verification,notification=config.notification;if(!verification?.enabled)return endpoints;let basePath=verification.endpoints?.basePath||"/verifications",flowBasePath=verification.flowEndpoints?.basePath||"/verification-flows",notifBasePath=notification?.endpoints?.basePath||"/notifications";if(endpoints.VERIFICATION_STATUS={method:"GET",path:`${basePath}/status/:entity_name/:entity_id`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.VERIFICATION_DECIDE={method:"POST",path:`${basePath}/:entity_name/:entity_id/decide`,isPublic:!1,skipCamelCase:!0,_payload:void 0,_success:void 0,_error:void 0},endpoints.VERIFICATION_PENDING={method:"GET",path:`${basePath}/pending`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.VERIFICATION_HISTORY={method:"GET",path:`${basePath}/history/:entity_name/:entity_id`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.VERIFICATION_START={method:"POST",path:`${basePath}/start`,isPublic:!1,skipCamelCase:!0,_payload:void 0,_success:void 0,_error:void 0},endpoints.VERIFICATION_START_FOR_ENTITY={method:"POST",path:`${basePath}/start-for-entity`,isPublic:!1,skipCamelCase:!0,_payload:void 0,_success:void 0,_error:void 0},endpoints.VERIFICATION_ENTITY_STATUSES={method:"GET",path:`${basePath}/statuses/:entity_name`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},verification.flowEndpoints?.enabled)endpoints.FLOW_LIST={method:"GET",path:flowBasePath,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.FLOW_GET={method:"GET",path:`${flowBasePath}/:flow_id`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.FLOW_SAVE={method:"POST",path:flowBasePath,isPublic:!1,skipCamelCase:!0,_payload:void 0,_success:void 0,_error:void 0},endpoints.FLOW_PUBLISH={method:"POST",path:`${flowBasePath}/:flow_id/publish`,isPublic:!1,skipCamelCase:!0,_payload:void 0,_success:void 0,_error:void 0},endpoints.FLOW_DELETE={method:"DELETE",path:`${flowBasePath}/:flow_id`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0};if(notification?.enabled&¬ification.endpoints?.enabled)endpoints.NOTIFICATION_LIST={method:"GET",path:notifBasePath,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.NOTIFICATION_UNSEEN_COUNT={method:"GET",path:`${notifBasePath}/unseen-count`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.NOTIFICATION_MARK_SEEN={method:"POST",path:`${notifBasePath}/:notification_id/seen`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0},endpoints.NOTIFICATION_MARK_ALL_SEEN={method:"POST",path:`${notifBasePath}/seen-all`,isPublic:!1,_payload:void 0,_success:void 0,_error:void 0};return endpoints}function generateTenantEndpoints(config){if(!config.database?.isMultiTenant)return{};return{...TENANT_ENDPOINTS}}function generateChatEndpoints(config){if(!config.chat?.enabled)return{};return{...CHAT_ENDPOINTS}}function generateDomainEndpoints(config){if(!config.domains?.enabled)return{};return{...DOMAIN_ENDPOINTS}}function generateMarketplaceEndpoints(config){let payment=config.payment;if(!payment?.enabled||!payment.marketplace?.enabled)return{};return{...MARKETPLACE_ENDPOINTS}}function generateAllEndpoints(config,extraEndpoints){let entityEndpoints=generateEndpointsFromConfig(config),authEndpoints=generateAuthEndpoints(config),adminEndpoints=generateAdminEndpoints(config),cohortEndpoints=generateCohortEndpoints(config),systemEndpoints=generateSystemTableEndpoints(),monitoringEndpoints=generateMonitoringEndpoints(config),verificationEndpoints=generateVerificationEndpoints(config),chatEndpoints=generateChatEndpoints(config),tenantEndpoints=generateTenantEndpoints(config),domainEndpoints=generateDomainEndpoints(config),marketplaceEndpoints=generateMarketplaceEndpoints(config);return{...entityEndpoints,...authEndpoints,...adminEndpoints,...cohortEndpoints,...systemEndpoints,...monitoringEndpoints,...verificationEndpoints,...chatEndpoints,...tenantEndpoints,...domainEndpoints,...marketplaceEndpoints,...extraEndpoints??{}}}init_Logger();var DEFAULT_CONFIG2={timeout:30000,retries:0,retryDelay:1000,debug:!1};class ServerFetch{config;logger;constructor(config={}){this.config={...DEFAULT_CONFIG2,...config},this.logger=new Logger({service:"ServerFetch",prettyPrint:this.config.debug,colorize:this.config.debug,auditEnabled:!1})}buildUrl(url){if(url.startsWith("http://")||url.startsWith("https://"))return url;return this.config.baseUrl?`${this.config.baseUrl}${url}`:url}buildHeaders(customHeaders){let headers=new Headers;if(this.config.defaultHeaders)for(let[key,value]of Object.entries(this.config.defaultHeaders))headers.set(key,value);if(customHeaders)if(customHeaders instanceof Headers)customHeaders.forEach((value,key)=>{headers.set(key,value)});else if(Array.isArray(customHeaders))for(let[key,value]of customHeaders)headers.set(key,value);else for(let[key,value]of Object.entries(customHeaders))headers.set(key,value);return headers}parseResponseHeaders(headers){let result={};if(headers.forEach((value,key)=>{if(key.toLowerCase()==="set-cookie"){let existing=result[key];result[key]=existing?`${existing}, ${value}`:value}else result[key]=value}),typeof headers.getSetCookie==="function"){let setCookies=headers.getSetCookie();if(setCookies.length>0)result["set-cookie"]=setCookies.join(", ")}return result}async executeWithTimeout(promise,timeoutMs,_requestId){let controller=new AbortController,timeoutId=setTimeout(()=>controller.abort(),timeoutMs);try{return await Promise.race([promise,new Promise((_,reject)=>{controller.signal.addEventListener("abort",()=>{reject(Error(`Request timeout after ${timeoutMs}ms`))})})])}finally{clearTimeout(timeoutId)}}async fetch(options){let requestId=randomId(),startTime=performance.now(),url=this.buildUrl(options.url),headers=this.buildHeaders(options.headers),timeout=options.timeout??this.config.timeout??30000,retries=options.retries??this.config.retries??0,retryDelay=options.retryDelay??this.config.retryDelay??1000,body;if(options.body)if(typeof options.body==="object"&&!(options.body instanceof FormData)&&!(options.body instanceof URLSearchParams)&&!(options.body instanceof Blob)&&!(options.body instanceof ArrayBuffer)){if(body=JSON.stringify(options.body),!headers.has("content-type"))headers.set("content-type","application/json")}else body=options.body;this.logger.debug(`[${requestId}] ${options.method} ${url}`,{method:options.method,url,hasBody:!!body});let lastError=null,attempt=0;while(attempt<=retries)try{let response=await this.executeWithTimeout(fetch(url,{method:options.method,headers,body}),timeout,requestId),durationMs2=performance.now()-startTime,responseHeaders=this.parseResponseHeaders(response.headers),rawSetCookies=typeof response.headers.getSetCookie==="function"?response.headers.getSetCookie():[],responseData,errorData,rawText=await response.text();if(rawText)try{let json=JSON.parse(rawText);if(response.ok)responseData=json;else errorData=json}catch{if(!response.ok)errorData={message:rawText||response.statusText}}else if(!response.ok)errorData={message:response.statusText};let result={isSuccess:response.ok,response:responseData,errors:errorData,code:response.status,headers:responseHeaders,rawSetCookies,durationMs:durationMs2,requestId,createdAt:new Date};if(response.ok)this.logger.info(`[${requestId}] ${options.method} ${url} ${response.status}`,{method:options.method,url,statusCode:response.status,durationMs:Math.round(durationMs2)});else this.logger.warn(`[${requestId}] ${options.method} ${url} ${response.status}`,{method:options.method,url,statusCode:response.status,durationMs:Math.round(durationMs2),error:errorData});return result}catch(error){if(lastError=error instanceof Error?error:Error(String(error)),attempt++,attempt<=retries)this.logger.warn(`[${requestId}] Retry ${attempt}/${retries} after error`,{method:options.method,url,error:lastError.message,attempt,retries}),await new Promise((resolve)=>setTimeout(resolve,retryDelay))}let durationMs=performance.now()-startTime;return this.logger.error(`[${requestId}] ${options.method} ${url} failed`,lastError,{method:options.method,url,durationMs:Math.round(durationMs),attempts:attempt}),{isSuccess:!1,response:void 0,errors:{message:lastError?.message||"Unknown error"},code:null,headers:{},rawSetCookies:[],durationMs,requestId,createdAt:new Date}}async get(url,options){return this.fetch({...options,url,method:"GET"})}async post(url,body,options){return this.fetch({...options,url,method:"POST",body})}async put(url,body,options){return this.fetch({...options,url,method:"PUT",body})}async patch(url,body,options){return this.fetch({...options,url,method:"PATCH",body})}async delete(url,options){return this.fetch({...options,url,method:"DELETE"})}}var serverFetch=new ServerFetch;var DEFAULT_TOKEN_NAMES={accessToken:"access_token",refreshToken:"refresh_token",sessionToken:"session_token"};function splitSetCookieHeader(header){let cookies=[],current="";for(let i=0;i<header.length;i++){let char=header[i];if(char===","){let next=header.slice(i+1).trimStart();if(/^[a-zA-Z0-9_-]+=/.test(next)){cookies.push(current.trim()),current="";continue}}current+=char}if(current.trim())cookies.push(current.trim());return cookies}function buildRequestHeaders(headersStore,tokenNames){let headers={},forwardHeaders=["x-forwarded-for","x-real-ip","user-agent","accept-language","x-request-id","x-client-ip","cf-connecting-ip","true-client-ip","x-tenant-id","x-app-origin"];for(let header of forwardHeaders){let value=headersStore.get(header);if(value)headers[header]=value}if(!headers["user-agent"])headers["user-agent"]="Nucleus-ServerAction/1.0";let accessToken=headersStore.get(`x-${tokenNames.accessToken}`),refreshToken=headersStore.get(`x-${tokenNames.refreshToken}`),sessionToken=headersStore.get(`x-${tokenNames.sessionToken}`);if(accessToken)headers[`x-${tokenNames.accessToken}`]=accessToken;if(refreshToken)headers[`x-${tokenNames.refreshToken}`]=refreshToken;if(sessionToken)headers[`x-${tokenNames.sessionToken}`]=sessionToken;let cookieHeader=headersStore.get("cookie");if(cookieHeader)headers.cookie=cookieHeader;return headers}function toCamelCase(str){return str.replace(/_([a-z])/g,(_,c)=>c.toUpperCase())}function convertKeysToCamelCase(obj){let result={};for(let[key,value]of Object.entries(obj)){let camelKey=key.startsWith("_")?key:toCamelCase(key);if(value instanceof Date)result[camelKey]=value.toISOString();else if(value&&typeof value==="object"&&!Array.isArray(value))result[camelKey]=convertKeysToCamelCase(value);else result[camelKey]=value}return result}var JSON_STRINGIFY_KEYS=new Set(["filters","sort","with","searchFields","select","distinctOn"]);function appendQueryParams(url,params){let searchParams=new URLSearchParams;for(let[key,value]of Object.entries(params)){if(value===void 0||value===null)continue;if(JSON_STRINGIFY_KEYS.has(key)&&typeof value==="object"){searchParams.append(key,JSON.stringify(value));continue}if(value instanceof Date)searchParams.append(key,value.toISOString());else if(Array.isArray(value))searchParams.append(key,value.filter((v)=>v!=null).map(String).join(","));else if(typeof value==="object")searchParams.append(key,JSON.stringify(value));else searchParams.append(key,String(value))}let queryString=searchParams.toString();if(!queryString)return url;return url.includes("?")?`${url}&${queryString}`:`${url}?${queryString}`}function createServerFactory(endpoints,config,getCookies,getHeaders){let tokenNames={...DEFAULT_TOKEN_NAMES,...config.tokenNames},serverFetch2=new ServerFetch({baseUrl:config.baseUrl,debug:config.debug,timeout:30000,retries:0});return async function(endpointKey,payload){let endpoint=endpoints[endpointKey];if(!endpoint)return{isSuccess:!1,errors:{message:`Endpoint "${endpointKey}" not found`},code:404};let cookieStore=await getCookies(),headersStore=await getHeaders(),allHeaders={};if(headersStore.forEach((value,key)=>{allHeaders[key]=value}),(endpoint.path.includes("/auth/login")||endpoint.path.includes("/auth/oauth"))&&endpoint.method==="POST")try{cookieStore.delete(tokenNames.accessToken),cookieStore.delete(tokenNames.refreshToken),cookieStore.delete(tokenNames.sessionToken)}catch(_){}let headers=buildRequestHeaders(headersStore,tokenNames),url=endpoint.path,body,pathParamNames=new Set,pathParamRegex=/:([a-zA-Z_][a-zA-Z0-9_]*)/g,paramMatch=pathParamRegex.exec(url);while(paramMatch!==null){if(paramMatch[1])pathParamNames.add(paramMatch[1]);paramMatch=pathParamRegex.exec(url)}if(payload&&typeof payload==="object"&&!(payload instanceof FormData)){let payloadObj=payload;for(let[key,value]of Object.entries(payloadObj))if(value!=null){if(pathParamNames.has(key))url=url.replace(`:${key}`,String(value));else if(key.startsWith("_")&&pathParamNames.has(key.substring(1)))url=url.replace(`:${key.substring(1)}`,String(value));else if(key==="id"&&pathParamNames.has("id"))url=url.replace(":id",String(value))}}if(endpoint.method==="GET"&&payload&&typeof payload==="object"){let queryPayload={...payload};for(let paramName of pathParamNames)delete queryPayload[paramName],delete queryPayload[`_${paramName}`];url=appendQueryParams(url,queryPayload)}else if(payload!==void 0){if(endpoint.isFormData&&payload instanceof FormData)body=payload;else if(Array.isArray(payload)){if(body=payload.map((item)=>item&&typeof item==="object"?convertKeysToCamelCase(item):item),!headers["content-type"])headers["content-type"]="application/json"}else if(body=endpoint.skipCamelCase?payload:convertKeysToCamelCase(payload),!headers["content-type"])headers["content-type"]="application/json"}let response=await serverFetch2.fetch({url,method:endpoint.method,headers,body}),setCookiesToProcess=response.rawSetCookies.length>0?response.rawSetCookies:response.headers["set-cookie"]?splitSetCookieHeader(response.headers["set-cookie"]):[];if(setCookiesToProcess.length>0)try{for(let cookie of setCookiesToProcess){let[nameValue,...options]=cookie.split(";");if(!nameValue)continue;let eqIdx=nameValue.indexOf("=");if(eqIdx===-1)continue;let name=nameValue.substring(0,eqIdx).trim(),value=nameValue.substring(eqIdx+1).trim();if(name&&value){let cookieOptions={};for(let opt of options){let trimmed=opt.trim(),optEqIdx=trimmed.indexOf("="),optName=optEqIdx===-1?trimmed:trimmed.substring(0,optEqIdx),optValue=optEqIdx===-1?void 0:trimmed.substring(optEqIdx+1);if(!optName)continue;let optNameLower=optName.toLowerCase();if(optNameLower==="path")cookieOptions.path=optValue;else if(optNameLower==="domain")cookieOptions.domain=optValue;else if(optNameLower==="max-age")cookieOptions.maxAge=Number(optValue);else if(optNameLower==="expires"&&optValue)cookieOptions.expires=new Date(optValue);else if(optNameLower==="httponly")cookieOptions.httpOnly=!0;else if(optNameLower==="secure")cookieOptions.secure=!0;else if(optNameLower==="samesite")cookieOptions.sameSite=optValue}cookieStore.set(name,value,cookieOptions)}}}catch(cookieError){console.warn("[ServerFactory] Failed to process Set-Cookie headers:",cookieError instanceof Error?cookieError.message:String(cookieError))}let normalizedResponse=response.response;if(response.isSuccess&&normalizedResponse&&typeof normalizedResponse==="object"&&!Array.isArray(normalizedResponse)){let raw=normalizedResponse;if("success"in raw&&!("data"in raw)){let{success,message,error,...rest}=raw;normalizedResponse={success,...message!==void 0?{message}:{},...error!==void 0?{error}:{},...Object.keys(rest).length>0?{data:rest}:{}}}}return{isSuccess:response.isSuccess,data:normalizedResponse,errors:response.errors,code:response.code,message:response.isSuccess?void 0:response.errors?.message}}}var SYSTEM_TABLES=[{table_name:"users",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"email",type:"varchar",length:255},{name:"password",type:"varchar",length:255},{name:"verified_at",type:"timestamp"},{name:"email_verification_token",type:"varchar",length:255},{name:"email_verification_token_expires_at",type:"timestamp"},{name:"email_verification_sent_at",type:"timestamp"},{name:"email_verification_attempts",type:"integer",default:0},{name:"last_login_at",type:"timestamp"},{name:"login_count",type:"integer",default:0},{name:"is_locked",type:"boolean",default:!1},{name:"locked_until",type:"timestamp"},{name:"failed_login_attempts",type:"integer",default:0},{name:"is_god",type:"boolean",default:!1},{name:"cohort_id",type:"uuid",references:{table:"user_cohorts",column:"id",onDelete:"set null"}},{name:"email_verified",type:"boolean",default:!1}],indexes:[{columns:["email"],unique:!0},{columns:["email","is_active"]},{columns:["last_login_at"]},{columns:["is_locked","locked_until"]}]},{table_name:"profiles",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id"}},{name:"first_name",type:"varchar",length:100,notNull:!0},{name:"last_name",type:"varchar",length:100,notNull:!0}],indexes:[{columns:["user_id"],unique:!0},{columns:["first_name","last_name"]}]},{table_name:"roles",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"name",type:"varchar",length:100,notNull:!0},{name:"description",type:"varchar",length:500}],indexes:[{columns:["name"],unique:!0}]},{table_name:"claims",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"action",type:"varchar",length:100,notNull:!0},{name:"description",type:"varchar",length:500},{name:"path",type:"varchar",length:200,notNull:!0},{name:"method",type:"varchar",length:10,notNull:!0},{name:"policy",type:"jsonb"}],indexes:[{columns:["action"],unique:!0},{columns:["path","method"]}]},{table_name:"user_roles",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"role_id",type:"uuid",notNull:!0,references:{table:"roles",column:"id",onDelete:"cascade"}}],indexes:[{columns:["user_id"]},{columns:["role_id"]}],constraints:{unique:[{name:"unique_user_role",columns:["user_id","role_id"]}]}},{table_name:"role_claims",feature_set:["authentication","authorization"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"role_id",type:"uuid",notNull:!0,references:{table:"roles",column:"id",onDelete:"cascade"}},{name:"claim_id",type:"uuid",notNull:!0,references:{table:"claims",column:"id",onDelete:"cascade"}},{name:"scope",type:"text"}],indexes:[{columns:["role_id"]},{columns:["claim_id"]},{columns:["role_id","claim_id","scope"]}]},{table_name:"files",feature_set:["storage"],add_base_columns:!0,is_form_data:!0,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"name",type:"varchar",length:255,notNull:!0},{name:"original_name",type:"varchar",length:255,notNull:!0},{name:"type",type:"varchar",length:50,enumValues:["image","document","video","audio","profile_picture"]},{name:"path",type:"varchar",length:500,notNull:!0},{name:"size",type:"bigint",mode:"number",notNull:!0},{name:"mime_type",type:"varchar",length:100,notNull:!0},{name:"extension",type:"varchar",length:10,notNull:!0},{name:"uploaded_by",type:"uuid",references:{table:"users",column:"id"}}],indexes:[{columns:["type"]},{columns:["uploaded_by"]},{columns:["size"]}]},{table_name:"addresses",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"owner_type",type:"varchar",length:50,notNull:!0,enumValues:["user","company","contact"]},{name:"owner_id",type:"uuid",notNull:!0},{name:"name",type:"varchar",length:100,notNull:!0},{name:"street",type:"varchar",length:255},{name:"city",type:"varchar",length:100},{name:"state",type:"varchar",length:50},{name:"zip",type:"varchar",length:20},{name:"country",type:"varchar",length:50,default:"US"},{name:"latitude",type:"decimal",precision:10,scale:8},{name:"longitude",type:"decimal",precision:11,scale:8},{name:"neighborhood",type:"varchar",length:100},{name:"apartment",type:"varchar",length:50},{name:"province",type:"varchar",length:100},{name:"district",type:"varchar",length:100},{name:"type",type:"varchar",length:50}],indexes:[{columns:["city","state"]},{columns:["latitude","longitude"]},{columns:["type"]},{columns:["owner_type","owner_id"]}]},{table_name:"phones",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!0,columns:[{name:"owner_type",type:"varchar",length:50,notNull:!0,enumValues:["user","company","contact"]},{name:"owner_id",type:"uuid",notNull:!0},{name:"name",type:"varchar",length:100,notNull:!0},{name:"type",type:"varchar",length:50,enumValues:["mobile","office","fax"]},{name:"number",type:"varchar",length:20,notNull:!0},{name:"country_code",type:"varchar",length:10,notNull:!0,default:"+1"},{name:"extension",type:"varchar",length:10}],indexes:[{columns:["number"]},{columns:["type"]},{columns:["owner_type","owner_id"]}]},{table_name:"notifications",feature_set:["notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",notNull:!0},{name:"title",type:"varchar",length:255,notNull:!0},{name:"body",type:"varchar",length:1000},{name:"entity_name",type:"varchar",length:100},{name:"entity_id",type:"uuid"},{name:"type",type:"varchar",length:50,notNull:!0,default:"system",enumValues:["verification","system","custom"]},{name:"source",type:"varchar",length:100},{name:"is_seen",type:"boolean",notNull:!0,default:!1},{name:"seen_at",type:"timestamptz"}],indexes:[{columns:["user_id","created_at"]},{columns:["is_seen"]},{columns:["type"]},{columns:["user_id","type","is_seen"]}]},{table_name:"tenants",feature_set:["multi-tenant"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:[],columns:[{name:"subdomain",type:"varchar",length:100,notNull:!0,unique:!0},{name:"schema_name",type:"varchar",length:100,notNull:!0,unique:!0},{name:"company_id",type:"uuid",notNull:!0},{name:"company_name",type:"varchar",length:255},{name:"god_admin_email",type:"varchar",length:255,notNull:!0},{name:"status",type:"varchar",length:20,notNull:!0,default:"provisioning"},{name:"plan",type:"varchar",length:50,default:"free"},{name:"domain",type:"varchar",length:255},{name:"settings",type:"jsonb",default:"{}"},{name:"trusted_sources",type:"jsonb",default:"[]"},{name:"max_users",type:"integer"},{name:"provisioned_at",type:"timestamptz"},{name:"suspended_at",type:"timestamptz"},{name:"suspended_reason",type:"text"}],indexes:[{columns:["status"]}]},{table_name:"tenant_events",feature_set:["multi-tenant"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],columns:[{name:"tenant_id",type:"uuid",notNull:!0,references:{table:"tenants",column:"id",onDelete:"cascade"}},{name:"event_type",type:"varchar",length:50,notNull:!0},{name:"event_data",type:"jsonb",default:"{}"},{name:"performed_by",type:"varchar",length:255},{name:"ip_address",type:"varchar",length:45}],indexes:[{columns:["tenant_id"]},{columns:["event_type"]}]},{table_name:"tenant_features",feature_set:["multi-tenant"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:[],columns:[{name:"tenant_id",type:"uuid",notNull:!0,references:{table:"tenants",column:"id",onDelete:"cascade"}},{name:"feature_name",type:"varchar",length:100,notNull:!0},{name:"enabled",type:"boolean",notNull:!0,default:!0},{name:"config",type:"jsonb",default:"{}"}],indexes:[{columns:["tenant_id","feature_name"],unique:!0},{columns:["feature_name"]}]},{table_name:"domain_hostnames",feature_set:["domains"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:["PUT"],group_name:"Domains",columns:[{name:"owner_type",type:"varchar",length:20,notNull:!0,default:"tenant",comment:"tenant | organization | user | external"},{name:"owner_id",type:"uuid",notNull:!0,comment:"Product-defined owner reference (e.g. band id, org id)"},{name:"tenant_id",type:"uuid",references:{table:"tenants",column:"id",onDelete:"cascade"},comment:"Tenant this hostname routes to; null for non-tenant owners"},{name:"schema_name",type:"varchar",length:100,comment:"Resolved tenant schema for routing"},{name:"hostname",type:"varchar",length:255,notNull:!0,comment:"Original hostname as entered by the user"},{name:"normalized_hostname",type:"varchar",length:255,notNull:!0,unique:!0,comment:"Lowercased, punycode, port-stripped hostname used for matching"},{name:"hostname_kind",type:"varchar",length:20,notNull:!0,default:"apex",comment:"platform_subdomain | apex | www | subdomain"},{name:"status",type:"varchar",length:20,notNull:!0,default:"pending_verification",comment:"draft | pending_verification | verifying | active | failed | disabled | archived"},{name:"routing_status",type:"varchar",length:20,notNull:!0,default:"inactive",comment:"inactive | pending | active | failed"},{name:"certificate_status",type:"varchar",length:20,notNull:!0,default:"pending",comment:"not_required | pending | active | failed"},{name:"verification_status",type:"varchar",length:20,notNull:!0,default:"pending",comment:"pending | verified | failed | expired"},{name:"provider",type:"varchar",length:30,notNull:!0,default:"manual_dns",comment:"manual_dns | cloudflare_for_saas | cloudflare_registrar"},{name:"provider_hostname_id",type:"varchar",length:255},{name:"dns_target",type:"varchar",length:255,comment:"CNAME / A target the customer must point at"},{name:"is_primary",type:"boolean",notNull:!0,default:!1},{name:"redirect_to_hostname_id",type:"uuid",comment:"When set, this hostname 301-redirects to another hostname (e.g. apex to www)"},{name:"activated_at",type:"timestamptz"},{name:"disabled_at",type:"timestamptz"},{name:"failure_reason",type:"text"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["tenant_id"]},{columns:["schema_name"]},{columns:["status"]},{columns:["owner_type","owner_id"]},{columns:["provider","provider_hostname_id"]}]},{table_name:"domain_registrations",feature_set:["domains"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:["PUT"],group_name:"Domains",columns:[{name:"owner_type",type:"varchar",length:20,notNull:!0,default:"tenant"},{name:"owner_id",type:"uuid",notNull:!0},{name:"tenant_id",type:"uuid",references:{table:"tenants",column:"id",onDelete:"set null"}},{name:"requested_domain",type:"varchar",length:255,notNull:!0},{name:"registered_domain",type:"varchar",length:255},{name:"provider",type:"varchar",length:30,notNull:!0,default:"cloudflare_registrar"},{name:"provider_registration_id",type:"varchar",length:255},{name:"registrant_owner_type",type:"varchar",length:20,notNull:!0,default:"customer",comment:"customer | platform"},{name:"registrant_contact_snapshot",type:"jsonb",default:"{}"},{name:"status",type:"varchar",length:30,notNull:!0,default:"draft",comment:"draft | availability_checked | awaiting_payment | registering | active | failed | transfer_requested | transferred_out | cancelled | expired"},{name:"price_amount",type:"numeric",precision:12,scale:2},{name:"currency",type:"varchar",length:10},{name:"renewal_date",type:"timestamptz"},{name:"auto_renew",type:"boolean",notNull:!0,default:!0},{name:"terms_version",type:"varchar",length:50},{name:"terms_accepted_at",type:"timestamptz"},{name:"failure_reason",type:"text"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["owner_type","owner_id"]},{columns:["tenant_id"]},{columns:["status"]}]},{table_name:"domain_verification_challenges",feature_set:["domains"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],group_name:"Domains",columns:[{name:"domain_hostname_id",type:"uuid",notNull:!0,references:{table:"domainHostnames",column:"id",onDelete:"cascade"}},{name:"challenge_type",type:"varchar",length:30,notNull:!0,default:"ownership_validation",comment:"hostname_validation | certificate_validation | ownership_validation"},{name:"record_type",type:"varchar",length:10,notNull:!0,default:"TXT",comment:"TXT | CNAME | A | AAAA | HTTP"},{name:"record_name",type:"varchar",length:255,notNull:!0},{name:"record_value",type:"text",notNull:!0},{name:"expected_target",type:"varchar",length:255},{name:"status",type:"varchar",length:20,notNull:!0,default:"pending",comment:"pending | verified | failed | expired"},{name:"expires_at",type:"timestamptz"},{name:"verified_at",type:"timestamptz"},{name:"failure_reason",type:"text"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["domain_hostname_id"]},{columns:["status"]}]},{table_name:"domain_provider_records",feature_set:["domains"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],group_name:"Domains",columns:[{name:"domain_hostname_id",type:"uuid",notNull:!0,references:{table:"domainHostnames",column:"id",onDelete:"cascade"}},{name:"provider",type:"varchar",length:30,notNull:!0},{name:"provider_resource_type",type:"varchar",length:30,notNull:!0,comment:"custom_hostname | certificate | validation | zone | dns_record | registration"},{name:"provider_resource_id",type:"varchar",length:255},{name:"provider_status",type:"varchar",length:50},{name:"last_synced_at",type:"timestamptz"},{name:"raw_status",type:"jsonb",default:"{}"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["domain_hostname_id"]},{columns:["provider","provider_resource_id"]}]},{table_name:"domain_events",feature_set:["domains"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],group_name:"Domains",columns:[{name:"domain_hostname_id",type:"uuid",references:{table:"domainHostnames",column:"id",onDelete:"cascade"}},{name:"domain_registration_id",type:"uuid",references:{table:"domainRegistrations",column:"id",onDelete:"cascade"}},{name:"event_type",type:"varchar",length:50,notNull:!0},{name:"actor_type",type:"varchar",length:20},{name:"actor_id",type:"varchar",length:255},{name:"message",type:"text"},{name:"ip_address",type:"varchar",length:45},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["domain_hostname_id"]},{columns:["event_type"]}]},{table_name:"verifications",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"instance_id",type:"uuid",notNull:!0,references:{table:"verificationInstances",column:"id",onDelete:"cascade"}},{name:"requirement_id",type:"uuid",notNull:!0,references:{table:"verificationRequirements",column:"id"}},{name:"verifier_id",type:"uuid",notNull:!0,references:{table:"users",column:"id"}},{name:"signature_id",type:"uuid",references:{table:"files",column:"id"}},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"entity_id",type:"uuid",notNull:!0},{name:"step_order",type:"integer",notNull:!0,default:1},{name:"decision",type:"varchar",length:50,notNull:!0,default:"pending",enumValues:["approved","rejected","pending"]},{name:"reason",type:"text"},{name:"diff",type:"jsonb"}],indexes:[{columns:["instance_id"]},{columns:["requirement_id"]},{columns:["verifier_id"]},{columns:["entity_name","entity_id"]},{columns:["entity_name","entity_id","step_order"]},{columns:["decision"]}]},{table_name:"verificationRequirements",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"instance_id",type:"uuid",notNull:!0,references:{table:"verificationInstances",column:"id",onDelete:"cascade"}},{name:"step_node_id",type:"varchar",length:100,notNull:!0},{name:"verifier_node_id",type:"varchar",length:100,notNull:!0},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"entity_id",type:"uuid",notNull:!0},{name:"verifier_type",type:"varchar",length:30,notNull:!0,enumValues:["user","role"]},{name:"verifier_user_id",type:"uuid"},{name:"verifier_role",type:"varchar",length:100},{name:"require_signature",type:"boolean",notNull:!0,default:!1},{name:"all_must_approve",type:"boolean",notNull:!0,default:!1},{name:"step_order",type:"integer",notNull:!0,default:1},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","approved","rejected"]}],indexes:[{columns:["instance_id"]},{columns:["instance_id","step_order"]},{columns:["entity_name","entity_id"]},{columns:["verifier_user_id"]},{columns:["status"]}]},{table_name:"verificationFlows",feature_set:["authentication","verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"name",type:"varchar",length:255,notNull:!0},{name:"description",type:"text"},{name:"trigger_on",type:"varchar",length:50,notNull:!0,default:"update",enumValues:["create","update","delete","manual"]},{name:"trigger_fields",type:"jsonb"},{name:"is_draft",type:"boolean",notNull:!0,default:!0},{name:"published_at",type:"timestamptz"},{name:"viewport",type:"jsonb"}],indexes:[{columns:["entity_name"]},{columns:["entity_name","trigger_on"]},{columns:["is_draft"]}]},{table_name:"verificationSteps",feature_set:["authentication","verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"node_id",type:"varchar",length:100,notNull:!0},{name:"node_type",type:"varchar",length:50,notNull:!0,default:"step",enumValues:["step","verifier","notification"]},{name:"step_order",type:"integer",notNull:!0,default:1},{name:"name",type:"varchar",length:255},{name:"description",type:"text"},{name:"position_x",type:"numeric",notNull:!0,default:0},{name:"position_y",type:"numeric",notNull:!0,default:0},{name:"width",type:"numeric"},{name:"height",type:"numeric"},{name:"style",type:"jsonb"},{name:"data",type:"jsonb"}],indexes:[{columns:["flow_id"]},{columns:["entity_name"]},{columns:["flow_id","node_id"],unique:!0},{columns:["entity_name","step_order"]}]},{table_name:"verificationEdges",feature_set:["authentication","verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"edge_id",type:"varchar",length:100,notNull:!0},{name:"source_node_id",type:"varchar",length:100,notNull:!0},{name:"target_node_id",type:"varchar",length:100,notNull:!0},{name:"source_handle",type:"varchar",length:50},{name:"target_handle",type:"varchar",length:50},{name:"edge_type",type:"varchar",length:50,default:"default",enumValues:["default","conditional","success","failure"]},{name:"label",type:"varchar",length:255},{name:"condition",type:"jsonb"},{name:"style",type:"jsonb"},{name:"animated",type:"boolean",default:!1}],indexes:[{columns:["flow_id"]},{columns:["flow_id","edge_id"],unique:!0},{columns:["source_node_id"]},{columns:["target_node_id"]}]},{table_name:"verificationNotificationRules",feature_set:["verification","notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"node_id",type:"varchar",length:100,notNull:!0},{name:"trigger",type:"varchar",length:50,notNull:!0,enumValues:["on_flow_started","on_step_reached","on_approved","on_rejected","on_flow_completed"]},{name:"title_template",type:"varchar",length:255},{name:"body_template",type:"text"},{name:"starts_at",type:"timestamptz"},{name:"expires_at",type:"timestamptz"}],indexes:[{columns:["flow_id"]},{columns:["flow_id","node_id"],unique:!0},{columns:["trigger"]}]},{table_name:"verificationNotificationRecipients",feature_set:["verification","notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"rule_id",type:"uuid",notNull:!0,references:{table:"verificationNotificationRules",column:"id",onDelete:"cascade"}},{name:"recipient_type",type:"varchar",length:30,notNull:!0,enumValues:["user","role","all_verifiers","step_verifier","entity_creator"]},{name:"recipient_user_id",type:"uuid"},{name:"recipient_role",type:"varchar",length:100}],indexes:[{columns:["rule_id"]},{columns:["recipient_type"]}]},{table_name:"verificationVerifierConfigs",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id",onDelete:"cascade"}},{name:"node_id",type:"varchar",length:100,notNull:!0},{name:"verifier_type",type:"varchar",length:30,notNull:!0,enumValues:["user","role"]},{name:"verifier_user_id",type:"uuid"},{name:"verifier_role",type:"varchar",length:100},{name:"require_signature",type:"boolean",notNull:!0,default:!1},{name:"all_must_approve",type:"boolean",notNull:!0,default:!1}],indexes:[{columns:["flow_id"]},{columns:["flow_id","node_id"],unique:!0},{columns:["verifier_type"]}]},{table_name:"verificationInstances",feature_set:["verification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"flow_id",type:"uuid",notNull:!0,references:{table:"verificationFlows",column:"id"}},{name:"entity_name",type:"varchar",length:100,notNull:!0},{name:"entity_id",type:"uuid",notNull:!0},{name:"started_by",type:"uuid",references:{table:"users",column:"id"}},{name:"status",type:"varchar",length:30,notNull:!0,default:"active",enumValues:["active","completed","rejected","cancelled"]},{name:"current_step_order",type:"integer",notNull:!0,default:1},{name:"started_at",type:"timestamptz",notNull:!0,defaultRaw:"now()"},{name:"completed_at",type:"timestamptz"}],indexes:[{columns:["flow_id"]},{columns:["entity_name","entity_id"]},{columns:["entity_name","entity_id","status"]},{columns:["status"]},{columns:["started_by"]}]},{table_name:"verificationNotificationChannels",feature_set:["verification","notification"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"rule_id",type:"uuid",notNull:!0,references:{table:"verificationNotificationRules",column:"id",onDelete:"cascade"}},{name:"channel",type:"varchar",length:30,notNull:!0,enumValues:["portal","email","sms","telegram","webhook"]}],indexes:[{columns:["rule_id"]},{columns:["rule_id","channel"],unique:!0},{columns:["channel"]}]},{table_name:"user_cohorts",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"name",type:"varchar",length:255,notNull:!0},{name:"description",type:"text"},{name:"created_by",type:"uuid",references:{table:"users",column:"id",onDelete:"set null"}},{name:"expires_at",type:"timestamptz"},{name:"user_count",type:"integer",notNull:!0,default:0},{name:"metadata",type:"jsonb",default:"{}"}]},{table_name:"user_sessions",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,group_name:"Authentication",available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"token_hash",type:"varchar",length:255,notNull:!0},{name:"refresh_token_hash",type:"varchar",length:255},{name:"device_fingerprint",type:"varchar",length:255},{name:"device_name",type:"varchar",length:100},{name:"device_type",type:"varchar",length:50,enumValues:["desktop","mobile","tablet","unknown"]},{name:"browser_name",type:"varchar",length:50},{name:"browser_version",type:"varchar",length:20},{name:"os_name",type:"varchar",length:50},{name:"os_version",type:"varchar",length:20},{name:"ip_address",type:"varchar",length:45,notNull:!0},{name:"location_country",type:"varchar",length:100},{name:"location_city",type:"varchar",length:100},{name:"location_coordinates",type:"varchar",length:50},{name:"last_activity_at",type:"timestamptz",notNull:!0,defaultRaw:"now()"},{name:"expires_at",type:"timestamptz",notNull:!1},{name:"revoked_at",type:"timestamptz"},{name:"revoked_reason",type:"varchar",length:100,enumValues:["user_logout","user_revoked","admin_revoked","security_concern","password_changed","expired","replaced"]},{name:"is_current",type:"boolean",notNull:!0,default:!1},{name:"login_method",type:"varchar",length:50,enumValues:["password","oauth_google","oauth_github","oauth_microsoft","magic_link","sso","api_key"]},{name:"remember_me",type:"boolean",notNull:!0,default:!1},{name:"trust_score",type:"integer",default:100},{name:"approval_status",type:"varchar",length:20,default:"approved",enumValues:["approved","pending","rejected"]},{name:"approval_token",type:"varchar",length:64},{name:"approval_requested_at",type:"timestamptz"},{name:"approval_responded_at",type:"timestamptz"}],indexes:[{columns:["user_id"]},{columns:["token_hash"],unique:!0},{columns:["refresh_token_hash"]},{columns:["user_id","is_active"]},{columns:["expires_at"]},{columns:["device_fingerprint"]},{columns:["ip_address"]},{columns:["last_activity_at"]},{columns:["approval_status"]},{columns:["approval_token"]}]},{table_name:"trusted_devices",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,group_name:"Authentication",available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"token_hash",type:"varchar",length:64,notNull:!0},{name:"status",type:"varchar",length:20,notNull:!0,default:"pending",enumValues:["pending","trusted","revoked"]},{name:"origin_session_id",type:"uuid"},{name:"label",type:"varchar",length:120},{name:"device_fingerprint",type:"varchar",length:255},{name:"first_seen_ip",type:"varchar",length:45},{name:"last_seen_ip",type:"varchar",length:45},{name:"last_seen_at",type:"timestamptz"},{name:"expires_at",type:"timestamptz"},{name:"revoked_at",type:"timestamptz"},{name:"revoked_reason",type:"varchar",length:30,enumValues:["user_revoked","password_reset","logout","admin_revoked","expired","replaced"]}],indexes:[{columns:["token_hash"],unique:!0},{columns:["user_id"]},{columns:["user_id","status"]},{columns:["origin_session_id"]},{columns:["expires_at"]}]},{table_name:"password_reset_tokens",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,group_name:"Authentication",requires:["email"],available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"token_hash",type:"varchar",length:255,notNull:!0},{name:"expires_at",type:"timestamptz",notNull:!0},{name:"used_at",type:"timestamptz"}],indexes:[{columns:["token_hash"],unique:!0},{columns:["user_id"]},{columns:["expires_at"]}]},{table_name:"magic_link_tokens",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,group_name:"Authentication",requires:["email"],available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"email",type:"varchar",length:255,notNull:!0},{name:"token_hash",type:"varchar",length:255,notNull:!0},{name:"expires_at",type:"timestamptz",notNull:!0},{name:"used_at",type:"timestamptz"}],indexes:[{columns:["token_hash"],unique:!0},{columns:["user_id"]},{columns:["email"]},{columns:["expires_at"]}]},{table_name:"webauthn_credentials",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,group_name:"Authentication",requires:[],available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"credential_id",type:"text",notNull:!0},{name:"public_key",type:"text",notNull:!0},{name:"counter",type:"bigint",mode:"number",notNull:!0,defaultValue:0},{name:"transports",type:"jsonb"},{name:"device_type",type:"varchar",length:32},{name:"backed_up",type:"boolean",notNull:!0,defaultValue:!1},{name:"aaguid",type:"varchar",length:64},{name:"authenticator_attachment",type:"varchar",length:32},{name:"nickname",type:"varchar",length:128},{name:"last_used_at",type:"timestamptz"},{name:"revoked_at",type:"timestamptz"}],indexes:[{columns:["credential_id"],unique:!0},{columns:["user_id"]}]},{table_name:"webauthn_challenges",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,group_name:"Authentication",requires:[],available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE","GET"],columns:[{name:"user_id",type:"uuid",references:{table:"users",column:"id",onDelete:"cascade"}},{name:"challenge",type:"text",notNull:!0},{name:"challenge_type",type:"varchar",length:32,notNull:!0},{name:"expires_at",type:"timestamptz",notNull:!0},{name:"consumed_at",type:"timestamptz"}],indexes:[{columns:["challenge"],unique:!0},{columns:["user_id"]},{columns:["expires_at"]}]},{table_name:"audit_logs",feature_set:["audit"],add_base_columns:!1,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","DELETE","PATCH","TOGGLE","VERIFICATION"],columns:[{name:"id",type:"uuid",primaryKey:!0,defaultRaw:"gen_random_uuid()"},{name:"entity_id",type:"uuid"},{name:"entity_name",type:"text",notNull:!0},{name:"operation_type",type:"text",notNull:!0},{name:"user_id",type:"uuid"},{name:"ip_address",type:"text"},{name:"user_agent",type:"text"},{name:"summary",type:"text"},{name:"severity",type:"text",default:"info"},{name:"category",type:"text"},{name:"occurrence_count",type:"integer",default:1},{name:"last_occurrence_at",type:"timestamp"},{name:"old_values",type:"jsonb"},{name:"new_values",type:"jsonb"},{name:"created_at",type:"timestamp",notNull:!0,defaultRaw:"now()"},{name:"path",type:"text"},{name:"query",type:"text"}],indexes:[{columns:["entity_id"]},{columns:["entity_name"]},{columns:["user_id"]},{columns:["created_at"]},{columns:["severity"]},{columns:["category"]}]},{table_name:"monitoring_metrics",feature_set:["monitoring"],add_base_columns:!1,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","DELETE","PATCH","TOGGLE","VERIFICATION"],columns:[{name:"id",type:"uuid",primaryKey:!0,defaultRaw:"gen_random_uuid()"},{name:"metric_type",type:"text",notNull:!0},{name:"metric_name",type:"text",notNull:!0},{name:"value",type:"doublePrecision",notNull:!0},{name:"tags",type:"jsonb"},{name:"recorded_at",type:"timestamp",notNull:!0}],indexes:[{columns:["metric_type"]},{columns:["metric_name"]},{columns:["recorded_at"]}]},{table_name:"oauth_accounts",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!1,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"provider",type:"varchar",length:50,notNull:!0,enumValues:["google","github","microsoft","discord","facebook","twitter","apple","custom"]},{name:"provider_account_id",type:"varchar",length:255,notNull:!0},{name:"provider_email",type:"varchar",length:255},{name:"provider_name",type:"varchar",length:255},{name:"provider_avatar_url",type:"text"},{name:"access_token",type:"text"},{name:"refresh_token",type:"text"},{name:"token_expires_at",type:"timestamp"},{name:"scope",type:"text"},{name:"raw_profile",type:"jsonb"},{name:"is_primary",type:"boolean",notNull:!0,default:!1},{name:"last_used_at",type:"timestamp"}],indexes:[{columns:["user_id"]},{columns:["provider","provider_account_id"],unique:!0},{columns:["provider_email"]},{columns:["user_id","provider"]}],constraints:{unique:[{name:"unique_provider_account",columns:["provider","provider_account_id"]}]}},{table_name:"api_keys",feature_set:["authentication"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH"],bulk_endpoints_enabled:!1,columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"name",type:"varchar",length:255,notNull:!0},{name:"description",type:"text"},{name:"key_hash",type:"varchar",length:255,notNull:!0},{name:"key_preview",type:"varchar",length:20,notNull:!0},{name:"owner_type",type:"varchar",length:30,notNull:!0,default:"personal",enumValues:["personal","application"]},{name:"application_name",type:"varchar",length:255},{name:"allowed_roles",type:"jsonb",notNull:!0,default:"[]"},{name:"allowed_claims",type:"jsonb",notNull:!0,default:"[]"},{name:"allowed_scopes",type:"jsonb",notNull:!0,default:"[]"},{name:"expires_at",type:"timestamptz"},{name:"last_used_at",type:"timestamptz"},{name:"last_used_ip",type:"varchar",length:45},{name:"usage_count",type:"integer",notNull:!0,default:0},{name:"revoked_at",type:"timestamptz"},{name:"revoked_reason",type:"varchar",length:255}],indexes:[{columns:["key_hash"],unique:!0},{columns:["user_id"]},{columns:["user_id","is_active"]},{columns:["owner_type"]},{columns:["expires_at"]},{columns:["last_used_at"]}]},{table_name:"backup_logs",feature_set:["backup"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["main","all"],excluded_schemas:[],excluded_methods:["PUT","PATCH"],columns:[{name:"backup_name",type:"varchar",length:255,notNull:!0},{name:"file_name",type:"varchar",length:500,notNull:!0},{name:"schema_name",type:"varchar",length:100,notNull:!0},{name:"format",type:"varchar",length:20,notNull:!0,default:"json"},{name:"status",type:"varchar",length:20,notNull:!0,default:"pending"},{name:"trigger",type:"varchar",length:20,notNull:!0,default:"manual"},{name:"size_bytes",type:"integer"},{name:"table_count",type:"integer"},{name:"row_count",type:"integer"},{name:"included_tables",type:"jsonb",default:"[]"},{name:"excluded_tables",type:"jsonb",default:"[]"},{name:"error_message",type:"text"},{name:"started_at",type:"timestamp"},{name:"completed_at",type:"timestamp"},{name:"performed_by",type:"varchar",length:255},{name:"cron_expression",type:"varchar",length:100},{name:"retention_days",type:"integer"}],indexes:[{columns:["schema_name"]},{columns:["status"]},{columns:["trigger"]},{columns:["created_at"]}]},{table_name:"payment_transactions",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"user_id",type:"uuid",references:{table:"users",column:"id"}},{name:"order_id",type:"varchar",length:255},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_transaction_id",type:"varchar",length:255},{name:"provider_payment_id",type:"varchar",length:255},{name:"payment_method",type:"varchar",length:50},{name:"amount",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"currency",type:"varchar",length:10,notNull:!0,default:"TRY"},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","processing","completed","failed","refunded","partially_refunded","cancelled"]},{name:"status_code",type:"integer"},{name:"status_message",type:"text"},{name:"card_last_four",type:"varchar",length:4},{name:"card_type",type:"varchar",length:50},{name:"card_association",type:"varchar",length:50},{name:"installment",type:"integer",default:1},{name:"is_three_d_secure",type:"boolean",default:!1},{name:"provider_response",type:"jsonb",default:"{}"},{name:"metadata",type:"jsonb",default:"{}"},{name:"refunded_amount",type:"numeric",precision:12,scale:2,default:0},{name:"refunded_at",type:"timestamptz"},{name:"completed_at",type:"timestamptz"},{name:"failed_at",type:"timestamptz"},{name:"ip_address",type:"varchar",length:45}],indexes:[{columns:["user_id"]},{columns:["order_id"]},{columns:["provider"]},{columns:["provider_payment_id"]},{columns:["status"]},{columns:["user_id","status"]}]},{table_name:"payment_methods",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"type",type:"varchar",length:30,notNull:!0,default:"card",enumValues:["card","bank_account","wallet"]},{name:"alias",type:"varchar",length:100},{name:"card_last_four",type:"varchar",length:4},{name:"card_type",type:"varchar",length:50},{name:"card_association",type:"varchar",length:50},{name:"card_family",type:"varchar",length:100},{name:"card_bank_name",type:"varchar",length:100},{name:"provider_card_user_key",type:"varchar",length:255},{name:"provider_card_token",type:"varchar",length:255},{name:"bin_number",type:"varchar",length:8},{name:"is_default",type:"boolean",default:!1},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["user_id"]},{columns:["provider"]},{columns:["user_id","is_default"]},{columns:["provider_card_user_key"]}]},{table_name:"payment_webhook_logs",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["PUT","PATCH","DELETE"],columns:[{name:"provider",type:"varchar",length:50,notNull:!0},{name:"event_type",type:"varchar",length:100,notNull:!0},{name:"provider_payment_id",type:"varchar",length:255},{name:"raw_payload",type:"jsonb",notNull:!0},{name:"processed",type:"boolean",default:!1},{name:"processing_result",type:"jsonb"},{name:"error_message",type:"text"},{name:"ip_address",type:"varchar",length:45},{name:"idempotency_key",type:"varchar",length:255}],indexes:[{columns:["provider"]},{columns:["event_type"]},{columns:["provider_payment_id"]},{columns:["processed"]},{columns:["idempotency_key"],unique:!0}]},{table_name:"payment_sub_merchants",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",references:{table:"users",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_sub_merchant_key",type:"varchar",length:255},{name:"external_id",type:"varchar",length:255},{name:"type",type:"varchar",length:50,notNull:!0,default:"personal",enumValues:["personal","private_company","limited_or_joint_stock_company"]},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","active","suspended","rejected"]},{name:"name",type:"varchar",length:255,notNull:!0},{name:"email",type:"varchar",length:255,notNull:!0},{name:"gsm_number",type:"varchar",length:20},{name:"address",type:"text"},{name:"iban",type:"varchar",length:50},{name:"contact_name",type:"varchar",length:100},{name:"contact_surname",type:"varchar",length:100},{name:"identity_number",type:"varchar",length:20},{name:"tax_office",type:"varchar",length:100},{name:"tax_number",type:"varchar",length:20},{name:"legal_company_title",type:"varchar",length:255},{name:"currency",type:"varchar",length:10,default:"TRY"},{name:"commission_rate",type:"numeric",precision:5,scale:2,default:0},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["user_id"]},{columns:["provider"]},{columns:["provider_sub_merchant_key"]},{columns:["external_id"]},{columns:["status"]},{columns:["email"]}]},{table_name:"payment_commission_splits",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"transaction_id",type:"uuid",notNull:!0,references:{table:"payment_transactions",column:"id",onDelete:"cascade"}},{name:"sub_merchant_id",type:"uuid",notNull:!0,references:{table:"payment_sub_merchants",column:"id"}},{name:"basket_item_id",type:"varchar",length:255},{name:"item_price",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"sub_merchant_price",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"platform_commission",type:"numeric",precision:12,scale:2,notNull:!0,default:0},{name:"commission_rate",type:"numeric",precision:5,scale:2,default:0},{name:"provider_split_id",type:"varchar",length:255},{name:"currency",type:"varchar",length:10,notNull:!0,default:"TRY"},{name:"status",type:"varchar",length:30,notNull:!0,default:"pending",enumValues:["pending","approved","disapproved","refunded"]},{name:"approved_at",type:"timestamptz"},{name:"disapproved_at",type:"timestamptz"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["transaction_id"]},{columns:["sub_merchant_id"]},{columns:["status"]},{columns:["transaction_id","sub_merchant_id"]},{columns:["provider_split_id"]}]},{table_name:"payment_products",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_product_id",type:"varchar",length:255},{name:"name",type:"varchar",length:255,notNull:!0},{name:"description",type:"text"},{name:"type",type:"varchar",length:30,default:"service",enumValues:["service","good"]},{name:"status",type:"varchar",length:30,notNull:!0,default:"active",enumValues:["active","archived","draft"]},{name:"images",type:"jsonb",default:"[]"},{name:"unit_label",type:"varchar",length:50},{name:"url",type:"varchar",length:500},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["provider"]},{columns:["provider_product_id"]},{columns:["name"]},{columns:["status"]},{columns:["type"]}]},{table_name:"payment_prices",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"product_id",type:"uuid",notNull:!0,references:{table:"payment_products",column:"id",onDelete:"cascade"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_price_id",type:"varchar",length:255},{name:"currency",type:"varchar",length:10,notNull:!0,default:"USD"},{name:"unit_amount",type:"integer",notNull:!0,default:0},{name:"unit_amount_decimal",type:"varchar",length:30},{name:"type",type:"varchar",length:30,notNull:!0,default:"one_time",enumValues:["one_time","recurring"]},{name:"billing_scheme",type:"varchar",length:30,default:"per_unit",enumValues:["per_unit","tiered"]},{name:"nickname",type:"varchar",length:255},{name:"recurring_interval",type:"varchar",length:20,enumValues:["day","week","month","year"]},{name:"recurring_interval_count",type:"integer",default:1},{name:"recurring_usage_type",type:"varchar",length:20,default:"licensed",enumValues:["licensed","metered"]},{name:"recurring_aggregate_usage",type:"varchar",length:30,enumValues:["sum","last_during_period","last_ever","max"]},{name:"transform_quantity_divide_by",type:"integer"},{name:"transform_quantity_round",type:"varchar",length:10,enumValues:["up","down"]},{name:"status",type:"varchar",length:30,notNull:!0,default:"active",enumValues:["active","archived"]},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["product_id"]},{columns:["provider"]},{columns:["provider_price_id"]},{columns:["type"]},{columns:["currency"]},{columns:["status"]},{columns:["product_id","status"]}]},{table_name:"payment_customers",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"user_id",type:"uuid",references:{table:"users",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_customer_id",type:"varchar",length:255,notNull:!0},{name:"email",type:"varchar",length:255,notNull:!0},{name:"name",type:"varchar",length:255},{name:"phone",type:"varchar",length:50},{name:"description",type:"text"},{name:"address",type:"jsonb",default:"{}"},{name:"tax_id_type",type:"varchar",length:50},{name:"tax_id_value",type:"varchar",length:100},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["user_id"]},{columns:["provider"]},{columns:["provider_customer_id"]},{columns:["email"]},{columns:["user_id","provider"],unique:!0}]},{table_name:"payment_subscriptions",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"customer_id",type:"uuid",notNull:!0,references:{table:"payment_customers",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_subscription_id",type:"varchar",length:255},{name:"status",type:"varchar",length:30,notNull:!0,default:"incomplete",enumValues:["active","past_due","unpaid","canceled","incomplete","incomplete_expired","trialing","paused"]},{name:"collection_method",type:"varchar",length:30,default:"charge_automatically",enumValues:["charge_automatically","send_invoice"]},{name:"current_period_start",type:"timestamptz"},{name:"current_period_end",type:"timestamptz"},{name:"cancel_at_period_end",type:"boolean",default:!1},{name:"canceled_at",type:"timestamptz"},{name:"trial_start",type:"timestamptz"},{name:"trial_end",type:"timestamptz"},{name:"items",type:"jsonb",default:"[]"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["customer_id"]},{columns:["provider"]},{columns:["provider_subscription_id"]},{columns:["status"]},{columns:["customer_id","status"]}]},{table_name:"payment_invoices",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["DELETE"],columns:[{name:"customer_id",type:"uuid",notNull:!0,references:{table:"payment_customers",column:"id"}},{name:"subscription_id",type:"uuid",references:{table:"payment_subscriptions",column:"id"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_invoice_id",type:"varchar",length:255},{name:"status",type:"varchar",length:30,notNull:!0,default:"draft",enumValues:["draft","open","paid","uncollectible","void"]},{name:"collection_method",type:"varchar",length:30,default:"charge_automatically",enumValues:["charge_automatically","send_invoice"]},{name:"currency",type:"varchar",length:10,notNull:!0,default:"USD"},{name:"amount_due",type:"integer",default:0},{name:"amount_paid",type:"integer",default:0},{name:"amount_remaining",type:"integer",default:0},{name:"description",type:"text"},{name:"hosted_invoice_url",type:"varchar",length:1000},{name:"invoice_pdf",type:"varchar",length:1000},{name:"due_date",type:"timestamptz"},{name:"days_until_due",type:"integer"},{name:"period_start",type:"timestamptz"},{name:"period_end",type:"timestamptz"},{name:"paid_at",type:"timestamptz"},{name:"voided_at",type:"timestamptz"},{name:"lines",type:"jsonb",default:"[]"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["customer_id"]},{columns:["subscription_id"]},{columns:["provider"]},{columns:["provider_invoice_id"]},{columns:["status"]},{columns:["customer_id","status"]}]},{table_name:"chat_conversations",feature_set:["authentication","chat"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"type",type:"varchar",length:20,notNull:!0,default:"direct",enumValues:["direct","group"]},{name:"title",type:"varchar",length:255},{name:"description",type:"text"},{name:"avatar_file_id",type:"uuid"},{name:"direct_key",type:"varchar",length:255},{name:"last_message_at",type:"timestamptz"},{name:"last_message_preview",type:"varchar",length:500},{name:"last_message_sender_id",type:"uuid",references:{table:"users",column:"id",onDelete:"set null"}}],indexes:[{columns:["direct_key"],unique:!0},{columns:["type"]},{columns:["last_message_at"]}]},{table_name:"chat_participants",feature_set:["authentication","chat"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"conversation_id",type:"uuid",notNull:!0,references:{table:"chat_conversations",column:"id",onDelete:"cascade"}},{name:"user_id",type:"uuid",notNull:!0,references:{table:"users",column:"id",onDelete:"cascade"}},{name:"role",type:"varchar",length:20,notNull:!0,default:"member",enumValues:["member","admin","owner"]},{name:"last_read_message_id",type:"uuid"},{name:"last_read_at",type:"timestamptz"},{name:"unread_count",type:"integer",notNull:!0,default:0},{name:"muted",type:"boolean",notNull:!0,default:!1},{name:"muted_until",type:"timestamptz"},{name:"notifications_enabled",type:"boolean",notNull:!0,default:!0},{name:"left_at",type:"timestamptz"}],indexes:[{columns:["user_id"]},{columns:["conversation_id"]}],constraints:{unique:[{name:"unique_conversation_participant",columns:["conversation_id","user_id"]}]}},{table_name:"chat_messages",feature_set:["authentication","chat"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"conversation_id",type:"uuid",notNull:!0,references:{table:"chat_conversations",column:"id",onDelete:"cascade"}},{name:"sender_id",type:"uuid",references:{table:"users",column:"id",onDelete:"set null"}},{name:"content",type:"text"},{name:"content_type",type:"varchar",length:20,notNull:!0,default:"text",enumValues:["text","image","file","video","audio","system"]},{name:"reply_to_id",type:"uuid",references:{table:"chat_messages",column:"id",onDelete:"set null"}},{name:"metadata",type:"jsonb",default:"{}"},{name:"client_message_id",type:"varchar",length:100},{name:"edited_at",type:"timestamptz"},{name:"deleted_at",type:"timestamptz"}],indexes:[{columns:["conversation_id","created_at"]},{columns:["sender_id"]},{columns:["reply_to_id"]}]},{table_name:"chat_message_attachments",feature_set:["authentication","chat","storage"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],columns:[{name:"message_id",type:"uuid",notNull:!0,references:{table:"chat_messages",column:"id",onDelete:"cascade"}},{name:"conversation_id",type:"uuid",notNull:!0,references:{table:"chat_conversations",column:"id",onDelete:"cascade"}},{name:"file_id",type:"uuid",notNull:!0,references:{table:"files",column:"id",onDelete:"cascade"}},{name:"kind",type:"varchar",length:20,notNull:!0,default:"file",enumValues:["image","video","audio","file"]},{name:"original_name",type:"varchar",length:255},{name:"mime_type",type:"varchar",length:100},{name:"size",type:"bigint",mode:"number"},{name:"width",type:"integer"},{name:"height",type:"integer"},{name:"duration",type:"integer"}],indexes:[{columns:["message_id"]},{columns:["conversation_id"]},{columns:["file_id"]}]},{table_name:"payment_splits",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],group_name:"Payments Marketplace",columns:[{name:"transaction_id",type:"uuid",references:{table:"paymentTransactions",column:"id",onDelete:"set null"}},{name:"recipient_owner_type",type:"varchar",length:20,notNull:!0,default:"seller",comment:"seller | platform | tenant | user"},{name:"recipient_owner_id",type:"uuid",notNull:!0},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"gross_amount",type:"bigint",mode:"number",notNull:!0,comment:"Minor units"},{name:"provider_fee_amount",type:"bigint",mode:"number",notNull:!0,default:0},{name:"platform_fee_amount",type:"bigint",mode:"number",notNull:!0,default:0},{name:"reserve_amount",type:"bigint",mode:"number",notNull:!0,default:0},{name:"net_payable_amount",type:"bigint",mode:"number",notNull:!0},{name:"currency",type:"varchar",length:10,notNull:!0},{name:"available_for_payout_at",type:"timestamptz"},{name:"status",type:"varchar",length:20,notNull:!0,default:"pending",comment:"pending | available | payout_requested | paid | held | refunded | disputed | cancelled"},{name:"source_type",type:"varchar",length:50},{name:"source_id",type:"varchar",length:255},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["recipient_owner_type","recipient_owner_id"]},{columns:["status"]},{columns:["transaction_id"]}]},{table_name:"payment_ledger_entries",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],group_name:"Payments Marketplace",columns:[{name:"account",type:"varchar",length:40,notNull:!0,comment:"platform_revenue | provider_fee | seller_payable | reserve | refund_liability | dispute_liability | payout_in_transit | payout_completed"},{name:"owner_type",type:"varchar",length:20},{name:"owner_id",type:"uuid"},{name:"direction",type:"varchar",length:6,notNull:!0,comment:"debit | credit"},{name:"amount",type:"bigint",mode:"number",notNull:!0,comment:"Minor units"},{name:"currency",type:"varchar",length:10,notNull:!0},{name:"entry_type",type:"varchar",length:40,notNull:!0,comment:"split | refund | payout | reserve_hold | reserve_release | dispute | adjustment"},{name:"reference_type",type:"varchar",length:50},{name:"reference_id",type:"varchar",length:255},{name:"split_id",type:"uuid",references:{table:"paymentSplits",column:"id",onDelete:"set null"}},{name:"description",type:"text"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["account"]},{columns:["owner_type","owner_id"]},{columns:["entry_type"]},{columns:["reference_type","reference_id"]}]},{table_name:"payment_settlement_policies",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],group_name:"Payments Marketplace",columns:[{name:"owner_type",type:"varchar",length:20,notNull:!0,default:"tenant",comment:"tenant | seller"},{name:"owner_id",type:"uuid",notNull:!0},{name:"default_delay_days",type:"integer",notNull:!0,default:7},{name:"new_seller_delay_days",type:"integer",notNull:!0,default:14},{name:"reserve_rate",type:"numeric",precision:5,scale:4,notNull:!0,default:0,comment:"Fraction 0..1 held as reserve"},{name:"reserve_days",type:"integer",notNull:!0,default:0},{name:"minimum_payout_amount",type:"bigint",mode:"number",notNull:!0,default:0},{name:"currency",type:"varchar",length:10},{name:"early_payout_enabled",type:"boolean",notNull:!0,default:!1},{name:"status",type:"varchar",length:20,notNull:!0,default:"active"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["owner_type","owner_id"],unique:!0}]},{table_name:"payment_reserves",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],group_name:"Payments Marketplace",columns:[{name:"owner_type",type:"varchar",length:20,notNull:!0,default:"seller"},{name:"owner_id",type:"uuid",notNull:!0},{name:"split_id",type:"uuid",references:{table:"paymentSplits",column:"id",onDelete:"set null"}},{name:"amount",type:"bigint",mode:"number",notNull:!0},{name:"currency",type:"varchar",length:10,notNull:!0},{name:"reason",type:"varchar",length:30,notNull:!0,default:"refund_window",comment:"refund_window | chargeback_risk | new_seller | manual_hold | dispute | compliance_review"},{name:"status",type:"varchar",length:20,notNull:!0,default:"held",comment:"held | released | consumed | cancelled"},{name:"release_at",type:"timestamptz"},{name:"released_at",type:"timestamptz"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["owner_type","owner_id"]},{columns:["status"]},{columns:["release_at"]}]},{table_name:"payment_payout_requests",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["PUT"],group_name:"Payments Marketplace",columns:[{name:"recipient_owner_type",type:"varchar",length:20,notNull:!0,default:"seller"},{name:"recipient_owner_id",type:"uuid",notNull:!0},{name:"amount",type:"bigint",mode:"number",notNull:!0},{name:"currency",type:"varchar",length:10,notNull:!0},{name:"status",type:"varchar",length:20,notNull:!0,default:"pending",comment:"pending | approved | rejected | processing | completed | failed | cancelled"},{name:"provider",type:"varchar",length:50},{name:"provider_payout_id",type:"varchar",length:255},{name:"provider_transfer_id",type:"varchar",length:255},{name:"destination",type:"varchar",length:255},{name:"requested_by",type:"uuid"},{name:"decided_by",type:"uuid"},{name:"decided_at",type:"timestamptz"},{name:"completed_at",type:"timestamptz"},{name:"failure_reason",type:"text"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["recipient_owner_type","recipient_owner_id"]},{columns:["status"]}]},{table_name:"payment_disputes",feature_set:["payment"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["PUT"],group_name:"Payments Marketplace",columns:[{name:"transaction_id",type:"uuid",references:{table:"paymentTransactions",column:"id",onDelete:"set null"}},{name:"provider",type:"varchar",length:50,notNull:!0},{name:"provider_dispute_id",type:"varchar",length:255},{name:"owner_type",type:"varchar",length:20},{name:"owner_id",type:"uuid"},{name:"amount",type:"bigint",mode:"number"},{name:"currency",type:"varchar",length:10},{name:"reason",type:"varchar",length:100},{name:"status",type:"varchar",length:30,notNull:!0,default:"open",comment:"open | under_review | won | lost | accepted | cancelled"},{name:"evidence_due_at",type:"timestamptz"},{name:"resolved_at",type:"timestamptz"},{name:"metadata",type:"jsonb",default:"{}"}],indexes:[{columns:["provider","provider_dispute_id"]},{columns:["status"]},{columns:["owner_type","owner_id"]},{columns:["transaction_id"]}]},{table_name:"nucleus_secrets",feature_set:["secrets"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["GET","POST","PUT","PATCH","DELETE","TOGGLE"],bulk_endpoints_enabled:!1,group_name:"Secrets",columns:[{name:"scope",type:"varchar",length:200,notNull:!0,comment:"Config dot-path that owns the credential, e.g. authentication.oauth.providers.microsoft"},{name:"key",type:"varchar",length:120,notNull:!0,comment:"Leaf key under that path, e.g. clientSecret"},{name:"value_enc",type:"text",notNull:!0,comment:"AES-256-GCM envelope v1:iv:tag:ciphertext \u2014 never returned by any route"},{name:"previous_enc",type:"text",comment:"Value replaced by the last rotation, retained for one-step rollback"},{name:"preview",type:"varchar",length:80},{name:"kind",type:"varchar",length:30,notNull:!0,default:"text",enumValues:["text","password","json","connection_string","pem"]},{name:"description",type:"varchar",length:500},{name:"version",type:"integer",notNull:!0,default:1},{name:"rotated_at",type:"timestamptz"},{name:"last_used_at",type:"timestamptz"}],indexes:[{columns:["scope","key"],unique:!0},{columns:["scope"]}]},{table_name:"integration_sources",feature_set:["integrations"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!1,group_name:"Integrations",columns:[{name:"name",type:"varchar",length:150,notNull:!0},{name:"slug",type:"varchar",length:150,notNull:!0,comment:"Stable machine name; referenced by exports and by operators in logs"},{name:"base_url",type:"varchar",length:500,notNull:!0,comment:"Any scheme, host and port \u2014 https, plain http, in-cluster DNS, IP. HTTPS is NOT required and must never be enforced: reaching a service inside the same cluster over http is a legitimate deployment."},{name:"description",type:"text"},{name:"enabled",type:"boolean",default:!0},{name:"auth_type",type:"varchar",length:20,notNull:!0,default:"none",enumValues:["none","bearer","api_key","basic","oauth2"]},{name:"auth_token_encrypted",type:"text",sensitive:!0,comment:"Static credential (bearer / api key / basic blob), encrypted at rest"},{name:"auth_token_hint",type:"varchar",length:24},{name:"auth_header_name",type:"varchar",length:80,default:"Authorization"},{name:"auth_query_param",type:"varchar",length:80,comment:"When set, an api_key credential travels as this query parameter instead of a header"},{name:"extra_headers",type:"jsonb",default:{}},{name:"token_url",type:"varchar",length:500},{name:"oauth_grant_type",type:"varchar",length:40,default:"password",enumValues:["password","client_credentials"]},{name:"oauth_client_id",type:"varchar",length:200},{name:"oauth_client_secret_encrypted",type:"text",sensitive:!0},{name:"oauth_client_secret_hint",type:"varchar",length:24},{name:"oauth_username",type:"varchar",length:200},{name:"oauth_password_encrypted",type:"text",sensitive:!0},{name:"oauth_password_hint",type:"varchar",length:24},{name:"oauth_scope",type:"varchar",length:300},{name:"oauth_client_auth",type:"varchar",length:20,default:"basic",enumValues:["basic","body"]},{name:"tls_verify",type:"boolean",notNull:!0,default:!0,comment:"Per-source certificate verification. Turning it off applies to THIS source's connections only \u2014 never to the process, which is what a NODE_TLS_REJECT_UNAUTHORIZED toggle would do."},{name:"timeout_ms",type:"integer",notNull:!0,default:30000},{name:"spec_url",type:"varchar",length:500,comment:"Optional API description document (OpenAPI/Swagger/Postman/Bruno). Discovery is a convenience: every endpoint can always be defined by hand instead."},{name:"spec_format",type:"varchar",length:20,default:"manual",enumValues:["manual","openapi","swagger","postman","bruno","har"]}],constraints:{unique:[{name:"uniq_integration_source_slug",columns:["slug"]}]},indexes:[{columns:["enabled"]}]},{table_name:"integration_endpoints",feature_set:["integrations"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!1,group_name:"Integrations",columns:[{name:"source_id",type:"uuid",notNull:!0,references:{table:"integrationSources",column:"id",onDelete:"cascade"}},{name:"tag",type:"varchar",length:120,notNull:!0},{name:"name",type:"varchar",length:200},{name:"method",type:"varchar",length:10,notNull:!0,default:"GET",enumValues:["GET","POST","PUT","PATCH","DELETE"]},{name:"path",type:"varchar",length:500,notNull:!0,comment:"Appended to the source base URL. May carry {brace} or :colon path tokens, whose values come from param_bindings."},{name:"description",type:"text"},{name:"query_params",type:"jsonb",default:{}},{name:"request_body",type:"jsonb",default:{}},{name:"param_bindings",type:"jsonb",default:[],comment:"Where each path/query parameter comes from: a static value, another endpoint's records (fan-out), or a column of one of our own tables."},{name:"pagination",type:"jsonb",default:{},comment:"Explicitly chosen paging profile (none/page_number/offset/cursor/link_header). Never guessed \u2014 a wrong guess silently imports one page."},{name:"response_root_path",type:"varchar",length:200},{name:"tree_children_path",type:"varchar",length:200,comment:"Field holding a record's children when the source answers with a shape rather than a list \u2014 each node then becomes its own row and knows its parent"},{name:"sample_response",type:"jsonb",default:{},comment:"A few real records captured by a live test, so the mapping screen still shows fields when the source is unreachable"},{name:"enabled",type:"boolean",default:!0}],indexes:[{columns:["source_id"]},{columns:["source_id","tag"]}]},{table_name:"integration_mappings",feature_set:["integrations"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:[],bulk_endpoints_enabled:!1,group_name:"Integrations",columns:[{name:"endpoint_id",type:"uuid",notNull:!0,references:{table:"integrationEndpoints",column:"id",onDelete:"cascade"}},{name:"name",type:"varchar",length:200,notNull:!0},{name:"target_entity",type:"varchar",length:120,notNull:!0,comment:"snake_case table name this mapping writes into"},{name:"field_mappings",type:"jsonb",notNull:!0,default:[]},{name:"reference_checks",type:"jsonb",notNull:!0,default:[],comment:"Columns whose value must already exist in another entity, and what to do when it does not."},{name:"dedup_source_field",type:"varchar",length:200},{name:"dedup_target_field",type:"varchar",length:200,comment:"Target column that identifies the same record across runs. Without it nothing can be matched and every run appends."},{name:"write_mode",type:"varchar",length:20,notNull:!0,default:"upsert",enumValues:["upsert","append","replace"],comment:"replace is the destructive wipe-and-rewrite; it is no longer the default and is gated by the completeness check."},{name:"missing_record_policy",type:"varchar",length:20,notNull:!0,default:"ignore",enumValues:["ignore","deactivate","delete"],comment:"What happens to a row that exists here but no longer in the source. deactivate is the right answer for most HR data and could not be expressed before."},{name:"missing_record_column",type:"varchar",length:120},{name:"missing_record_value",type:"varchar",length:200},{name:"removal_scope_column",type:"varchar",length:120,comment:"Target column carrying whatever the fan-out varies \u2014 a company code, a branch, a tenant. Set it when one mapping reads its source through several calls: removal is then confined to the values actually read, so a call that answers HTTP 500 costs that slice its cleanup instead of costing the whole run. Without it a single failing call refuses every removal, and a source whose one bad endpoint fails every night is never cleaned at all."},{name:"origin_column",type:"varchar",length:120,comment:"Column this mapping stamps on rows it owns. Set it when the target table ALSO holds rows people create by hand: without it every hand-made row looks like one the source stopped carrying, and the first run with a removal policy deletes them all."},{name:"origin_value",type:"varchar",length:120,comment:"The value written into origin_column. Rows carrying it are the only removal candidates."},{name:"max_removal_share",type:"numeric",comment:"Share of the target table (0-1) above which an UNATTENDED run refuses to remove. A scheduled run passes through neither the preview nor a confirmation, so this is the only thing between a wrong plan and the table. 0 or null disables."},{name:"password_target_column",type:"varchar",length:100,comment:"Column that receives the shared opening password given at run time. The password itself is never stored."},{name:"account_rule",type:"jsonb",comment:"Creates a login alongside each imported record, in the same transaction, and links it. The password belongs to the run, never to this row."},{name:"schedule_cron",type:"varchar",length:120},{name:"schedule_timezone",type:"varchar",length:64,comment:"IANA zone the cron expression is read in. Without it a nightly job drifts with the container's clock."},{name:"schedule_enabled",type:"boolean",notNull:!0,default:!1},{name:"last_run_at",type:"timestamptz"},{name:"enabled",type:"boolean",default:!0}],indexes:[{columns:["endpoint_id"]},{columns:["target_entity"]},{columns:["schedule_enabled"]}]},{table_name:"integration_runs",feature_set:["integrations"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],bulk_endpoints_enabled:!1,group_name:"Integrations",columns:[{name:"mapping_id",type:"uuid",references:{table:"integrationMappings",column:"id",onDelete:"set null"},comment:"Nullable and NOT cascaded: deleting a mapping must not erase the record that it once rewrote a table."},{name:"target_entity",type:"varchar",length:120},{name:"write_mode",type:"varchar",length:20,enumValues:["upsert","append","replace"]},{name:"status",type:"varchar",length:20,notNull:!0,default:"queued",enumValues:["queued","running","succeeded","failed","cancelled","reverted"],comment:"There is deliberately no 'partial': a run either applied in full or not at all."},{name:"trigger",type:"varchar",length:20,notNull:!0,default:"manual",enumValues:["manual","schedule","api"]},{name:"total_fetched",type:"integer",notNull:!0,default:0},{name:"source_reported_total",type:"integer",comment:"What the source said it had. When this and total_fetched disagree, a destructive run refuses to start."},{name:"created_count",type:"integer",notNull:!0,default:0},{name:"references_created_count",type:"integer",notNull:!0,default:0,comment:"Rows this run added to OTHER tables so its records could point at them."},{name:"accounts_created_count",type:"integer",notNull:!0,default:0,comment:"Logins this run created so its records could be signed in to."},{name:"updated_count",type:"integer",notNull:!0,default:0},{name:"skipped_count",type:"integer",notNull:!0,default:0},{name:"deleted_count",type:"integer",notNull:!0,default:0},{name:"deactivated_count",type:"integer",notNull:!0,default:0},{name:"error_count",type:"integer",notNull:!0,default:0},{name:"external_call_count",type:"integer",notNull:!0,default:0},{name:"issues",type:"jsonb",default:[]},{name:"errors",type:"jsonb",default:[]},{name:"cancel_requested",type:"boolean",notNull:!0,default:!1,comment:"Set by the cancel endpoint; the engine checks it at every batch boundary. A dropped HTTP connection is NOT a cancellation."},{name:"started_at",type:"timestamptz"},{name:"finished_at",type:"timestamptz"},{name:"pre_images_expire_at",type:"timestamptz",comment:"After this, the run can no longer be reverted and the UI says so rather than offering a button that quietly does nothing."},{name:"reverted_at",type:"timestamptz"},{name:"reverted_by",type:"uuid",references:{table:"users",column:"id"}},{name:"reverted_run_id",type:"uuid"}],indexes:[{columns:["mapping_id"]},{columns:["status"]},{columns:["target_entity"]},{columns:["created_at"]}]},{table_name:"integration_run_items",feature_set:["integrations"],add_base_columns:!0,is_form_data:!1,available_app_ids:["default_be"],available_schemas:["*"],excluded_schemas:[],excluded_methods:["POST","PUT","PATCH","DELETE"],bulk_endpoints_enabled:!1,group_name:"Integrations",columns:[{name:"run_id",type:"uuid",notNull:!0,references:{table:"integrationRuns",column:"id",onDelete:"cascade"}},{name:"target_entity",type:"varchar",length:120,notNull:!0},{name:"row_id",type:"uuid"},{name:"action",type:"varchar",length:20,notNull:!0,enumValues:["create","update","delete","deactivate"]},{name:"before",type:"jsonb",comment:"The row as it stood before this run touched it. This is what makes a successful run reversible; the bulk delete path already produced these rows and threw them away."},{name:"after",type:"jsonb"}],indexes:[{columns:["run_id"]},{columns:["run_id","action"]},{columns:["target_entity","row_id"]}]}];import{batch as batch2,createStore as createStore2}from"h-state";var initialState={connection:{status:"disconnected",clientId:null,subscribedTopics:[],error:null,reconnectAttempt:0},events:[],maxEvents:100},{useStore:usePubSubStore}=createStore2(initialState,{setConnectionStatus:(store)=>(status)=>{store.connection.status=status},setClientId:(store)=>(clientId)=>{store.connection.clientId=clientId},setSubscribedTopics:(store)=>(topics)=>{store.connection.subscribedTopics=topics},setError:(store)=>(error)=>{store.connection.error=error},setReconnectAttempt:(store)=>(attempt)=>{store.connection.reconnectAttempt=attempt},addEvent:(store)=>(event)=>{let updated=[event,...store.events];store.events=updated.slice(0,store.maxEvents)},clearEvents:(store)=>()=>{store.events=[]},reset:(store)=>()=>{batch2(()=>{store.connection.status="disconnected",store.connection.clientId=null,store.connection.subscribedTopics=[],store.connection.error=null,store.connection.reconnectAttempt=0,store.events=[]})}});import{useEffect}from"react";function buildWsUrl(config){let path=config.wsPath||"/api/events/subscribe",topics=(config.topics||["*"]).join(","),query=`?userId=${encodeURIComponent(config.userId)}&topics=${encodeURIComponent(topics)}`;if(config.wsUrl)return`${config.wsUrl.replace(/\/$/,"")}${path}${query}`;if(typeof window>"u")return"";return`${window.location.protocol==="https:"?"wss:":"ws:"}//${window.location.host}${path}${query}`}var connections=new Map,eventIdCounter=0;function log(conn,...args){if(conn.options.debug)console.log("[usePubSub]",...args)}function clearTimers(conn){if(conn.heartbeat)clearInterval(conn.heartbeat),conn.heartbeat=null;if(conn.reconnectTimeout)clearTimeout(conn.reconnectTimeout),conn.reconnectTimeout=null}function detachSocket(conn){let ws=conn.ws;if(!ws)return;if(ws.onopen=null,ws.onmessage=null,ws.onerror=null,ws.onclose=null,ws.readyState===WebSocket.OPEN||ws.readyState===WebSocket.CONNECTING)ws.close();conn.ws=null}function startHeartbeat(conn){if(conn.heartbeat)clearInterval(conn.heartbeat);conn.heartbeat=setInterval(()=>{if(conn.ws?.readyState===WebSocket.OPEN)conn.ws.send(JSON.stringify({type:"ping"}))},conn.options.heartbeatInterval)}var HANDSHAKE_FAILURE_LIMIT=3;function scheduleReconnect(conn){if(!conn.options.autoReconnect)return;if(connections.get(conn.url)!==conn)return;if(conn.reconnectAttempt>=conn.options.maxReconnectAttempts){conn.dispatch.setConnectionStatus("disconnected"),conn.dispatch.setError(Error("Max reconnection attempts reached")),log(conn,"Max reconnect attempts reached");return}let delay=Math.min(conn.options.reconnectBaseDelay*2**conn.reconnectAttempt,conn.options.reconnectMaxDelay);if(conn.reconnectAttempt+=1,conn.dispatch.setConnectionStatus("reconnecting"),conn.dispatch.setReconnectAttempt(conn.reconnectAttempt),log(conn,`Reconnecting in ${delay}ms (attempt ${conn.reconnectAttempt})`),conn.reconnectTimeout)clearTimeout(conn.reconnectTimeout);conn.reconnectTimeout=setTimeout(()=>{if(connections.get(conn.url)===conn)openSocket(conn)},delay)}function handleMessage(conn,raw){let message;try{message=JSON.parse(raw)}catch{log(conn,"Failed to parse message");return}switch(message.type){case"connected":conn.reconnectAttempt=0,conn.dispatch.setConnectionStatus("connected"),conn.dispatch.setClientId(message.clientId),conn.dispatch.setSubscribedTopics(message.subscribedTopics),conn.dispatch.setReconnectAttempt(0),conn.dispatch.setError(null),log(conn,"Connected, clientId:",message.clientId);break;case"subscribed":conn.dispatch.setSubscribedTopics(message.topics),log(conn,"Subscribed to:",message.topics);break;case"event":{if(conn.dispatch.addEvent({id:`evt_${Date.now()}_${eventIdCounter++}`,topic:message.topic,data:message.data,timestamp:message.timestamp,receivedAt:Date.now(),messageId:message.messageId,isRedelivery:message.isRedelivery}),message.messageId&&conn.ws?.readyState===WebSocket.OPEN)conn.ws.send(JSON.stringify({type:"ack",messageId:message.messageId}));break}case"pong":break;case"error":conn.dispatch.setError(Error(message.error)),log(conn,"Server error:",message.error);break}}function openSocket(conn){if(conn.ws?.readyState===WebSocket.OPEN||conn.ws?.readyState===WebSocket.CONNECTING)return;detachSocket(conn),conn.dispatch.setConnectionStatus("connecting"),conn.dispatch.setError(null),log(conn,"Connecting to:",conn.url);let ws=new WebSocket(conn.url);conn.ws=ws;let opened=!1;ws.onopen=()=>{log(conn,"WebSocket opened"),opened=!0,conn.handshakeFailures=0,conn.reconnectAttempt=0,startHeartbeat(conn)},ws.onmessage=(event)=>handleMessage(conn,event.data),ws.onerror=()=>{log(conn,"WebSocket error"),conn.dispatch.setError(Error("WebSocket connection error"))},ws.onclose=(event)=>{if(log(conn,"WebSocket closed",event.code,event.reason),conn.heartbeat)clearInterval(conn.heartbeat),conn.heartbeat=null;if(conn.dispatch.setConnectionStatus("disconnected"),conn.dispatch.setClientId(null),connections.get(conn.url)!==conn)return;if(event.code===4001){conn.dispatch.setConnectionStatus("unauthorized"),conn.dispatch.setError(Error("WebSocket rejected: session is not valid"));return}if(!opened){if(conn.handshakeFailures+=1,conn.handshakeFailures>=HANDSHAKE_FAILURE_LIMIT){conn.dispatch.setConnectionStatus("unauthorized"),conn.dispatch.setError(Error("WebSocket handshake refused \u2014 the session needs refreshing")),log(conn,"Handshake refused repeatedly; not retrying");return}}else conn.handshakeFailures=0;scheduleReconnect(conn)}}function acquire(url,dispatch,options){let conn=connections.get(url);if(!conn)conn={url,ws:null,refCount:0,reconnectAttempt:0,handshakeFailures:0,heartbeat:null,reconnectTimeout:null,dispatch,options},connections.set(url,conn);else conn.dispatch=dispatch,conn.options=options;conn.refCount+=1,openSocket(conn)}function release(url){let conn=connections.get(url);if(!conn)return;if(conn.refCount-=1,conn.refCount>0)return;connections.delete(url),clearTimers(conn),detachSocket(conn),conn.dispatch.setConnectionStatus("disconnected"),conn.dispatch.setClientId(null)}function send(url,payload){let ws=connections.get(url)?.ws;if(ws?.readyState===WebSocket.OPEN)ws.send(JSON.stringify(payload))}function usePubSub(config){let store=usePubSubStore(),url=config.userId?buildWsUrl(config):"";return useEffect(()=>{if(!url)return;let dispatch={setConnectionStatus:store.setConnectionStatus,setClientId:store.setClientId,setSubscribedTopics:store.setSubscribedTopics,setError:store.setError,setReconnectAttempt:store.setReconnectAttempt,addEvent:store.addEvent},options={autoReconnect:config.autoReconnect??!0,maxReconnectAttempts:config.maxReconnectAttempts??10,reconnectBaseDelay:config.reconnectBaseDelay??1000,reconnectMaxDelay:config.reconnectMaxDelay??30000,heartbeatInterval:config.heartbeatInterval??30000,debug:config.debug??!1};return acquire(url,dispatch,options),()=>release(url)},[url]),{isConnected:store.connection.status==="connected",isConnecting:store.connection.status==="connecting"||store.connection.status==="reconnecting",sessionExpired:store.connection.status==="unauthorized",clientId:store.connection.clientId,subscribedTopics:store.connection.subscribedTopics,events:store.events,error:store.connection.error,reconnectAttempt:store.connection.reconnectAttempt,connect:()=>{let conn=connections.get(url);if(conn)openSocket(conn)},disconnect:()=>release(url),subscribe:(topics)=>send(url,{type:"subscribe",topics}),unsubscribe:(topics)=>send(url,{type:"unsubscribe",topics}),clearEvents:store.clearEvents,getEventsByTopic:(topic)=>store.events.filter((e)=>e.topic===topic)}}import{createHash as createHash4,randomUUID as randomUUID9}from"crypto";var import_fast_decode_uri_component=__toESM(require_fast_decode_uri_component(),1);import{Elysia,NotFoundError}from"elysia";var fs,path,isBun=typeof Bun<"u"&&!!Bun.file;function getBuiltinModule(){if(fs||(fs=process.getBuiltinModule("fs/promises")),path||(path=process.getBuiltinModule("path")),!path){console.warn("@elysiajs/static require path to be available.");return}return[fs,path]}async function listHTMLFiles(dir){if(fs||getBuiltinModule(),isBun){let glob=new Bun.Glob("**/*.html"),files=[];for await(let file of glob.scan(dir))files.push(path.join(dir,file));return files}return[]}async function listFiles(dir){if(fs||getBuiltinModule(),isBun){let glob=new Bun.Glob("**/*"),files2=[];for await(let file of glob.scan(dir))files2.push(path.join(dir,file));return files2}let files=await fs.readdir(dir).catch(()=>[]);return(await Promise.all(files.map(async(name)=>{let file=dir+path.sep+name,stats=await fs.stat(file).catch(()=>null);return stats?stats.isDirectory()?await listFiles(file):[path.resolve(dir,file)]:[]}))).flat()}function fileExists(path2){return fs||getBuiltinModule(),fs.stat(path2).then(()=>!0,()=>!1)}class LRUCache{constructor(max=250,ttl=10800){this.max=max,this.ttl=ttl,this.map=new Map}get(key){let entry=this.map.get(key);if(entry)return entry[1]<=Date.now()?void this.delete(key):(this.map.delete(key),this.map.set(key,entry),entry[0])}set(key,value){if(this.interval||(this.interval=setInterval(()=>{let now=Date.now();for(let[key2,entry]of this.map)entry[1]<=now&&this.map.delete(key2)},this.ttl)),this.map.has(key))this.map.delete(key);else if(this.map.size>=this.max){let oldestKey=this.map.keys().next().value;oldestKey!==void 0&&this.delete(oldestKey)}this.map.set(key,[value,Date.now()+this.ttl*1000])}delete(key){this.map.get(key)&&this.map.delete(key)}clear(){this.map.clear()}size(){return this.map.size}[Symbol.dispose](){this.interval&&clearInterval(this.interval)}}function isCached(headers,etag,filePath){if(headers["cache-control"]&&/no-cache|no-store/.test(headers["cache-control"]))return!1;if("if-none-match"in headers){let ifNoneMatch=headers["if-none-match"];return ifNoneMatch==="*"?!0:ifNoneMatch===null||typeof etag!="string"?!1:ifNoneMatch===etag}if(headers["if-modified-since"]){let ifModifiedSince=headers["if-modified-since"];try{return fs.stat(filePath).then((stat)=>{if(stat.mtime!==void 0&&stat.mtime.getTime()<=Date.parse(ifModifiedSince))return!0})}catch{}}return!1}var Crypto;function getFile(path2){return isBun?Bun.file(path2):(fs||getBuiltinModule(),fs.readFile(path2))}async function generateETag(file){return isBun?new Bun.CryptoHasher("md5").update(await file.arrayBuffer()).digest("base64"):(Crypto||(Crypto=process.getBuiltinModule("crypto")),Crypto?Crypto.createHash("md5").update(file).digest("base64"):void console.warn("[@elysiajs/static] crypto is required to generate etag."))}var isNotEmpty=(obj)=>{if(!obj)return!1;for(let _ in obj)return!0;return!1};async function staticPlugin({assets="public",prefix="/public",staticLimit=1024,alwaysStatic=!1,ignorePatterns=[".DS_Store",".git",".env"],headers:initialHeaders,maxAge=86400,directive="public",etag:useETag=!0,extension=!0,indexHTML=!0,decodeURI,silent}={}){if(typeof process>"u"||typeof process.getBuiltinModule>"u")return silent||console.warn("[@elysiajs/static] require process.getBuiltinModule. Static plugin is disabled"),new Elysia;let builtinModule=getBuiltinModule();if(!builtinModule)return new Elysia;let[fs2,path2]=builtinModule,normalizePath=path2.sep!=="/"?(p)=>p.replace(/\\/g,"/"):(p)=>p,fileCache=new LRUCache;prefix===path2.sep&&(prefix="");let assetsDir=path2.resolve(assets),shouldIgnore=ignorePatterns.length?(file)=>ignorePatterns.find((pattern)=>typeof pattern=="string"?pattern.includes(file):pattern.test(file)):()=>!1,app=new Elysia({name:"static",seed:prefix});if(alwaysStatic){let files=await listFiles(path2.resolve(assets));if(files.length<=staticLimit)for(let absolutePath of files){let handleCache2=function({headers:requestHeaders}){if(etag){let cached=isCached(requestHeaders,etag,absolutePath);if(cached===!0)return new Response(null,{status:304,headers:isNotEmpty(initialHeaders)?initialHeaders:void 0});if(cached!==!1){let cache2=fileCache.get(pathName);return cache2?cache2.clone():cached.then((cached2)=>{if(cached2)return new Response(null,{status:304,headers:initialHeaders||void 0});let response2=new Response(file,{headers:Object.assign({"Cache-Control":maxAge?`${directive}, max-age=${maxAge}`:directive},initialHeaders,etag?{Etag:etag}:{})});return fileCache.set(prefix,response2),response2.clone()})}}let cache=fileCache.get(pathName);if(cache)return cache.clone();let response=new Response(file,{headers:Object.assign({"Cache-Control":maxAge?`${directive}, max-age=${maxAge}`:directive},initialHeaders,etag?{Etag:etag}:{})});return fileCache.set(pathName,response),response.clone()};var handleCache=handleCache2;if(!absolutePath||shouldIgnore(absolutePath))continue;let relativePath=absolutePath.replace(assetsDir,"");decodeURI&&(relativePath=import_fast_decode_uri_component.default(relativePath)??relativePath);let pathName=normalizePath(path2.join(prefix,relativePath));if(isBun&&absolutePath.endsWith(".html")){let htmlBundle=await import(absolutePath);app.get(pathName,htmlBundle.default),indexHTML&&pathName.endsWith("/index.html")&&app.get(pathName.replace("/index.html",""),htmlBundle.default);continue}extension||(pathName=normalizePath(pathName.slice(0,pathName.lastIndexOf("."))));let file=isBun?getFile(absolutePath):await getFile(absolutePath);if(!file)return silent||console.warn(`[@elysiajs/static] Failed to load file: ${absolutePath}`),new Elysia;let etag=await generateETag(file);app.get(pathName,useETag?handleCache2:new Response(file,isNotEmpty(initialHeaders)?{headers:initialHeaders}:void 0)),indexHTML&&pathName.endsWith("/index.html")&&app.get(pathName.replace("/index.html",""),useETag?handleCache2:new Response(file,isNotEmpty(initialHeaders)?{headers:initialHeaders}:void 0))}return app}if(!(`GET_${prefix}/*`in app.routeTree)){if(isBun){let htmls=await listHTMLFiles(path2.resolve(assets));for(let absolutePath of htmls){if(!absolutePath||shouldIgnore(absolutePath))continue;let relativePath=absolutePath.replace(assetsDir,""),pathName=normalizePath(path2.join(prefix,relativePath)),htmlBundle=await import(absolutePath);app.get(pathName,htmlBundle.default),indexHTML&&pathName.endsWith("/index.html")&&app.get(pathName.replace("/index.html",""),htmlBundle.default)}}app.onError(()=>{}).get(`${prefix.endsWith("/")?prefix.slice(0,-1):prefix}/*`,async({params,headers:requestHeaders})=>{let pathName=normalizePath(path2.join(assets,decodeURI?import_fast_decode_uri_component.default(params["*"])??params["*"]:params["*"]));if(shouldIgnore(pathName))throw new NotFoundError;let cache=fileCache.get(pathName);if(cache)return cache.clone();try{let fileStat=await fs2.stat(pathName).catch(()=>null);if(!fileStat)throw new NotFoundError;if(!indexHTML&&fileStat.isDirectory())throw new NotFoundError;let file;if(!isBun&&indexHTML){let htmlPath=path2.join(pathName,"index.html"),cache2=fileCache.get(htmlPath);if(cache2)return cache2.clone();await fileExists(htmlPath)&&(file=await getFile(htmlPath))}if(!file&&!fileStat.isDirectory()&&await fileExists(pathName))file=await getFile(pathName);else throw new NotFoundError;if(!useETag)return new Response(file,isNotEmpty(initialHeaders)?{headers:initialHeaders}:void 0);let etag=await generateETag(file);if(etag&&await isCached(requestHeaders,etag,pathName))return new Response(null,{status:304});let response=new Response(file,{headers:Object.assign({"Cache-Control":maxAge?`${directive}, max-age=${maxAge}`:directive},initialHeaders,etag?{Etag:etag}:{})});return fileCache.set(pathName,response),response.clone()}catch(error){throw error instanceof NotFoundError?error:(silent||console.error("[@elysiajs/static]",error),new NotFoundError)}})}return app}import{pushSchema}from"drizzle-kit/api";import{and as and23,desc as desc7,eq as eq63,lt as lt3,ne as ne3,sql as sql13}from"drizzle-orm";import{drizzle as drizzle2}from"drizzle-orm/node-postgres";import{pgSchema as pgSchema2}from"drizzle-orm/pg-core";import Elysia52 from"elysia";import{join as join3}from"path";class LiveStorageProvider{resolve;constructor(resolve){this.resolve=resolve}get kind(){return this.resolve().kind}get describe(){return this.resolve().describe}isAvailable(){return this.resolve().isAvailable()}exists(relativePath){return this.resolve().exists(relativePath)}stat(relativePath){return this.resolve().stat(relativePath)}read(relativePath){return this.resolve().read(relativePath)}write(relativePath,data){return this.resolve().write(relativePath,data)}delete(relativePath){return this.resolve().delete(relativePath)}ensureDir(relativeDir){return this.resolve().ensureDir(relativeDir)}list(relativeDir){return this.resolve().list(relativeDir)}localPath(relativePath){return this.resolve().localPath(relativePath)}close(){return this.resolve().close()}}import{mkdir,readdir,stat,unlink}from"fs/promises";import{dirname,join}from"path";function normalizeRelativePath(relativePath){let cleaned=relativePath.replace(/\\/g,"/").replace(/^\/+/,""),segments=[];for(let segment of cleaned.split("/")){if(!segment||segment===".")continue;if(segment==="..")throw Error(`Path traversal rejected: ${relativePath}`);segments.push(segment)}return segments.join("/")}class LocalStorageProvider{kind="local";describe;basePath;constructor(basePath,_deps){this.basePath=basePath,this.describe=`local:${basePath}`}resolve(relativePath){return join(this.basePath,normalizeRelativePath(relativePath))}async isAvailable(){try{return await mkdir(this.basePath,{recursive:!0}),!0}catch{return!1}}async exists(relativePath){return Bun.file(this.resolve(relativePath)).exists()}async stat(relativePath){try{let info=await stat(this.resolve(relativePath));return{size:info.size,modifiedAt:info.mtime,isDirectory:info.isDirectory()}}catch{return null}}async read(relativePath){let file=Bun.file(this.resolve(relativePath));if(!await file.exists())return null;return Buffer.from(await file.arrayBuffer())}async write(relativePath,data){let full=this.resolve(relativePath);await mkdir(dirname(full),{recursive:!0}),await Bun.write(full,data)}async delete(relativePath){try{return await unlink(this.resolve(relativePath)),!0}catch{return!1}}async ensureDir(relativeDir){await mkdir(this.resolve(relativeDir),{recursive:!0})}async list(relativeDir){try{return await readdir(this.resolve(relativeDir))}catch{return[]}}async localPath(relativePath){let full=this.resolve(relativePath);return await Bun.file(full).exists()?full:null}async close(){}}import{stat as fsStat,mkdir as mkdir2,rename,unlink as unlink2}from"fs/promises";import{dirname as dirname2,join as join2}from"path";var DEFAULT_TIMEOUT_MS=15000,DEFAULT_CACHE_TTL_SECONDS=300;class SmbStorageProvider{kind="smb";describe;getConfig;logger;client=null;clientFingerprint="";cacheDir;cacheTtlMs;cacheEnabled;inFlight=new Map;constructor(getConfig,deps,defaultCacheDir){this.getConfig=getConfig,this.logger=deps.logger;let config=getConfig();this.cacheEnabled=config.cache?.enabled!==!1,this.cacheDir=config.cache?.path||defaultCacheDir,this.cacheTtlMs=(config.cache?.ttlSeconds??DEFAULT_CACHE_TTL_SECONDS)*1000,this.describe=`smb://${config.host}/${config.share}${config.basePath?`/${config.basePath}`:""}`}async getClient(){let{host,share,domain,username,password,port,timeoutMs}=this.getConfig(),fingerprint=`${host}|${share}|${domain}|${username}|${password}|${port}`;if(this.client&&fingerprint===this.clientFingerprint)return this.client;if(this.client){try{this.client.disconnect()}catch{}this.client=null}let imported=await Promise.resolve().then(() => __toESM(require_smb2(),1)).catch(()=>{throw Error('storage.provider is "smb" but the optional @marsaud/smb2 dependency is not installed \u2014 run: bun add @marsaud/smb2')}),SMB2=imported.default??imported;return this.client=new SMB2({share:`\\\\${host}\\${share}`,domain:domain||"WORKGROUP",username,password,port:port??445,autoCloseTimeout:timeoutMs??DEFAULT_TIMEOUT_MS}),this.clientFingerprint=fingerprint,this.client}async call(fn){let client=await this.getClient(),timeoutMs=this.getConfig().timeoutMs??DEFAULT_TIMEOUT_MS;return new Promise((resolve,reject)=>{let settled=!1,timer=setTimeout(()=>{if(settled)return;settled=!0,reject(Error(`SMB operation timed out after ${timeoutMs}ms (${this.describe})`))},timeoutMs);fn(client,(err,value)=>{if(settled)return;if(settled=!0,clearTimeout(timer),err)reject(err);else resolve(value)})})}remotePath(relativePath){let normalized=normalizeRelativePath(relativePath),configuredBase=this.getConfig().basePath,base=configuredBase?normalizeRelativePath(configuredBase):"";return(base?`${base}/${normalized}`:normalized).replace(/\//g,"\\")}cachePath(relativePath){return join2(this.cacheDir,normalizeRelativePath(relativePath))}async isAvailable(){try{return await this.call((client,cb)=>client.readdir(this.getConfig().basePath?this.remotePath(""):"",cb)),!0}catch(error){return this.logger.warn("[Storage/SMB] Share is not reachable",{target:this.describe,error:error instanceof Error?error.message:String(error)}),!1}}async exists(relativePath){try{return await this.call((client,cb)=>client.exists(this.remotePath(relativePath),cb))}catch{return!1}}async stat(relativePath){try{let info=await this.call((client,cb)=>client.stat(this.remotePath(relativePath),cb));return{size:Number(info.size),modifiedAt:new Date(info.mtime),isDirectory:typeof info.isDirectory==="function"?info.isDirectory():await this.looksLikeDirectory(relativePath)}}catch{return null}}async read(relativePath){try{return await this.call((client,cb)=>client.readFile(this.remotePath(relativePath),cb))}catch(error){return this.logger.warn("[Storage/SMB] Read failed",{path:relativePath,error:error instanceof Error?error.message:String(error)}),null}}async write(relativePath,data){let parent=normalizeRelativePath(relativePath).split("/").slice(0,-1).join("/");if(parent)await this.ensureDir(parent);let payload=typeof data==="string"?Buffer.from(data,"utf-8"):Buffer.from(data);if(await this.call((client,cb)=>client.writeFile(this.remotePath(relativePath),payload,cb)),this.cacheEnabled){let target=this.cachePath(relativePath);await mkdir2(dirname2(target),{recursive:!0}).catch(()=>{}),await Bun.write(target,payload).catch(()=>{})}}async delete(relativePath){try{if(await this.call((client,cb)=>client.unlink(this.remotePath(relativePath),cb)),this.cacheEnabled)await unlink2(this.cachePath(relativePath)).catch(()=>{});return!0}catch{return!1}}async ensureDir(relativeDir){let normalized=normalizeRelativePath(relativeDir);if(!normalized)return;let segments=normalized.split("/");for(let i=1;i<=segments.length;i++){let partial=segments.slice(0,i).join("/");try{await this.call((client,cb)=>client.mkdir(this.remotePath(partial),cb))}catch{}}}async looksLikeDirectory(relativePath){try{return await this.call((client,cb)=>client.readdir(this.remotePath(relativePath),cb)),!0}catch{return!1}}async list(relativeDir){try{return await this.call((client,cb)=>client.readdir(this.remotePath(relativeDir),cb))}catch{return[]}}async localPath(relativePath){if(!this.cacheEnabled)return null;let target=this.cachePath(relativePath),cached=await fsStat(target).catch(()=>null);if(cached&&Date.now()-cached.mtimeMs<this.cacheTtlMs)return target;let pending=this.inFlight.get(target);if(pending)return pending;let download=(async()=>{let data=await this.read(relativePath);if(!data)return null;await mkdir2(dirname2(target),{recursive:!0}).catch(()=>{});let tmp=`${target}.${process.pid}.tmp`;try{return await Bun.write(tmp,data),await rename(tmp,target),target}catch(error){return await unlink2(tmp).catch(()=>{}),this.logger.warn("[Storage/SMB] Could not cache file locally",{path:relativePath,error:error instanceof Error?error.message:String(error)}),null}})().finally(()=>{this.inFlight.delete(target)});return this.inFlight.set(target,download),download}async close(){try{this.client?.disconnect()}catch{}this.client=null}}var DEFAULT_EXCLUDES=[".cache",".tmp","lost+found"];async function migrateStorage(options,deps){let{from,to,onProgress}=options,exclude=new Set([...DEFAULT_EXCLUDES,...options.exclude??[]]),maxFiles=options.maxFiles??50000,report={copied:0,skipped:0,failed:0,bytes:0,failures:[],truncated:!1},walk=async(dir)=>{if(report.truncated)return;let entries=await from.list(dir);for(let entry of entries){if(report.truncated)return;if(!entry||entry==="."||entry==="..")continue;let relative=dir?`${dir}/${entry}`:entry;if(exclude.has(entry))continue;let info=await from.stat(relative);if(!info){if(report.failed+=1,report.failures.length<50)report.failures.push(relative);continue}if(info.isDirectory){await walk(relative);continue}if(report.copied+report.skipped>=maxFiles){report.truncated=!0;return}if(await to.exists(relative)){report.skipped+=1;continue}try{let bytes=await from.read(relative);if(!bytes){if(report.failed+=1,report.failures.length<50)report.failures.push(relative);continue}let parent=relative.includes("/")?relative.slice(0,relative.lastIndexOf("/")):"";if(parent)await to.ensureDir(parent);await to.write(relative,bytes),report.copied+=1,report.bytes+=bytes.length,onProgress?.(report.copied,relative)}catch(error){if(report.failed+=1,report.failures.length<50)report.failures.push(relative);deps.logger.warn("[Storage] Migration copy failed",{path:relative,error:error instanceof Error?error.message:String(error)})}}};return await walk(""),deps.logger.info("[Storage] Migration finished",{from:from.describe,to:to.describe,copied:report.copied,skipped:report.skipped,failed:report.failed,truncated:report.truncated}),report}function parseSmbUrl(value){let raw=(value??"").trim();if(!raw)return{host:"",share:""};let withoutScheme=raw.replace(/^smb:\/\//i,"").replace(/^\\\\/,"").replace(/\\/g,"/"),[host="",share="",...rest]=withoutScheme.split("/").filter(Boolean);return{host,share,basePath:rest.length>0?rest.join("/"):void 0}}function createStorageProvider(options,deps){let{basePath,smb,resolveCredential}=options,setting=(key,configValue)=>resolveCredential?.("storage.smb",key,configValue)??configValue,resolveSmbConfig=()=>{let fromUrl=parseSmbUrl(setting("url"));return{...smb,host:fromUrl.host||setting("host",smb?.host)||"",share:fromUrl.share||setting("share",smb?.share)||"",basePath:fromUrl.basePath??setting("base_path",smb?.basePath),domain:setting("domain",smb?.domain),username:setting("username",smb?.username),password:setting("password",smb?.password)}},resolveKind=()=>{let chosen=resolveCredential?.("storage","provider",options.provider);return chosen==="smb"?"smb":chosen==="local"?"local":options.provider??"local"},local=new LocalStorageProvider(basePath,deps),smbProvider=null,smbSignature="",warnedIncomplete=!1;return new LiveStorageProvider(()=>{if(resolveKind()!=="smb")return local;let config=resolveSmbConfig();if(!config.host||!config.share){if(!warnedIncomplete)warnedIncomplete=!0,deps.logger.error('[Storage] provider is "smb" but the host/share are not set \u2014 using local storage until they are');return local}warnedIncomplete=!1;let signature=JSON.stringify([config.host,config.share,config.basePath,config.domain,config.username,config.password,config.port]);if(!smbProvider||signature!==smbSignature)smbProvider?.close(),smbProvider=new SmbStorageProvider(resolveSmbConfig,deps,join3(basePath,".cache","smb")),smbSignature=signature,deps.logger.info("[Storage] SMB target configured",{target:smbProvider.describe});return smbProvider})}init_Services();init_ApiKey();init_Middleware();init_Captcha();init_Domain();init_ServerLogBuffer();init_transports();init_Secrets();init_lifetime();import{and as and10,desc as desc3,eq as eq16,inArray as inArray4}from"drizzle-orm";var DEFAULT_CHAT_CONFIG={enabled:!1,basePath:"/chat",groupsEnabled:!0,maxGroupParticipants:256,maxMessageLength:8000,editingEnabled:!0,deletionEnabled:!0,typingIndicators:!0,readReceipts:!0,presence:!0,realtimeTopicPrefix:"chat",messagePageSize:50,moderatorRoles:[],attachments:{enabled:!0,maxPerMessage:10,maxFileSizeBytes:null,allowedMimeTypes:[]}};function mergeChatConfig(input){let base=DEFAULT_CHAT_CONFIG;if(!input)return base;return{enabled:input.enabled??base.enabled,basePath:input.basePath??base.basePath,groupsEnabled:input.groupsEnabled??base.groupsEnabled,maxGroupParticipants:input.maxGroupParticipants??base.maxGroupParticipants,maxMessageLength:input.maxMessageLength??base.maxMessageLength,editingEnabled:input.editingEnabled??base.editingEnabled,deletionEnabled:input.deletionEnabled??base.deletionEnabled,typingIndicators:input.typingIndicators??base.typingIndicators,readReceipts:input.readReceipts??base.readReceipts,presence:input.presence??base.presence,realtimeTopicPrefix:input.realtimeTopicPrefix??base.realtimeTopicPrefix,messagePageSize:input.messagePageSize??base.messagePageSize,moderatorRoles:input.moderatorRoles??base.moderatorRoles,attachments:{enabled:input.attachments?.enabled??base.attachments.enabled,maxPerMessage:input.attachments?.maxPerMessage??base.attachments.maxPerMessage,maxFileSizeBytes:input.attachments?.maxFileSizeBytes??base.attachments.maxFileSizeBytes,allowedMimeTypes:input.attachments?.allowedMimeTypes??base.attachments.allowedMimeTypes}}}function getCol(table,col7){return table[col7]}function getTable(schemaTables,name2,logger2){return resolveSchemaTable(schemaTables,name2,logger2)}function computeDirectKey(userA,userB){return[userA,userB].sort().join(":")}function kindFromMime(mime){if(!mime)return"file";if(mime.startsWith("image/"))return"image";if(mime.startsWith("video/"))return"video";if(mime.startsWith("audio/"))return"audio";return"file"}function str3(value){return typeof value==="string"?value:null}function num2(value){return typeof value==="number"?value:null}function date(value){if(value instanceof Date)return value;if(typeof value==="string")return new Date(value);return null}function cdnUrl(cdnBasePath,fileId){if(!fileId)return null;return`${cdnBasePath}/${fileId}`}function mapConversation(row,cdnBasePath){let avatarFileId=str3(row.avatarFileId);return{id:String(row.id),type:str3(row.type)??"direct",title:str3(row.title),description:str3(row.description),avatarFileId,avatarUrl:cdnUrl(cdnBasePath,avatarFileId),directKey:str3(row.directKey),lastMessageAt:date(row.lastMessageAt),lastMessagePreview:str3(row.lastMessagePreview),lastMessageSenderId:str3(row.lastMessageSenderId),createdBy:str3(row.createdBy),createdAt:date(row.createdAt)??new Date(0),updatedAt:date(row.updatedAt)??new Date(0),isActive:row.isActive!==!1}}function mapParticipant(row){return{id:String(row.id),conversationId:String(row.conversationId),userId:String(row.userId),role:str3(row.role)??"member",lastReadMessageId:str3(row.lastReadMessageId),lastReadAt:date(row.lastReadAt),unreadCount:num2(row.unreadCount)??0,muted:row.muted===!0,mutedUntil:date(row.mutedUntil),notificationsEnabled:row.notificationsEnabled!==!1,leftAt:date(row.leftAt),joinedAt:date(row.createdAt)??new Date(0)}}function mapAttachment(row,cdnBasePath){let fileId=String(row.fileId);return{id:String(row.id),messageId:String(row.messageId),conversationId:String(row.conversationId),fileId,kind:str3(row.kind)??"file",originalName:str3(row.originalName),mimeType:str3(row.mimeType),size:num2(row.size),width:num2(row.width),height:num2(row.height),duration:num2(row.duration),url:`${cdnBasePath}/${fileId}`}}function mapMessage(row,attachments){let metadata=row.metadata;return{id:String(row.id),conversationId:String(row.conversationId),senderId:str3(row.senderId),content:str3(row.content),contentType:str3(row.contentType)??"text",replyToId:str3(row.replyToId),metadata:metadata&&typeof metadata==="object"?metadata:null,clientMessageId:str3(row.clientMessageId),editedAt:date(row.editedAt),deletedAt:date(row.deletedAt),createdAt:date(row.createdAt)??new Date(0),updatedAt:date(row.updatedAt)??new Date(0),attachments}}function buildPreview(content,contentType,attachmentCount){if(content&&content.trim().length>0){let trimmed=content.trim();return trimmed.length>280?`${trimmed.slice(0,277)}...`:trimmed}if(attachmentCount>0){if(contentType==="image")return attachmentCount>1?`${attachmentCount} photos`:"Photo";if(contentType==="video")return attachmentCount>1?`${attachmentCount} videos`:"Video";if(contentType==="audio")return"Audio";return attachmentCount>1?`${attachmentCount} files`:"File"}if(contentType==="system")return"System message";return""}import{and as and9,eq as eq15,inArray as inArray3}from"drizzle-orm";class ChatError extends Error{code;constructor(code,message){super(message);this.code=code,this.name="ChatError"}}function resolveChatTables(ctx){let conversations=getTable(ctx.schemaTables,"chat_conversations",ctx.logger),participants=getTable(ctx.schemaTables,"chat_participants",ctx.logger),messages=getTable(ctx.schemaTables,"chat_messages",ctx.logger);if(!conversations||!participants||!messages)throw new ChatError("disabled","Chat tables are not available in this schema");let attachments=getTable(ctx.schemaTables,"chat_message_attachments")??null,files=getTable(ctx.schemaTables,"files")??null;return{conversations,participants,messages,attachments,files}}function chatTopic(ctx){return ctx.config.realtimeTopicPrefix||"chat"}async function getConversationRow(ctx,tables,conversationId){return(await ctx.db.select().from(tables.conversations).where(eq15(getCol(tables.conversations,"id"),conversationId)).limit(1))[0]??null}async function getParticipant(ctx,tables,conversationId,userId){let row=(await ctx.db.select().from(tables.participants).where(and9(eq15(getCol(tables.participants,"conversationId"),conversationId),eq15(getCol(tables.participants,"userId"),userId))).limit(1))[0];return row?mapParticipant(row):null}async function requireActiveMembership(ctx,tables,conversationId,userId){let participant=await getParticipant(ctx,tables,conversationId,userId);if(!participant||participant.leftAt)throw new ChatError("forbidden","You are not a participant of this conversation");return participant}async function listParticipants(ctx,tables,conversationId,includeLeft=!1){let all=(await ctx.db.select().from(tables.participants).where(eq15(getCol(tables.participants,"conversationId"),conversationId))).map(mapParticipant);return includeLeft?all:all.filter((p)=>!p.leftAt)}async function assertUsersExist(ctx,userIds){let unique=[...new Set(userIds)];if(unique.length===0)return;let usersTable=getTable(ctx.schemaTables,"users",ctx.logger);if(!usersTable)throw new ChatError("disabled","Users table is not available in this schema");let rows=await ctx.db.select({id:getCol(usersTable,"id")}).from(usersTable).where(inArray3(getCol(usersTable,"id"),unique)),found=new Set(rows.map((r)=>r.id));for(let id of unique)if(!found.has(id))throw new ChatError("not_found",`User ${id} does not exist`)}function deliverToParticipants(ctx,participants,event,exceptUserId){if(!ctx.broadcaster)return;let topic=chatTopic(ctx);for(let participant of participants){if(participant.leftAt)continue;if(exceptUserId&&participant.userId===exceptUserId)continue;ctx.broadcaster.broadcastToUser(participant.userId,topic,event)}}async function buildSummary(ctx,tables,conversationRow,userId,participantsOverride){let conversation=mapConversation(conversationRow,ctx.cdnBasePath),participants=participantsOverride??await listParticipants(ctx,tables,conversation.id),myParticipant=participants.find((p)=>p.userId===userId)??null;return{...conversation,participants,myParticipant,unreadCount:myParticipant?.unreadCount??0}}async function getOrCreateDirect(ctx,params){let tables=resolveChatTables(ctx),{userId,targetUserId}=params;if(!targetUserId||targetUserId===userId)throw new ChatError("validation","A different target user is required");await assertUsersExist(ctx,[targetUserId]);let directKey=computeDirectKey(userId,targetUserId),existing=(await ctx.db.select().from(tables.conversations).where(eq16(getCol(tables.conversations,"directKey"),directKey)).limit(1))[0];if(existing)return await rejoinIfNeeded(ctx,tables,String(existing.id),[userId,targetUserId]),buildSummary(ctx,tables,existing,userId);let now=new Date,conversationRow;try{conversationRow=(await ctx.db.insert(tables.conversations).values({type:"direct",directKey,createdBy:userId,lastMessageAt:now,lastMessagePreview:""}).returning())[0]}catch(_err){let raced=(await ctx.db.select().from(tables.conversations).where(eq16(getCol(tables.conversations,"directKey"),directKey)).limit(1))[0];if(!raced)throw new ChatError("conflict","Failed to create direct conversation");return await rejoinIfNeeded(ctx,tables,String(raced.id),[userId,targetUserId]),buildSummary(ctx,tables,raced,userId)}let conversationId=String(conversationRow.id);await ctx.db.insert(tables.participants).values([{conversationId,userId,role:"member",createdBy:userId},{conversationId,userId:targetUserId,role:"member",createdBy:userId}]);let summary=await buildSummary(ctx,tables,conversationRow,userId);return deliverToParticipants(ctx,summary.participants,{type:"conversation.created",conversationId,conversation:summary},userId),summary}async function createGroup(ctx,params){if(!ctx.config.groupsEnabled)throw new ChatError("disabled","Group conversations are disabled");let tables=resolveChatTables(ctx),{creatorId,title}=params;if(!title||title.trim().length===0)throw new ChatError("validation","A group title is required");let memberIds=[...new Set([creatorId,...params.participantIds])];if(memberIds.length>ctx.config.maxGroupParticipants)throw new ChatError("validation",`A group cannot exceed ${ctx.config.maxGroupParticipants} participants`);if(await assertUsersExist(ctx,memberIds),params.avatarFileId){if(!tables.files)throw new ChatError("disabled","Avatar files require storage to be enabled");let avatarRow=(await ctx.db.select().from(tables.files).where(eq16(getCol(tables.files,"id"),params.avatarFileId)).limit(1))[0],owner=avatarRow?String(avatarRow.uploadedBy??avatarRow.createdBy??""):"";if(!avatarRow||owner!==creatorId)throw new ChatError("forbidden","Avatar file is not owned by the creator")}let now=new Date,conversationRow=(await ctx.db.insert(tables.conversations).values({type:"group",title:title.trim(),description:params.description??null,avatarFileId:params.avatarFileId??null,createdBy:creatorId,lastMessageAt:now,lastMessagePreview:""}).returning())[0],conversationId=String(conversationRow.id);await ctx.db.insert(tables.participants).values(memberIds.map((memberId)=>({conversationId,userId:memberId,role:memberId===creatorId?"owner":"member",createdBy:creatorId})));let summary=await buildSummary(ctx,tables,conversationRow,creatorId);return deliverToParticipants(ctx,summary.participants,{type:"conversation.created",conversationId,conversation:summary},creatorId),summary}async function listConversations(ctx,params){let tables=resolveChatTables(ctx),limit=Math.min(Math.max(params.limit??30,1),100),offset=Math.max(params.offset??0,0),myParticipants=(await ctx.db.select().from(tables.participants).where(eq16(getCol(tables.participants,"userId"),params.userId))).map(mapParticipant).filter((p)=>!p.leftAt);if(myParticipants.length===0)return[];let conversationIds=myParticipants.map((p)=>p.conversationId),pageRows=await ctx.db.select().from(tables.conversations).where(and10(inArray4(getCol(tables.conversations,"id"),conversationIds),eq16(getCol(tables.conversations,"isActive"),!0))).orderBy(desc3(getCol(tables.conversations,"lastMessageAt"))).limit(limit).offset(offset);if(pageRows.length===0)return[];let pageIds=pageRows.map((r)=>String(r.id)),participantRows=await ctx.db.select().from(tables.participants).where(inArray4(getCol(tables.participants,"conversationId"),pageIds)),byConversation=new Map;for(let row of participantRows){let mapped=mapParticipant(row);if(mapped.leftAt)continue;let list2=byConversation.get(mapped.conversationId)??[];list2.push(mapped),byConversation.set(mapped.conversationId,list2)}let summaries=[];for(let row of pageRows){let id=String(row.id);summaries.push(await buildSummary(ctx,tables,row,params.userId,byConversation.get(id)??[]))}return summaries}async function getConversation(ctx,conversationId,userId){let tables=resolveChatTables(ctx);await requireActiveMembership(ctx,tables,conversationId,userId);let row=await getConversationRow(ctx,tables,conversationId);if(!row)throw new ChatError("not_found","Conversation not found");return buildSummary(ctx,tables,row,userId)}async function rejoinIfNeeded(ctx,tables,conversationId,userIds){for(let userId of userIds){let participant=await getParticipant(ctx,tables,conversationId,userId);if(!participant)await ctx.db.insert(tables.participants).values({conversationId,userId,role:"member",createdBy:userId});else if(participant.leftAt)await ctx.db.update(tables.participants).set({leftAt:null}).where(eq16(getCol(tables.participants,"id"),participant.id))}}function assertCanManage(actor){if(actor.role!=="owner"&&actor.role!=="admin")throw new ChatError("forbidden","Only group admins can manage participants")}async function addParticipants(ctx,conversationId,actorId,userIds){let tables=resolveChatTables(ctx),conversation=await getConversationRow(ctx,tables,conversationId);if(!conversation)throw new ChatError("not_found","Conversation not found");if(mapConversation(conversation,ctx.cdnBasePath).type!=="group")throw new ChatError("validation","Participants can only be managed in group conversations");let actor=await requireActiveMembership(ctx,tables,conversationId,actorId);assertCanManage(actor);let toAdd=[...new Set(userIds)];await assertUsersExist(ctx,toAdd);let current=await listParticipants(ctx,tables,conversationId,!0),activeCount=current.filter((p)=>!p.leftAt).length,newOnes=toAdd.filter((id)=>!current.some((p)=>p.userId===id&&!p.leftAt));if(activeCount+newOnes.length>ctx.config.maxGroupParticipants)throw new ChatError("validation","Group participant limit exceeded");for(let userId of toAdd)await rejoinIfNeeded(ctx,tables,conversationId,[userId]);let participants=await listParticipants(ctx,tables,conversationId);return deliverToParticipants(ctx,participants,{type:"participant.added",conversationId,userIds:toAdd,by:actorId}),participants}async function removeParticipant(ctx,conversationId,actorId,targetUserId){let tables=resolveChatTables(ctx),actor=await requireActiveMembership(ctx,tables,conversationId,actorId);if(actorId!==targetUserId)assertCanManage(actor);let target2=await getParticipant(ctx,tables,conversationId,targetUserId);if(!target2||target2.leftAt)throw new ChatError("not_found","Participant not found in conversation");await ctx.db.update(tables.participants).set({leftAt:new Date}).where(eq16(getCol(tables.participants,"id"),target2.id));let participants=await listParticipants(ctx,tables,conversationId),event={type:"participant.removed",conversationId,userId:targetUserId,by:actorId};if(deliverToParticipants(ctx,participants,event),ctx.broadcaster)ctx.broadcaster.broadcastToUser(targetUserId,ctx.config.realtimeTopicPrefix||"chat",event)}import{and as and11,desc as desc4,eq as eq17,inArray as inArray5,isNull,lt,ne,sql as sql6}from"drizzle-orm";async function loadAttachments(ctx,tables,messageIds){let grouped=new Map;if(!tables.attachments||messageIds.length===0)return grouped;let rows=await ctx.db.select().from(tables.attachments).where(inArray5(getCol(tables.attachments,"messageId"),messageIds));for(let row of rows){let attachment=mapAttachment(row,ctx.cdnBasePath),list2=grouped.get(attachment.messageId)??[];list2.push(attachment),grouped.set(attachment.messageId,list2)}return grouped}function inferContentType(explicit,attachments){if(explicit)return explicit;if(attachments.length===0)return"text";let kind=attachments[0]?.kind;if(kind==="image")return"image";if(kind==="video")return"video";if(kind==="audio")return"audio";return"file"}async function persistAttachments(ctx,tables,conversationId,messageId,params){let inputs=params.attachments??[];if(inputs.length===0)return[];if(!ctx.attachmentsAvailable||!tables.attachments||!tables.files)throw new ChatError("disabled","File attachments require storage and CDN to be enabled");if(inputs.length>ctx.config.attachments.maxPerMessage)throw new ChatError("validation",`A message cannot have more than ${ctx.config.attachments.maxPerMessage} attachments`);let fileIds=inputs.map((a)=>a.fileId),fileRows=await ctx.db.select().from(tables.files).where(inArray5(getCol(tables.files,"id"),fileIds)),filesById=new Map;for(let row of fileRows)filesById.set(String(row.id),row);let payloads=inputs.map((input)=>{let fileRow=filesById.get(input.fileId);if(!fileRow)throw new ChatError("not_found",`Attachment file ${input.fileId} was not found`);if(String(fileRow.uploadedBy??fileRow.createdBy??"")!==params.senderId)throw new ChatError("forbidden",`Attachment file ${input.fileId} is not owned by the sender`);let mimeType=fileRow.mimeType??input.mimeType??null;return{conversationId,messageId,fileId:input.fileId,kind:input.kind??kindFromMime(mimeType),originalName:fileRow.originalName??input.originalName??null,mimeType,size:fileRow.size??input.size??null,width:input.width??null,height:input.height??null,duration:input.duration??null,createdBy:params.senderId}});return(await ctx.db.insert(tables.attachments).values(payloads).returning()).map((row)=>mapAttachment(row,ctx.cdnBasePath))}async function sendMessage(ctx,params){let tables=resolveChatTables(ctx);await requireActiveMembership(ctx,tables,params.conversationId,params.senderId);let content=params.content?.trim()?params.content:null,hasAttachments=(params.attachments?.length??0)>0;if(!content&&!hasAttachments)throw new ChatError("validation","A message must contain text or at least one attachment");if(content&&content.length>ctx.config.maxMessageLength)throw new ChatError("validation",`Message exceeds the maximum length of ${ctx.config.maxMessageLength} characters`);if(params.metadata!==void 0&¶ms.metadata!==null){if(JSON.stringify(params.metadata).length>4096)throw new ChatError("validation","Message metadata exceeds the maximum size of 4096 bytes")}let{message,participants}=await ctx.db.transaction(async(tx)=>{let txCtx={...ctx,db:tx},messageRow=(await tx.insert(tables.messages).values({conversationId:params.conversationId,senderId:params.senderId,content,contentType:params.contentType??"text",replyToId:params.replyToId??null,clientMessageId:params.clientMessageId??null,metadata:params.metadata??{},createdBy:params.senderId}).returning())[0],messageId=String(messageRow.id),attachments=await persistAttachments(txCtx,tables,params.conversationId,messageId,params),contentType=inferContentType(params.contentType,attachments);if(contentType!==messageRow.contentType)await tx.update(tables.messages).set({contentType}).where(eq17(getCol(tables.messages,"id"),messageId)),messageRow.contentType=contentType;let mappedMessage=mapMessage(messageRow,attachments),preview=buildPreview(mappedMessage.content,mappedMessage.contentType,attachments.length),now=mappedMessage.createdAt;await tx.update(tables.conversations).set({lastMessageAt:now,lastMessagePreview:preview,lastMessageSenderId:params.senderId,updatedAt:new Date}).where(eq17(getCol(tables.conversations,"id"),params.conversationId)),await tx.update(tables.participants).set({unreadCount:sql6`${getCol(tables.participants,"unreadCount")} + 1`}).where(and11(eq17(getCol(tables.participants,"conversationId"),params.conversationId),ne(getCol(tables.participants,"userId"),params.senderId),isNull(getCol(tables.participants,"leftAt"))));let parts=await listParticipants(txCtx,tables,params.conversationId);return{message:mappedMessage,participants:parts}});return deliverToParticipants(ctx,participants,{type:"message.created",conversationId:params.conversationId,message}),message}async function getMessages(ctx,params){let tables=resolveChatTables(ctx);await requireActiveMembership(ctx,tables,params.conversationId,params.userId);let limit=Math.min(Math.max(params.limit??ctx.config.messagePageSize,1),100),conditions=[eq17(getCol(tables.messages,"conversationId"),params.conversationId)];if(params.before){let cursor=(await ctx.db.select().from(tables.messages).where(eq17(getCol(tables.messages,"id"),params.before)).limit(1))[0];if(cursor?.createdAt)conditions.push(lt(getCol(tables.messages,"createdAt"),cursor.createdAt))}let rows=await ctx.db.select().from(tables.messages).where(and11(...conditions)).orderBy(desc4(getCol(tables.messages,"createdAt"))).limit(limit+1),pageRows=rows.slice(0,limit),hasMore=rows.length>limit,attachmentsByMessage=await loadAttachments(ctx,tables,pageRows.map((r)=>String(r.id)));return{messages:pageRows.map((row)=>mapMessage(row,attachmentsByMessage.get(String(row.id))??[])),hasMore}}async function markRead(ctx,conversationId,userId,messageId){let tables=resolveChatTables(ctx),participant=await requireActiveMembership(ctx,tables,conversationId,userId),targetMessageId=messageId??null;if(!targetMessageId){let latestRow=(await ctx.db.select().from(tables.messages).where(eq17(getCol(tables.messages,"conversationId"),conversationId)).orderBy(desc4(getCol(tables.messages,"createdAt"))).limit(1))[0];targetMessageId=latestRow?String(latestRow.id):null}let readAt=new Date;if(await ctx.db.update(tables.participants).set({lastReadMessageId:targetMessageId,lastReadAt:readAt,unreadCount:0}).where(eq17(getCol(tables.participants,"id"),participant.id)),ctx.config.readReceipts){let participants=await listParticipants(ctx,tables,conversationId);deliverToParticipants(ctx,participants,{type:"conversation.read",conversationId,userId,lastReadMessageId:targetMessageId,readAt:readAt.toISOString()},userId)}return{lastReadMessageId:targetMessageId,readAt}}async function editMessage(ctx,messageId,userId,content){if(!ctx.config.editingEnabled)throw new ChatError("disabled","Message editing is disabled");let tables=resolveChatTables(ctx),row=(await ctx.db.select().from(tables.messages).where(eq17(getCol(tables.messages,"id"),messageId)).limit(1))[0];if(!row||row.deletedAt)throw new ChatError("not_found","Message not found");if(String(row.senderId)!==userId)throw new ChatError("forbidden","You can only edit your own messages");let trimmed=content.trim();if(!trimmed)throw new ChatError("validation","Message content cannot be empty");if(trimmed.length>ctx.config.maxMessageLength)throw new ChatError("validation","Message exceeds the maximum length");let editedAt=new Date,updated=await ctx.db.update(tables.messages).set({content:trimmed,editedAt,updatedAt:editedAt}).where(eq17(getCol(tables.messages,"id"),messageId)).returning(),attachments=await loadAttachments(ctx,tables,[messageId]),message=mapMessage(updated[0],attachments.get(messageId)??[]),participants=await listParticipants(ctx,tables,String(row.conversationId));return deliverToParticipants(ctx,participants,{type:"message.updated",conversationId:String(row.conversationId),message}),message}async function deleteMessage(ctx,messageId,userId,asModerator=!1){if(!ctx.config.deletionEnabled&&!asModerator)throw new ChatError("disabled","Message deletion is disabled");let tables=resolveChatTables(ctx),row=(await ctx.db.select().from(tables.messages).where(eq17(getCol(tables.messages,"id"),messageId)).limit(1))[0];if(!row||row.deletedAt)throw new ChatError("not_found","Message not found");if(!asModerator&&String(row.senderId)!==userId)throw new ChatError("forbidden","You can only delete your own messages");let deletedAt=new Date;await ctx.db.update(tables.messages).set({content:null,deletedAt,updatedAt:deletedAt}).where(eq17(getCol(tables.messages,"id"),messageId));let participants=await listParticipants(ctx,tables,String(row.conversationId));deliverToParticipants(ctx,participants,{type:"message.deleted",conversationId:String(row.conversationId),messageId})}async function setTyping(ctx,conversationId,userId,isTyping=!0){if(!ctx.config.typingIndicators)return;let tables=resolveChatTables(ctx),participants=await listParticipants(ctx,tables,conversationId);if(!participants.some((p)=>p.userId===userId))throw new ChatError("forbidden","You are not a participant of this conversation");deliverToParticipants(ctx,participants,{type:"typing",conversationId,userId,isTyping},userId)}class ChatService{ctx;constructor(init){this.ctx={db:init.db,schemaTables:init.schemaTables,config:init.config,logger:init.logger,broadcaster:init.broadcaster??null,cdnBasePath:init.cdnBasePath??"/cdn",attachmentsAvailable:init.attachmentsAvailable??!1}}get config(){return this.ctx.config}getOrCreateDirect(userId,targetUserId){return getOrCreateDirect(this.ctx,{userId,targetUserId})}createGroup(params){return createGroup(this.ctx,params)}listConversations(userId,opts){return listConversations(this.ctx,{userId,limit:opts?.limit,offset:opts?.offset})}getConversation(conversationId,userId){return getConversation(this.ctx,conversationId,userId)}addParticipants(conversationId,actorId,userIds){return addParticipants(this.ctx,conversationId,actorId,userIds)}removeParticipant(conversationId,actorId,targetUserId){return removeParticipant(this.ctx,conversationId,actorId,targetUserId)}sendMessage(params){return sendMessage(this.ctx,params)}getMessages(params){return getMessages(this.ctx,params)}markRead(conversationId,userId,messageId){return markRead(this.ctx,conversationId,userId,messageId)}editMessage(messageId,userId,content){return editMessage(this.ctx,messageId,userId,content)}deleteMessage(messageId,userId,asModerator=!1){return deleteMessage(this.ctx,messageId,userId,asModerator)}setTyping(conversationId,userId,isTyping){return setTyping(this.ctx,conversationId,userId,isTyping)}}init_SystemCollector();init_Notification();var EXTEND_ALLOWED_KEYS=new Set(["table_name","extends","columns","indexes"]);function hasDbDefault(column){return column.default!==void 0||column.defaultRaw!==void 0||column.generatedAlwaysAs!==void 0||column.generatedAlwaysAsIdentity===!0||column.generatedByDefaultAsIdentity===!0}var AUTH_FEATURES=new Set(["authentication","authorization"]);function resolveEntities(systemTables2,configEntities,options={}){let errors2=[],warnings=[],consumed=new Set,entities=[];for(let system of systemTables2){let config=configEntities.find((c)=>c.table_name===system.table_name);if(!config){entities.push(system);continue}if(consumed.add(config.table_name),!config.extends){warnings.push(`[Schema] "${config.table_name}" is declared in config.entities AND ships as a system table. Using YOUR definition and skipping the built-in one. Add "extends": true to inherit the built-in columns and route policy instead.`),entities.push(config);continue}for(let key2 of Object.keys(config))if(!EXTEND_ALLOWED_KEYS.has(key2))warnings.push(`[Schema] "${config.table_name}" sets "${key2}" alongside "extends": true \u2014 ignored. `+"An extending entry inherits every table-level setting from the built-in definition.");if(options.enabledTableNames&&!options.enabledTableNames.has(system.table_name))errors2.push({code:"E5_FEATURE_DISABLED",table:system.table_name,message:`"${system.table_name}" is extended but its feature is disabled, so the table is never created. Enable the feature or remove the extending entry.`});if(options.consumerMode&&(system.feature_set??[]).some((f)=>AUTH_FEATURES.has(f)))errors2.push({code:"E3_CONSUMER_AUTH_TABLE",table:system.table_name,message:`"${system.table_name}" is an auth system table and cannot be extended in consumer mode \u2014 `+"the identity tables live in the IDP. Extending it would create a local copy here."});let builtInNames=new Set((system.columns??[]).map((c)=>c.name));if(system.add_base_columns!==!1)for(let name2 of options.baseColumnNames??[])builtInNames.add(name2);for(let column of config.columns??[]){if(builtInNames.has(column.name))errors2.push({code:"E1_COLUMN_COLLISION",table:system.table_name,column:column.name,message:`"${system.table_name}.${column.name}" already exists in the built-in definition. An extending entry may only ADD columns; rename yours.`});if(column.notNull===!0&&column.nullable!==!0&&!hasDbDefault(column))errors2.push({code:"E2_NOT_NULL_WITHOUT_DEFAULT",table:system.table_name,column:column.name,message:`"${system.table_name}.${column.name}" is notNull without a default. The framework writes this table from fixed-column inserts (register, invite, admin create-user, godmin seed, `+"tenant provisioning) that cannot supply it \u2014 every one of them would fail. Make it "+"nullable or give it a default."})}let merged={...system,columns:[...system.columns??[],...config.columns??[]],indexes:[...system.indexes??[],...config.indexes??[]]};entities.push(merged)}for(let config of configEntities){if(consumed.has(config.table_name))continue;if(config.extends){errors2.push({code:"E4_UNKNOWN_SYSTEM_TABLE",table:config.table_name,message:`"${config.table_name}" sets "extends": true but there is no system table with that name. Remove the flag to declare it as an ordinary entity.`});continue}entities.push(config)}return{entities,errors:errors2,warnings}}function resolveAuthType(pathname,auth){let at=(route)=>pathname===route||pathname.endsWith(route)||pathname.includes(`${route}/`);if(at(auth?.login?.route||"/auth/login"))return"login";if(at(auth?.register?.route||"/auth/register"))return"register";if(at(auth?.passwordReset?.route||"/auth/password-reset"))return"passwordReset";if(at(auth?.magicLink?.route||"/auth/magic-link"))return"magicLink";if(at(auth?.invite?.route||"/auth/invite"))return"other";if(at("/sessions/approve")||at("/sessions/reject"))return"login";return}init_Logger2();var METHOD_MAP={GET:["GET"],POST:["POST"],PUT:["PUT"],DELETE:["DELETE"],PATCH:["PATCH"],TOGGLE:["PATCH"],VERIFICATION:["POST"]};function buildAuthPublicRoutes(config,basePath){let routes=[],auth=config.authentication;if(!auth)return routes;if(auth.login?.enabled&&auth.login?.isPublic)routes.push({path:auth.login.route||`${basePath}/auth/login`,method:"POST",source:"auth"});if(auth.register?.enabled&&auth.register?.isPublic)routes.push({path:auth.register.route||`${basePath}/auth/register`,method:"POST",source:"auth"});if(auth.logout?.enabled&&auth.logout?.isPublic)routes.push({path:auth.logout.route||`${basePath}/auth/logout`,method:"POST",source:"auth"});if(auth.refresh?.enabled&&auth.refresh?.isPublic)routes.push({path:auth.refresh.route||`${basePath}/auth/refresh`,method:"POST",source:"auth"});if(auth.passwordReset?.enabled&&auth.passwordReset?.isPublic){let baseRoute=auth.passwordReset.route||`${basePath}/auth/password-reset`;routes.push({path:`${baseRoute}/request`,method:"POST",source:"auth"},{path:`${baseRoute}/confirm`,method:"POST",source:"auth"})}if(auth.passwordChange?.enabled&&auth.passwordChange?.isPublic)routes.push({path:auth.passwordChange.route||`${basePath}/auth/password-change`,method:"POST",source:"auth"});if(auth.magicLink?.enabled&&auth.magicLink?.isPublic)routes.push({path:auth.magicLink.route||`${basePath}/auth/magic-link`,method:"POST",source:"auth"},{path:auth.magicLink.verifyRoute||`${basePath}/auth/magic-link/verify`,method:"GET",source:"auth"});if(auth.register?.enabled&&auth.register?.emailVerification?.enabled)routes.push({path:`${basePath}/verify-email`,method:"GET",source:"auth"},{path:`${basePath}/resend-verification`,method:"POST",source:"auth"});if(auth.invite?.enabled&&auth.invite?.isPublic)routes.push({path:auth.invite.route||`${basePath}/auth/invite`,method:"POST",source:"auth"});if(auth.invite?.enabled){let inviteRoute=auth.invite.route||`${basePath}/auth/invite`;routes.push({path:`${inviteRoute}/verify`,method:"POST",source:"auth"})}if(auth.passwordSet?.enabled)routes.push({path:auth.passwordSet.route||`${basePath}/auth/password-set`,method:"POST",source:"auth"});if(auth.webauthn?.enabled){let webauthnRoute=auth.webauthn.route||`${basePath}/auth/webauthn`;routes.push({path:`${webauthnRoute}/authenticate/options`,method:"POST",source:"auth"},{path:`${webauthnRoute}/authenticate/verify`,method:"POST",source:"auth"})}if(auth.captcha?.enabled&&auth.captcha?.isPublic){let baseRoute=auth.captcha.route||`${basePath}/auth/captcha`;routes.push({path:`${baseRoute}/generate`,method:"GET",source:"auth"},{path:`${baseRoute}/validate`,method:"POST",source:"auth"})}if(auth.sessions?.enabled){let sessionsRoute=auth.sessions.route||`${basePath}/auth/sessions`;routes.push({path:`${sessionsRoute}/approve`,method:"POST",source:"auth"},{path:`${sessionsRoute}/reject`,method:"POST",source:"auth"},{path:`${sessionsRoute}/approve-page`,method:"GET",source:"auth"},{path:`${sessionsRoute}/reject-page`,method:"GET",source:"auth"},{path:`${sessionsRoute}/approval-status`,method:"GET",source:"auth"})}if(auth.oauth?.enabled){let oauthBase=auth.oauth.basePath||`${basePath}/auth/oauth`,knownProviders=["google","github","microsoft","discord","facebook","twitter","apple","custom"];routes.push({path:`${oauthBase}/providers`,method:"GET",source:"auth"});for(let provider of knownProviders)routes.push({path:`${oauthBase}/${provider}`,method:"GET",source:"auth"},{path:`${oauthBase}/${provider}/callback`,method:"GET",source:"auth"})}return routes}function buildEntityPublicRoutes(entities,basePath,_schema){let routes=[];for(let entity of entities){if(!entity.is_public)continue;let camelName=entity.table_name.replace(/_([a-z])/g,(_,l)=>l.toUpperCase()),entityPath=`${basePath}/${camelName}`;for(let[nucleusMethod,isPublic]of Object.entries(entity.is_public)){if(!isPublic)continue;let httpMethods=METHOD_MAP[nucleusMethod];if(!httpMethods)continue;for(let method of httpMethods)if(method==="GET")routes.push({path:entityPath,method:"GET",source:"entity"}),routes.push({path:`${entityPath}/:id`,method:"GET",source:"entity"});else if(method==="POST")routes.push({path:entityPath,method:"POST",source:"entity"});else if(method==="PUT"||method==="PATCH")routes.push({path:`${entityPath}/:id`,method,source:"entity"});else if(method==="DELETE")routes.push({path:`${entityPath}/:id`,method:"DELETE",source:"entity"})}}return routes}function buildSystemTablePublicRoutes(systemTables2,basePath,schema){return buildEntityPublicRoutes(systemTables2,basePath,schema)}function buildPublicRoutes(config,systemTables2,basePath="",schema="public"){let authRoutes=buildAuthPublicRoutes(config,basePath),entityRoutes=buildEntityPublicRoutes(config.entities||[],basePath,schema),systemRoutes=buildSystemTablePublicRoutes(systemTables2,basePath,schema),pubsubRoutes=[];if(config.pubsub?.enabled){let pubsubBasePath=config.pubsub.basePath||"/subs",wsPath=config.pubsub.wsPath||"/api/events/subscribe";pubsubRoutes.push({path:`${pubsubBasePath}/:topic`,method:"POST",source:"system"},{path:wsPath,method:"GET",source:"system"})}let paymentRoutes=[];if(config.payment?.enabled){let paymentBasePath=config.payment.basePath||"/payment";paymentRoutes.push({path:`${paymentBasePath}/callback`,method:"POST",source:"system"},{path:`${paymentBasePath}/callback`,method:"OPTIONS",source:"system"},{path:`${paymentBasePath}/bin-query`,method:"POST",source:"system"},{path:`${paymentBasePath}/webhook`,method:"POST",source:"system"})}let discoveryRoutes=[];if(config.authorization?.endpointDiscovery?.enabled)discoveryRoutes.push({path:"/authorization/route-manifest",method:"GET",source:"system"},{path:"/authorization/route-manifest",method:"OPTIONS",source:"system"},{path:"/authorization/role-claims-manifest",method:"GET",source:"system"},{path:"/authorization/role-claims-manifest",method:"OPTIONS",source:"system"});let domainRoutes=[];if(config.domains?.enabled){let domainsBasePath=config.domains.basePath||"/domains";domainRoutes.push({path:`${basePath}${domainsBasePath}/resolve`,method:"GET",source:"system"})}let tenantRoutes=[];if(config.database?.isMultiTenant)tenantRoutes.push({path:`${basePath}/tenants`,method:"GET",source:"system"}),tenantRoutes.push({path:`${basePath}/tenants/check-subdomain/:subdomain`,method:"GET",source:"system"}),tenantRoutes.push({path:`${basePath}/tenants/self-signup`,method:"POST",source:"system"}),tenantRoutes.push({path:`${basePath}/tenants/refresh`,method:"POST",source:"system"});let customRoutes=[{path:"/nucleus-core",method:"GET",source:"custom"},{path:"/public",method:"GET",source:"custom"},{path:"/docs",method:"GET",source:"custom"},{path:"/docs/json",method:"GET",source:"custom"},{path:"/swagger",method:"GET",source:"custom"},{path:"/swagger/json",method:"GET",source:"custom"}],configPublicPaths=config.authorization?.publicPaths||[],ALL_PUBLIC_METHODS=["GET","POST","PUT","PATCH","DELETE","OPTIONS"],configPublicRoutes=configPublicPaths.flatMap((entry)=>{let trimmed=entry.trim(),qualified=trimmed.match(/^(GET|POST|PUT|PATCH|DELETE|OPTIONS)\s+(.+)$/i);if(qualified?.[1]&&qualified[2]){let method=qualified[1].toUpperCase(),path2=qualified[2].trim(),routes=[{path:path2,method,source:"custom"}];if(method!=="OPTIONS")routes.push({path:path2,method:"OPTIONS",source:"custom"});return routes}if(trimmed.startsWith("/auth/"))return ALL_PUBLIC_METHODS.map((method)=>({path:trimmed,method,source:"custom"}));return logger.warn(`[Security] publicPaths entry "${trimmed}" is unqualified \u2014 exposing GET + OPTIONS only. To make a write method public, use the explicit form, e.g. "POST ${trimmed}".`),[{path:trimmed,method:"GET",source:"custom"},{path:trimmed,method:"OPTIONS",source:"custom"}]});return[...authRoutes,...entityRoutes,...systemRoutes,...pubsubRoutes,...paymentRoutes,...discoveryRoutes,...domainRoutes,...tenantRoutes,...customRoutes,...configPublicRoutes]}function isPublicRoute(publicRoutes,path2,method){if(/\/\/|\\|%2f|%2e|%5c/i.test(path2))return!1;let normalizedPath=path2.replace(/\/$/,""),normalizedMethod=method.toUpperCase();for(let route of publicRoutes){if(route.method!==normalizedMethod)continue;if(matchPath(route.path,normalizedPath))return!0}return!1}function matchPath(pattern,path2){if(pattern===path2)return!0;let patternParts=pattern.split("/").filter(Boolean),pathParts=path2.split("/").filter(Boolean);if(patternParts.length!==pathParts.length)return!1;for(let i=0;i<patternParts.length;i++){let patternPart=patternParts[i],pathPart=pathParts[i];if(patternPart?.startsWith(":"))continue;if(patternPart!==pathPart)return!1}return!0}import{Elysia as Elysia2}from"elysia";import{eq as eq19}from"drizzle-orm";import{eq as eq18}from"drizzle-orm";var col7=(table,name2)=>{let tableRecord=table,snakeCase=name2.replace(/([A-Z])/g,"_$1").toLowerCase();return tableRecord[name2]||tableRecord[snakeCase]};async function requireGodmin(db,usersTable,userId){let user=(await db.select().from(usersTable).where(eq18(col7(usersTable,"id"),userId)).limit(1))[0];return Boolean(user?.isGod)}function validatePassword(pwd,policy){let errors2=[],minLen=policy?.minLength??8,maxLen=policy?.maxLength??128,needUpper=policy?.requireUppercase??!0,needLower=policy?.requireLowercase??!0,needDigit=policy?.requireNumber??!0,needSpecial=policy?.requireSpecialChar??!1;if(pwd.length<minLen)errors2.push(`Password must be at least ${minLen} characters`);if(pwd.length>maxLen)errors2.push(`Password must be at most ${maxLen} characters`);if(needUpper&&!/[A-Z]/.test(pwd))errors2.push("Password must contain uppercase letter");if(needLower&&!/[a-z]/.test(pwd))errors2.push("Password must contain lowercase letter");if(needDigit&&!/[0-9]/.test(pwd))errors2.push("Password must contain a number");if(needSpecial&&!/[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/.test(pwd))errors2.push("Password must contain a special character");return{valid:errors2.length===0,errors:errors2}}var handleActivateUsers=(db,usersTable,logger2)=>async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId||!await requireGodmin(db,usersTable,userId))return ctx.set.status=403,{success:!1,message:"Forbidden"};let result=await db.update(usersTable).set({isLocked:!1,lockedUntil:null,failedLoginAttempts:0,updatedAt:new Date}).where(eq19(col7(usersTable,"cohortId"),ctx.params.id)).returning();return logger2.audit({entityName:"user_cohorts",entityId:ctx.params.id,operation:"COHORT_ACTIVATE_USERS",userId,summary:`Activated ${result.length} users in cohort`}),{success:!0,data:{affected:result.length}}};init_assignDefaultRole();init_utils6();import{count,eq as eq21,inArray as inArray6}from"drizzle-orm";var handleBulkCreateUsers=(config,logger2)=>{let{db,usersTable,cohortsTable,rolesTable,userRolesTable,profilesTable}=config;return async(ctx)=>{if(!db||!usersTable||!cohortsTable)return ctx.set.status=500,{success:!1,message:"Server misconfigured"};let callerId=ctx.request.headers.get("x-user-id");if(!callerId||!await requireGodmin(db,usersTable,callerId))return ctx.set.status=403,{success:!1,message:"Forbidden"};let cohortId=ctx.params.id;if((await db.select().from(cohortsTable).where(eq21(col7(cohortsTable,"id"),cohortId)).limit(1)).length===0)return ctx.set.status=404,{success:!1,message:"Cohort not found"};let{users:explicitUsers,emailPrefix,emailDomain,sharedPassword,count:userCount,roleIds}=ctx.body,userList=[];if(explicitUsers&&explicitUsers.length>0)for(let u of explicitUsers)userList.push({email:u.email.toLowerCase().trim(),password:u.password,firstName:u.profile?.firstName,lastName:u.profile?.lastName});else if(emailPrefix&&emailDomain&&sharedPassword&&userCount){let padLen=String(userCount).length;for(let i=1;i<=userCount;i++){let paddedNum=String(i).padStart(padLen,"0");userList.push({email:`${emailPrefix}-${paddedNum}@${emailDomain}`.toLowerCase(),password:sharedPassword})}}else return ctx.set.status=400,{success:!1,message:'Provide either "users" array or "emailPrefix" + "emailDomain" + "sharedPassword" + "count"'};if(userList.length>500)return ctx.set.status=400,{success:!1,message:"Maximum 500 users per batch"};for(let entry of userList){let validation=validatePassword(entry.password,config.passwordPolicy);if(!validation.valid)return ctx.set.status=400,{success:!1,message:`Password too weak for ${entry.email}`,errors:validation.errors}}let emails=userList.map((u)=>u.email),existingRows=await db.select({email:col7(usersTable,"email")}).from(usersTable).where(inArray6(col7(usersTable,"email"),emails)),existingEmails=new Set(existingRows.map((r)=>String(r.email).toLowerCase())),created=[],skipped=[],now=new Date;for(let entry of userList){if(existingEmails.has(entry.email)){skipped.push(entry.email);continue}let hashedPw=await hashPassword(entry.password),newUser=(await db.insert(usersTable).values({email:entry.email,password:hashedPw,emailVerified:!0,verifiedAt:now,isLocked:!1,cohortId,createdAt:now,updatedAt:now}).returning())[0];if(!newUser)continue;let newUserId=String(newUser.id);if(created.push({id:newUserId,email:entry.email,password:entry.password}),roleIds&&roleIds.length>0&&rolesTable&&userRolesTable){let validIds=(await db.select({id:col7(rolesTable,"id")}).from(rolesTable).where(inArray6(col7(rolesTable,"id"),roleIds))).map((r)=>String(r.id));if(validIds.length>0)await db.insert(userRolesTable).values(validIds.map((roleId)=>({userId:newUserId,roleId})))}else{let cohortDefaultRoles=resolveDefaultRoleNames(config);if(cohortDefaultRoles.length>0)await assignDefaultRoles({db,userId:newUserId,roleNames:cohortDefaultRoles,rolesTable,userRolesTable,logger:logger2})}if((entry.firstName||entry.lastName)&&profilesTable)await db.insert(profilesTable).values({userId:newUserId,firstName:entry.firstName??null,lastName:entry.lastName??null,createdAt:now,updatedAt:now}).catch((err)=>{logger2.warn("[Cohort] Failed to create profile for user",{userId:newUserId,error:err.message})})}let countResult=await db.select({count:count()}).from(usersTable).where(eq21(col7(usersTable,"cohortId"),cohortId)),totalUsers=Number(countResult[0]?.count)||0;return await db.update(cohortsTable).set({userCount:totalUsers,updatedAt:new Date}).where(eq21(col7(cohortsTable,"id"),cohortId)),logger2.audit({entityName:"user_cohorts",entityId:cohortId,operation:"COHORT_BULK_CREATE",userId:callerId,summary:`Bulk created ${created.length} users in cohort (${skipped.length} skipped)`}),{success:!0,data:{created:created.length,skipped:skipped.length,skippedEmails:skipped,users:created}}}};var handleCreateCohort=(db,usersTable,cohortsTable,logger2)=>async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId||!await requireGodmin(db,usersTable,userId))return ctx.set.status=403,{success:!1,message:"Forbidden"};let{name:name2,description,expiresAt,metadata}=ctx.body,now=new Date,inserted=await db.insert(cohortsTable).values({name:name2,description:description??null,createdBy:userId,expiresAt:expiresAt?new Date(expiresAt):null,userCount:0,metadata:metadata??{},createdAt:now,updatedAt:now}).returning();return logger2.audit({entityName:"user_cohorts",entityId:inserted[0]?.id,operation:"COHORT_CREATE",userId,summary:`Created cohort "${name2}"`}),{success:!0,data:inserted[0]}};import{eq as eq22}from"drizzle-orm";var handleDeactivateUsers=(db,usersTable,logger2)=>async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId||!await requireGodmin(db,usersTable,userId))return ctx.set.status=403,{success:!1,message:"Forbidden"};let result=await db.update(usersTable).set({isLocked:!0,updatedAt:new Date}).where(eq22(col7(usersTable,"cohortId"),ctx.params.id)).returning();return logger2.audit({entityName:"user_cohorts",entityId:ctx.params.id,operation:"COHORT_DEACTIVATE_USERS",userId,summary:`Deactivated ${result.length} users in cohort`}),{success:!0,data:{affected:result.length}}};import{eq as eq23,inArray as inArray7}from"drizzle-orm";var handleDeleteUsers=(db,usersTable,cohortsTable,userRolesTable,profilesTable,logger2)=>async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId||!await requireGodmin(db,usersTable,userId))return ctx.set.status=403,{success:!1,message:"Forbidden"};let userIds=(await db.select({id:col7(usersTable,"id")}).from(usersTable).where(eq23(col7(usersTable,"cohortId"),ctx.params.id))).map((u)=>String(u.id));if(userIds.length>0){if(userRolesTable)await db.delete(userRolesTable).where(inArray7(col7(userRolesTable,"userId"),userIds));if(profilesTable)await db.delete(profilesTable).where(inArray7(col7(profilesTable,"userId"),userIds));await db.delete(usersTable).where(inArray7(col7(usersTable,"id"),userIds))}return await db.update(cohortsTable).set({userCount:0,updatedAt:new Date}).where(eq23(col7(cohortsTable,"id"),ctx.params.id)),logger2.audit({entityName:"user_cohorts",entityId:ctx.params.id,operation:"COHORT_DELETE_USERS",userId,summary:`Deleted ${userIds.length} users from cohort`}),{success:!0,data:{deleted:userIds.length}}};import{eq as eq24}from"drizzle-orm";var handleGetCohort=(db,usersTable,cohortsTable)=>async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId||!await requireGodmin(db,usersTable,userId))return ctx.set.status=403,{success:!1,message:"Forbidden"};let rows=await db.select().from(cohortsTable).where(eq24(col7(cohortsTable,"id"),ctx.params.id)).limit(1);if(rows.length===0)return ctx.set.status=404,{success:!1,message:"Cohort not found"};let userRows=await db.select().from(usersTable).where(eq24(col7(usersTable,"cohortId"),ctx.params.id));return{success:!0,data:{...rows[0],users:userRows}}};import{eq as eq25}from"drizzle-orm";var csvCell=(value)=>{let s=value==null?"":String(value);if(/^[=+\-@\t\r]/.test(s))s=`'${s}`;if(/[",\n\r]/.test(s))s=`"${s.replace(/"/g,'""')}"`;return s},handleExportUsers=(db,usersTable)=>async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId||!await requireGodmin(db,usersTable,userId))return ctx.set.status=403,{success:!1,message:"Forbidden"};let userRows=await db.select().from(usersTable).where(eq25(col7(usersTable,"cohortId"),ctx.params.id)),lines=["email,status,locked,created_at"];for(let row of userRows){let u=row;lines.push([csvCell(u.email),csvCell(u.isActive?"active":"inactive"),csvCell(u.isLocked?"yes":"no"),csvCell(u.createdAt)].join(","))}return ctx.set.headers["content-type"]="text/csv",ctx.set.headers["content-disposition"]=`attachment; filename="cohort-${ctx.params.id}-users.csv"`,lines.join(`
|
|
532
537
|
`)};var handleListCohorts=(db,usersTable,cohortsTable)=>async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId||!await requireGodmin(db,usersTable,userId))return ctx.set.status=403,{success:!1,message:"Forbidden"};let rows=await db.select().from(cohortsTable);return{success:!0,data:{items:rows,meta:{totalItems:rows.length}}}};import{eq as eq26}from"drizzle-orm";var handleDeleteCohort=(db,usersTable,cohortsTable,logger2)=>async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId||!await requireGodmin(db,usersTable,userId))return ctx.set.status=403,{success:!1,message:"Forbidden"};return await db.update(usersTable).set({cohortId:null,updatedAt:new Date}).where(eq26(col7(usersTable,"cohortId"),ctx.params.id)),await db.delete(cohortsTable).where(eq26(col7(cohortsTable,"id"),ctx.params.id)),logger2.audit({entityName:"user_cohorts",entityId:ctx.params.id,operation:"COHORT_DELETE",userId,summary:`Deleted cohort ${ctx.params.id}`}),{success:!0,data:null}};import{eq as eq27}from"drizzle-orm";var handleUpdateCohort=(db,usersTable,cohortsTable)=>async(ctx)=>{let userId=ctx.request.headers.get("x-user-id");if(!userId||!await requireGodmin(db,usersTable,userId))return ctx.set.status=403,{success:!1,message:"Forbidden"};let updates={updatedAt:new Date};if(ctx.body.name!==void 0)updates.name=ctx.body.name;if(ctx.body.description!==void 0)updates.description=ctx.body.description;if(ctx.body.expiresAt!==void 0)updates.expiresAt=ctx.body.expiresAt?new Date(ctx.body.expiresAt):null;if(ctx.body.metadata!==void 0)updates.metadata=ctx.body.metadata;if(ctx.body.isActive!==void 0)updates.isActive=ctx.body.isActive;let updated=await db.update(cohortsTable).set(updates).where(eq27(col7(cohortsTable,"id"),ctx.params.id)).returning();if(updated.length===0)return ctx.set.status=404,{success:!1,message:"Cohort not found"};return{success:!0,data:updated[0]}};import{t}from"elysia";var CohortBodySchema=t.Object({name:t.String({minLength:1,maxLength:255}),description:t.Optional(t.String()),expiresAt:t.Optional(t.String()),metadata:t.Optional(t.Record(t.String(),t.Unknown()))}),CohortUpdateSchema=t.Object({name:t.Optional(t.String({minLength:1,maxLength:255})),description:t.Optional(t.String()),expiresAt:t.Optional(t.Union([t.String(),t.Null()])),metadata:t.Optional(t.Record(t.String(),t.Unknown())),isActive:t.Optional(t.Boolean())}),BulkCreateUserItem=t.Object({email:t.String({format:"email"}),password:t.String({minLength:8}),profile:t.Optional(t.Object({firstName:t.Optional(t.String()),lastName:t.Optional(t.String())}))}),BulkCreateSchema=t.Object({users:t.Optional(t.Array(BulkCreateUserItem)),emailPrefix:t.Optional(t.String()),emailDomain:t.Optional(t.String()),sharedPassword:t.Optional(t.String({minLength:8})),count:t.Optional(t.Integer({minimum:1,maximum:500})),roleIds:t.Optional(t.Array(t.String()))});function createCohortRoutes(config){let{db,logger:logger2,cohortsTable,usersTable,userRolesTable,profilesTable,basePath}=config,routes=new Elysia2;if(!db||!cohortsTable||!usersTable)return logger2.warn("[Cohort] Skipped \u2014 missing tables",{hasDb:!!db,hasCohortsTable:!!cohortsTable,hasUsersTable:!!usersTable}),routes;return routes.get(basePath,handleListCohorts(db,usersTable,cohortsTable)),routes.get(`${basePath}/:id`,handleGetCohort(db,usersTable,cohortsTable)),routes.post(basePath,handleCreateCohort(db,usersTable,cohortsTable,logger2),{body:CohortBodySchema}),routes.patch(`${basePath}/:id`,handleUpdateCohort(db,usersTable,cohortsTable),{body:CohortUpdateSchema}),routes.delete(`${basePath}/:id`,handleDeleteCohort(db,usersTable,cohortsTable,logger2)),routes.post(`${basePath}/:id/bulk-create`,handleBulkCreateUsers(config,logger2),{body:BulkCreateSchema}),routes.post(`${basePath}/:id/deactivate-users`,handleDeactivateUsers(db,usersTable,logger2)),routes.post(`${basePath}/:id/activate-users`,handleActivateUsers(db,usersTable,logger2)),routes.post(`${basePath}/:id/delete-users`,handleDeleteUsers(db,usersTable,cohortsTable,userRolesTable,profilesTable,logger2)),routes.get(`${basePath}/:id/export`,handleExportUsers(db,usersTable)),routes}init_deviceInfo();function shouldNotifyDevice(question){if(question.isImpersonationLogin)return!1;if(!question.emailAvailable)return!1;if(question.requiresApproval)return!0;if(question.trustScore<question.lowTrustThreshold)return!0;return question.notifyOnNewDevice&&question.isNewDevice}import{Elysia as Elysia6}from"elysia";import{Elysia as Elysia3,t as t2}from"elysia";init_Authorization();function getUserId(request){return request.headers.get("x-user-id")}function isChatModerator(request,moderatorRoles){let roles=decodeHeaderList(request.headers.get("x-user-roles"));if(roles.includes(GODMIN_ROLE_NAME))return!0;if(moderatorRoles.length===0)return!1;let allowed=new Set(moderatorRoles.map((role)=>role.toLowerCase()));return roles.some((role)=>allowed.has(role.toLowerCase()))}function chatErrorStatus(code){switch(code){case"forbidden":return 403;case"not_found":return 404;case"validation":return 400;case"conflict":return 409;case"disabled":return 409;default:return 400}}async function guard(set,logger2,fn){try{return{success:!0,data:await fn()}}catch(err){if(err instanceof ChatError)return set.status=chatErrorStatus(err.code),{success:!1,message:err.message};return logger2.error("[Chat] Unhandled route error",{error:err instanceof Error?err.message:String(err)}),set.status=500,{success:!1,message:"Internal server error"}}}function unauthorized(set){return set.status=401,{success:!1,message:"Authentication required"}}function createConversationRoutes(deps){let{logger:logger2,getService}=deps,app=new Elysia3({prefix:deps.config.basePath});return app.get("/conversations",({request,query,set})=>{let userId=getUserId(request);if(!userId)return unauthorized(set);let{service}=getService(request);return guard(set,logger2,()=>service.listConversations(userId,{limit:query.limit?Number(query.limit):void 0,offset:query.offset?Number(query.offset):void 0}))},{query:t2.Object({limit:t2.Optional(t2.String()),offset:t2.Optional(t2.String())}),detail:{tags:["Chat"],summary:"List my conversations"}}),app.post("/conversations",({request,body,set})=>{let userId=getUserId(request);if(!userId)return unauthorized(set);let{service}=getService(request),input=body;return guard(set,logger2,()=>{if(input.type==="group"){if(!input.title)throw new ChatError("validation","A group title is required");return service.createGroup({creatorId:userId,title:input.title,description:input.description,avatarFileId:input.avatarFileId,participantIds:input.participantIds??[]})}if(!input.targetUserId)throw new ChatError("validation","targetUserId is required for a direct conversation");return service.getOrCreateDirect(userId,input.targetUserId)})},{body:t2.Object({type:t2.Optional(t2.Union([t2.Literal("direct"),t2.Literal("group")])),targetUserId:t2.Optional(t2.String()),title:t2.Optional(t2.String()),description:t2.Optional(t2.String()),avatarFileId:t2.Optional(t2.String()),participantIds:t2.Optional(t2.Array(t2.String()))}),detail:{tags:["Chat"],summary:"Create or open a conversation"}}),app.get("/conversations/:id",({request,params,set})=>{let userId=getUserId(request);if(!userId)return unauthorized(set);let{service}=getService(request);return guard(set,logger2,()=>service.getConversation(params.id,userId))},{params:t2.Object({id:t2.String()}),detail:{tags:["Chat"],summary:"Get a conversation"}}),app.post("/conversations/:id/participants",({request,params,body,set})=>{let userId=getUserId(request);if(!userId)return unauthorized(set);let{service}=getService(request),{userIds}=body;return guard(set,logger2,()=>service.addParticipants(params.id,userId,userIds))},{params:t2.Object({id:t2.String()}),body:t2.Object({userIds:t2.Array(t2.String())}),detail:{tags:["Chat"],summary:"Add group participants"}}),app.delete("/conversations/:id/participants/:userId",({request,params,set})=>{let userId=getUserId(request);if(!userId)return unauthorized(set);let{service}=getService(request);return guard(set,logger2,async()=>{return await service.removeParticipant(params.id,userId,params.userId),{removed:params.userId}})},{params:t2.Object({id:t2.String(),userId:t2.String()}),detail:{tags:["Chat"],summary:"Remove a participant / leave group"}}),app}import{Elysia as Elysia5,t as t4}from"elysia";init_storage2();var CONTENT_TYPE_SCHEMA=t4.Optional(t4.Union([t4.Literal("text"),t4.Literal("image"),t4.Literal("file"),t4.Literal("video"),t4.Literal("audio")]));function createMessageRoutes(deps){let{logger:logger2,getService}=deps,app=new Elysia5({prefix:deps.config.basePath});return app.get("/conversations/:id/messages",({request,params,query,set})=>{let userId=getUserId(request);if(!userId)return unauthorized(set);let{service}=getService(request);return guard(set,logger2,()=>service.getMessages({conversationId:params.id,userId,limit:query.limit?Number(query.limit):void 0,before:query.before||void 0}))},{params:t4.Object({id:t4.String()}),query:t4.Object({limit:t4.Optional(t4.String()),before:t4.Optional(t4.String())}),detail:{tags:["Chat"],summary:"Get conversation messages (newest first)"}}),app.post("/conversations/:id/messages",({request,params,body,set})=>{let userId=getUserId(request);if(!userId)return unauthorized(set);let{service}=getService(request),input=body;return guard(set,logger2,()=>service.sendMessage({conversationId:params.id,senderId:userId,content:input.content,contentType:input.contentType,replyToId:input.replyToId,clientMessageId:input.clientMessageId,attachments:input.attachmentIds?.map((fileId)=>({fileId})),metadata:input.metadata}))},{params:t4.Object({id:t4.String()}),body:t4.Object({content:t4.Optional(t4.String()),contentType:CONTENT_TYPE_SCHEMA,replyToId:t4.Optional(t4.String()),clientMessageId:t4.Optional(t4.String()),attachmentIds:t4.Optional(t4.Array(t4.String())),metadata:t4.Optional(t4.Any())}),detail:{tags:["Chat"],summary:"Send a message (link pre-uploaded attachments)"}}),app.post("/conversations/:id/messages/upload",({request,params,body,set})=>{let userId=getUserId(request);if(!userId)return unauthorized(set);if(!deps.attachmentsAvailable)return set.status=409,{success:!1,message:"File attachments require storage and CDN to be enabled"};let{service,schemaTables}=getService(request);return guard(set,logger2,async()=>{let filesTable=resolveSchemaTable(schemaTables,"files",logger2);if(!filesTable)throw new ChatError("disabled","Files table unavailable in this schema");let{data,files}=parseFormDataBody(body,deps.storageConfig);if(files.length===0)throw new ChatError("validation","At least one file is required");let{records,failed}=await persistUploadedFiles({db:deps.db,filesTable,files,storageConfig:deps.storageConfig,subFolder:"chat",userId});if(records.length===0)throw new ChatError("validation",failed[0]?.error??"File upload failed");if(deps.cdnMedia)scheduleUploadMediaProcessing(records,{storagePath:deps.storageConfig.basePath,media:deps.cdnMedia,logger:logger2});let content=typeof data.content==="string"?data.content:void 0,replyToId=typeof data.replyToId==="string"?data.replyToId:void 0,clientMessageId=typeof data.clientMessageId==="string"?data.clientMessageId:void 0;return service.sendMessage({conversationId:params.id,senderId:userId,content,replyToId,clientMessageId,attachments:records.map((record)=>({fileId:record.id,originalName:record.originalName,mimeType:record.mimeType,size:record.size}))})})},{type:"formdata",params:t4.Object({id:t4.String()}),body:t4.Object({[deps.storageConfig.formData.dataField]:t4.Optional(t4.Union([t4.String(),t4.Any()])),[deps.storageConfig.formData.filesField]:t4.Optional(t4.Union([t4.File(),t4.Array(t4.File())]))}),detail:{tags:["Chat"],summary:"Send a message with uploaded file attachments"}}),app.post("/conversations/:id/read",({request,params,body,set})=>{let userId=getUserId(request);if(!userId)return unauthorized(set);let{service}=getService(request),{messageId}=body;return guard(set,logger2,()=>service.markRead(params.id,userId,messageId))},{params:t4.Object({id:t4.String()}),body:t4.Object({messageId:t4.Optional(t4.String())}),detail:{tags:["Chat"],summary:"Mark a conversation as read"}}),app.post("/conversations/:id/typing",({request,params,body,set})=>{let userId=getUserId(request);if(!userId)return unauthorized(set);let{service}=getService(request),{isTyping}=body;return guard(set,logger2,async()=>{return await service.setTyping(params.id,userId,isTyping??!0),{ok:!0}})},{params:t4.Object({id:t4.String()}),body:t4.Object({isTyping:t4.Optional(t4.Boolean())}),detail:{tags:["Chat"],summary:"Broadcast a typing indicator"}}),app.patch("/messages/:id",({request,params,body,set})=>{let userId=getUserId(request);if(!userId)return unauthorized(set);let{service}=getService(request),{content}=body;return guard(set,logger2,()=>service.editMessage(params.id,userId,content))},{params:t4.Object({id:t4.String()}),body:t4.Object({content:t4.String()}),detail:{tags:["Chat"],summary:"Edit a message"}}),app.delete("/messages/:id",({request,params,set})=>{let userId=getUserId(request);if(!userId)return unauthorized(set);let{service}=getService(request),asModerator=isChatModerator(request,deps.config.moderatorRoles??[]);return guard(set,logger2,async()=>{if(await service.deleteMessage(params.id,userId,asModerator),asModerator)logger2.warn("[CHAT] Message deleted by a moderator",{actorId:userId,messageId:params.id});return{deleted:params.id}})},{params:t4.Object({id:t4.String()}),detail:{tags:["Chat"],summary:"Delete a message",description:"Sender-only, unless the caller is godmin or holds a role from chat.moderatorRoles \u2014 then any message, and `deletionEnabled` does not apply."}}),app}function createChatRoutes(routeConfig){let{db,schemaTables,config,logger:logger2,broadcaster,tenantRegistry,storageConfig,attachmentsAvailable,cdnBasePath,cdnMedia}=routeConfig,buildService=(tables)=>new ChatService({db,schemaTables:tables,config,logger:logger2,broadcaster,cdnBasePath,attachmentsAvailable}),defaultService=buildService(schemaTables),deps={db,config,logger:logger2,storageConfig,attachmentsAvailable,getService:(request)=>{if(!tenantRegistry)return{service:defaultService,schemaTables};let schemaName=request.headers.get("x-tenant-schema");if(!schemaName)return{service:defaultService,schemaTables};let ctx=tenantRegistry.getSchemaContext(schemaName);if(!ctx)return{service:defaultService,schemaTables};return{service:buildService(ctx.schemaTables),schemaTables:ctx.schemaTables}},cdnMedia},routes=new Elysia6;return routes.use(createConversationRoutes(deps)),routes.use(createMessageRoutes(deps)),logger2.info(`[Chat] Routes registered at ${config.basePath}`,{attachmentsAvailable,groupsEnabled:config.groupsEnabled}),{routes,chatService:defaultService}}init_Authorization();init_helpers3();import Elysia7,{t as t5}from"elysia";function createConfigRoutes(routeConfig){let{logger:logger2,resolvedOptions,configFilePath,basePath,onConfigUpdate,db,schemaTables,getRedis}=routeConfig,plugin=new Elysia7({prefix:basePath});return plugin.onBeforeHandle(async({request,set})=>{if(decodeHeaderList(request.headers.get("x-user-roles")).includes(GODMIN_ROLE_NAME))return;let userId=request.headers.get("x-user-id");if(userId&&db&&schemaTables.users)try{let{eq:eq28}=await import("drizzle-orm"),usersTable=schemaTables.users;if((await db.select().from(usersTable).where(eq28(usersTable.id,userId)).limit(1))[0]?.isGod===!0)return}catch(err){logger2.warn("[ConfigManagement] Failed to check isGod from DB",{error:err instanceof Error?err.message:String(err)})}return set.status=403,Response.json({isSuccess:!1,message:"Only godmin users can access config management",data:null})}),plugin.get("/",()=>{let configCopy=JSON.parse(JSON.stringify(resolvedOptions));return{isSuccess:!0,message:"Current running configuration",data:{config:maskSensitiveFields(configCopy),configFilePath,sections:buildSectionsMeta(resolvedOptions)}}},{detail:{tags:["Config Management"],summary:"Get full running configuration",description:"Returns the full running configuration with sensitive fields masked."}}),plugin.get("/sections",()=>({isSuccess:!0,message:"Config section metadata",data:{sections:buildSectionsMeta(resolvedOptions)}}),{detail:{tags:["Config Management"],summary:"List all config sections with metadata",description:"Section list is derived at runtime from the config object \u2014 no hardcoding."}}),plugin.get("/env",()=>{let configCopy=JSON.parse(JSON.stringify(resolvedOptions)),declared=scanEnvVars(configCopy),declaredNames=new Set(declared.map((e)=>e.envName)),undeclared=scanUndeclaredEnv(declaredNames),entries=[...declared,...undeclared],resolvedCount=entries.filter((e)=>e.resolved).length,missingCount=entries.length-resolvedCount,unrecognizedCount=undeclared.length;return{isSuccess:!0,message:`Found ${entries.length} env vars (${resolvedCount} resolved, ${missingCount} missing, ${unrecognizedCount} unrecognized)`,data:{entries,totalCount:entries.length,resolvedCount,missingCount,unrecognizedCount}}},{detail:{tags:["Config Management"],summary:"Get environment variables (declared + undeclared)",description:"Surfaces both (a) DECLARED env vars \u2014 UPPER_SNAKE_CASE references found in the config tree (recognized:true) \u2014 and (b) UNDECLARED env vars actually present in process.env but not declared (recognized:false), minus Kubernetes service-link and OS/interpreter infra noise, so orphaned / junk config surfaces for cleanup. Sensitive values are masked; AI-provider *_API_KEY vars are never surfaced."}}),plugin.get("/overrides",async()=>{let redis=getRedis();if(!redis)return{isSuccess:!0,message:"Redis not available \u2014 no overrides stored",data:{overrides:null,sectionCount:0,sections:[]}};let overrides=await readOverridesFromRedis(redis,resolvedOptions.appId||"nucleus"),sections=overrides?Object.keys(overrides).filter((k)=>{let v=overrides[k];return v!==void 0&&v!==null&&(typeof v!=="object"||Object.keys(v).length>0)}):[];return{isSuccess:!0,message:sections.length>0?`${sections.length} section override(s) stored in Redis`:"No overrides in Redis",data:{overrides:overrides?maskSensitiveFields(overrides):null,sectionCount:sections.length,sections}}},{detail:{tags:["Config Management"],summary:"View Redis config overrides",description:"Returns overrides stored in Redis that will be merged on next restart."}}),plugin.delete("/overrides",async()=>{let redis=getRedis();if(!redis)return{isSuccess:!1,message:"Redis not available",data:null};let existing=await readOverridesFromRedis(redis,resolvedOptions.appId||"nucleus"),clearedSections=existing?Object.keys(existing):[];return await clearOverridesFromRedis(redis,resolvedOptions.appId||"nucleus"),logger2.info("[ConfigManagement] Redis overrides cleared",{clearedSections}),{isSuccess:!0,message:clearedSections.length>0?`Cleared ${clearedSections.length} override(s) from Redis. Restart to revert to config.json defaults.`:"No overrides to clear.",data:{message:"Redis overrides cleared",clearedSections}}},{detail:{tags:["Config Management"],summary:"Clear all Redis config overrides",description:"Removes all stored overrides from Redis. Restart to revert to config.json defaults."}}),plugin.get("/:section",({params})=>{let{section}=params;if(!hasSection(resolvedOptions,section))return{isSuccess:!1,message:`Unknown config section: ${section}`,data:null};let sectionValue=extractSection(resolvedOptions,section),restart=isRestartRequired(section),maskedValue=sectionValue;if(typeof sectionValue==="object"&§ionValue!==null&&!Array.isArray(sectionValue))maskedValue=maskSensitiveFields({[section]:sectionValue})[section];return{isSuccess:!0,message:`Config section: ${section}`,data:{section,config:maskedValue??null,restartRequired:restart}}},{params:t5.Object({section:t5.String()}),detail:{tags:["Config Management"],summary:"Get a specific config section",description:"Returns a specific config section with sensitive fields masked."}}),plugin.patch("/:section",async({params,body})=>{let{section}=params,payload=body;if(!hasSection(resolvedOptions,section))return{isSuccess:!1,message:`Unknown config section: ${section}`,data:null};if(!payload.config||typeof payload.config!=="object")return{isSuccess:!1,message:'Request body must contain a "config" object',data:null};let restart=isRestartRequired(section),currentValue=extractSection(resolvedOptions,section),newValue;if(Array.isArray(currentValue))newValue=payload.config.value!==void 0?payload.config.value:payload.config;else if(typeof currentValue==="object"&¤tValue!==null)newValue=deepMerge(currentValue,payload.config);else if(currentValue===void 0||typeof currentValue==="string"||typeof currentValue==="number"||typeof currentValue==="boolean")newValue=payload.config.value!==void 0?payload.config.value:payload.config;else newValue=payload.config;if(applySectionUpdate(resolvedOptions,section,newValue),!restart)onConfigUpdate(section,newValue);let persistMethod="memory-only",persistWarning=null;if(configFilePath)try{await persistConfigToDisk(configFilePath,resolvedOptions),persistMethod="disk",logger2.info(`[ConfigManagement] Section "${section}" persisted to disk`)}catch(diskErr){let diskMsg=diskErr instanceof Error?diskErr.message:String(diskErr);logger2.warn(`[ConfigManagement] Disk persist failed: ${diskMsg}`);let redis=getRedis();if(redis)try{await persistSectionToRedis(redis,resolvedOptions.appId||"nucleus",section,newValue),persistMethod="redis",logger2.info(`[ConfigManagement] Section "${section}" persisted to Redis (disk unavailable)`)}catch(redisErr){let redisMsg=redisErr instanceof Error?redisErr.message:String(redisErr);logger2.error(`[ConfigManagement] Redis persist also failed: ${redisMsg}`),persistWarning=`Disk: ${diskMsg}. Redis: ${redisMsg}. Changes are in-memory only and will be lost on restart.`}else persistWarning=`Disk: ${diskMsg}. Redis not available. Changes are in-memory only and will be lost on restart.`}logger2.info(`[ConfigManagement] Section "${section}" updated (persist: ${persistMethod}, restart-required: ${restart})`);let updatedValue=extractSection(resolvedOptions,section),maskedUpdated=updatedValue;if(typeof updatedValue==="object"&&updatedValue!==null&&!Array.isArray(updatedValue))maskedUpdated=maskSensitiveFields({[section]:updatedValue})[section];let baseMsg=restart?`Config section "${section}" saved (${persistMethod}). Restart required for changes to take effect.`:`Config section "${section}" updated and applied (${persistMethod}).`;return{isSuccess:!0,message:persistWarning?`${baseMsg} Warning: ${persistWarning}`:baseMsg,data:{section,applied:!restart,restartRequired:restart,config:maskedUpdated}}},{params:t5.Object({section:t5.String()}),body:t5.Object({config:t5.Record(t5.String(),t5.Unknown())}),detail:{tags:["Config Management"],summary:"Update a config section",description:"Deep-merges the payload into the section. Hot-reloadable sections apply immediately. Restart-required sections are saved to disk only."}}),plugin.post("/restart",({body})=>{let delayMs=body.delayMs??1000;logger2.info(`[ConfigManagement] Restart scheduled in ${delayMs}ms`);let scheduledAt=new Date().toISOString();return setTimeout(()=>{logger2.info("[ConfigManagement] Restarting process..."),process.exit(0)},delayMs),{isSuccess:!0,message:`Server restart scheduled in ${delayMs}ms`,data:{message:`Process will exit in ${delayMs}ms. Orchestrator (K8s/PM2/systemd) will restart it.`,scheduledAt}}},{body:t5.Optional(t5.Object({delayMs:t5.Optional(t5.Number())})),detail:{tags:["Config Management"],summary:"Restart the server process",description:"Triggers a graceful process exit after a configurable delay. The orchestrator (K8s, PM2, systemd) is expected to restart the process automatically."}}),logger2.info(`[ConfigManagement] Routes enabled at ${basePath}`),plugin}init_adminGuard();import{Elysia as Elysia8,t as t6}from"elysia";var requireAuth=(ctx)=>ctx.request.headers.get("x-user-id"),fail=(ctx,status,message)=>{return ctx.set.status=status,{success:!1,message,data:null}},callerSchemaOf=(ctx)=>ctx.request.headers.get("x-tenant-schema"),isGodmin=(ctx)=>hasGodminRole(ctx.request),ownsHostname=(ctx,record)=>{if(isGodmin(ctx))return!0;let caller=callerSchemaOf(ctx);return record.schemaName!=null&&record.schemaName===caller};function createHostnameRoutes(config){let base=config.basePath,app=new Elysia8,svc=(ctx)=>{let s=config.getDomainService();if(!s)return ctx.set.status=503,null;return s};app.post(`${base}/hostnames`,async(ctx)=>{let service=svc(ctx);if(!service)return{success:!1,message:"Domains not available",data:null};if(!requireAuth(ctx))return fail(ctx,401,"Authentication required");let body=ctx.body,callerSchema=callerSchemaOf(ctx),schemaName=body.schemaName??null,tenantId=body.tenantId??null;if(!hasGodminRole(ctx.request)){if(schemaName&&schemaName!==callerSchema)return fail(ctx,403,"Cannot bind a hostname to another tenant's schema");schemaName=callerSchema;let ownTenantId=config.resolveTenantIdForSchema?.(callerSchema)??null;if(tenantId&&tenantId!==ownTenantId)return fail(ctx,403,"Cannot bind a hostname to another tenant");tenantId=ownTenantId}try{let result=await service.createHostname({hostname:body.hostname,ownerId:body.ownerId,ownerType:body.ownerType,tenantId,schemaName,isPrimary:body.isPrimary});return{success:!0,message:"Custom hostname created",data:{hostname:result.hostname,instructions:result.instructions}}}catch(err){return fail(ctx,400,err instanceof Error?err.message:"Failed to create hostname")}},{body:t6.Object({hostname:t6.String(),ownerId:t6.String(),ownerType:t6.Optional(t6.Union([t6.Literal("tenant"),t6.Literal("organization"),t6.Literal("user"),t6.Literal("external")])),tenantId:t6.Optional(t6.String()),schemaName:t6.Optional(t6.String()),isPrimary:t6.Optional(t6.Boolean())}),detail:{tags:["Domains"],summary:"Create custom hostname"}}),app.get(`${base}/hostnames`,async(ctx)=>{let service=svc(ctx);if(!service)return{success:!1,message:"Domains not available",data:null};if(!requireAuth(ctx))return fail(ctx,401,"Authentication required");let url=new URL(ctx.request.url),items;if(isGodmin(ctx))items=await service.listHostnames({ownerId:url.searchParams.get("ownerId")??void 0,tenantId:url.searchParams.get("tenantId")??void 0});else{let ownTenantId=config.resolveTenantIdForSchema?.(callerSchemaOf(ctx))??null;items=ownTenantId?await service.listHostnames({tenantId:ownTenantId}):[]}return{success:!0,message:`Found ${items.length} hostnames`,data:{items}}}),app.get(`${base}/hostnames/:id`,async(ctx)=>{let service=svc(ctx);if(!service)return{success:!1,message:"Domains not available",data:null};if(!requireAuth(ctx))return fail(ctx,401,"Authentication required");let record=await service.getHostname(ctx.params.id);if(!record||!ownsHostname(ctx,record))return fail(ctx,404,"Hostname not found");return{success:!0,message:"Hostname found",data:record}}),app.get(`${base}/hostnames/:id/instructions`,async(ctx)=>{let service=svc(ctx);if(!service)return{success:!1,message:"Domains not available",data:null};if(!requireAuth(ctx))return fail(ctx,401,"Authentication required");let id=ctx.params.id,record=await service.getHostname(id);if(!record||!ownsHostname(ctx,record))return fail(ctx,404,"Hostname not found");return{success:!0,message:"DNS instructions",data:{instructions:await service.getInstructions(id)}}});let lifecycle=(suffix,run,summary)=>{app.post(`${base}/hostnames/:id/${suffix}`,async(ctx)=>{let service=svc(ctx);if(!service)return{success:!1,message:"Domains not available",data:null};if(!requireAuth(ctx))return fail(ctx,401,"Authentication required");let id=ctx.params.id,record=await service.getHostname(id);if(!record||!ownsHostname(ctx,record))return fail(ctx,404,"Hostname not found");try{let data=await run(service,id);if(!data)return fail(ctx,404,"Hostname not found");return{success:!0,message:summary,data}}catch(err){return fail(ctx,400,err instanceof Error?err.message:summary)}})};return lifecycle("verify",(s,id)=>s.verifyHostname(id),"Verification processed"),lifecycle("activate",(s,id)=>s.activateHostname(id),"Hostname activated"),lifecycle("disable",(s,id)=>s.disableHostname(id),"Hostname disabled"),lifecycle("make-primary",(s,id)=>s.makePrimary(id),"Primary hostname set"),lifecycle("refresh-status",(s,id)=>s.refreshStatus(id),"Status refreshed"),app}init_adminGuard();import{Elysia as Elysia9,t as t7}from"elysia";var requireAuth2=(ctx)=>ctx.request.headers.get("x-user-id"),fail2=(ctx,status,message)=>{return ctx.set.status=status,{success:!1,message,data:null}},callerSchemaOf2=(ctx)=>ctx.request.headers.get("x-tenant-schema"),isGodmin2=(ctx)=>hasGodminRole(ctx.request);function createRegistrationRoutes(config){let base=config.basePath,app=new Elysia9,svc=(ctx)=>{let s=config.getRegistrationService();if(!s)return ctx.set.status=503,null;return s},ownTenantId=(ctx)=>config.resolveTenantIdForSchema?.(callerSchemaOf2(ctx))??null,ownsRegistration=(ctx,record)=>{if(isGodmin2(ctx))return!0;let own=ownTenantId(ctx);return record.tenantId!=null&&own!=null&&record.tenantId===own};return app.post(`${base}/registrations`,async(ctx)=>{let service=svc(ctx);if(!service)return{success:!1,message:"Domains not available",data:null};if(!requireAuth2(ctx))return fail2(ctx,401,"Authentication required");let body=ctx.body,tenantId=body.tenantId??null,registrantOwnerType=body.registrantOwnerType;if(!isGodmin2(ctx)){let own=ownTenantId(ctx);if(tenantId&&tenantId!==own)return fail2(ctx,403,"Cannot register a domain for another tenant");if(tenantId=own,registrantOwnerType==="platform")return fail2(ctx,403,"Only a platform admin may register as 'platform'");registrantOwnerType="customer"}try{return{success:!0,message:"Registration requested",data:await service.createRequest({requestedDomain:body.requestedDomain,ownerId:body.ownerId,ownerType:body.ownerType,tenantId,registrantOwnerType,termsVersion:body.termsVersion,termsAccepted:body.termsAccepted,autoRenew:body.autoRenew})}}catch(err){return fail2(ctx,400,err instanceof Error?err.message:"Failed to request registration")}},{body:t7.Object({requestedDomain:t7.String(),ownerId:t7.String(),ownerType:t7.Optional(t7.Union([t7.Literal("tenant"),t7.Literal("organization"),t7.Literal("user"),t7.Literal("external")])),tenantId:t7.Optional(t7.String()),registrantOwnerType:t7.Optional(t7.Union([t7.Literal("customer"),t7.Literal("platform")])),termsVersion:t7.String(),termsAccepted:t7.Boolean(),autoRenew:t7.Optional(t7.Boolean())}),detail:{tags:["Domains"],summary:"Request managed domain registration"}}),app.get(`${base}/registrations`,async(ctx)=>{let service=svc(ctx);if(!service)return{success:!1,message:"Domains not available",data:null};if(!requireAuth2(ctx))return fail2(ctx,401,"Authentication required");let url=new URL(ctx.request.url),items;if(isGodmin2(ctx))items=await service.listRegistrations({ownerId:url.searchParams.get("ownerId")??void 0,tenantId:url.searchParams.get("tenantId")??void 0});else{let own=ownTenantId(ctx);items=own?await service.listRegistrations({tenantId:own}):[]}return{success:!0,message:`Found ${items.length} registrations`,data:{items}}}),app.get(`${base}/registrations/:id`,async(ctx)=>{let service=svc(ctx);if(!service)return{success:!1,message:"Domains not available",data:null};if(!requireAuth2(ctx))return fail2(ctx,401,"Authentication required");let record=await service.getRegistration(ctx.params.id);if(!record||!ownsRegistration(ctx,record))return fail2(ctx,404,"Registration not found");return{success:!0,message:"Registration found",data:record}}),app.post(`${base}/registrations/:id/cancel`,async(ctx)=>{let service=svc(ctx);if(!service)return{success:!1,message:"Domains not available",data:null};if(!requireAuth2(ctx))return fail2(ctx,401,"Authentication required");let id=ctx.params.id,record=await service.getRegistration(id);if(!record||!ownsRegistration(ctx,record))return fail2(ctx,404,"Registration not found");let cancelled=await service.cancel(id);if(!cancelled)return fail2(ctx,404,"Registration not found");return{success:!0,message:"Registration cancelled",data:cancelled}}),app.post(`${base}/registrations/:id/transfer-out`,async(ctx)=>{let service=svc(ctx);if(!service)return{success:!1,message:"Domains not available",data:null};if(!requireAuth2(ctx))return fail2(ctx,401,"Authentication required");let id=ctx.params.id,record=await service.getRegistration(id);if(!record||!ownsRegistration(ctx,record))return fail2(ctx,404,"Registration not found");let out=await service.requestTransferOut(id);if(!out)return fail2(ctx,404,"Registration not found");return{success:!0,message:"Transfer-out requested",data:out}}),app}import{Elysia as Elysia10}from"elysia";function createResolveRoute(config){let base=config.basePath,app=new Elysia10;return app.get(`${base}/resolve`,async(ctx)=>{let service=config.getDomainService();if(!service)return ctx.set.status=503,{success:!1,message:"Domains not available",data:null};let hostname=new URL(ctx.request.url).searchParams.get("hostname")||ctx.request.headers.get("host")||"";if(!hostname)return ctx.set.status=400,{success:!1,message:"hostname is required",data:null};let match=await service.resolveHostname(hostname);if(!match)return ctx.set.status=404,{success:!1,message:"No active hostname matched",data:null};return{success:!0,message:"Resolved",data:match}},{detail:{tags:["Domains"],summary:"Resolve hostname to tenant",description:"Public."}}),app}function createDomainRoutes(app,config){return app.use(createResolveRoute(config)),app.use(createHostnameRoutes(config)),app.use(createRegistrationRoutes(config)),app}import{and as and13,arrayContains,arrayOverlaps,asc,createTableRelationsHelpers,desc as desc5,eq as eq28,getTableName,gt,gte,ilike,inArray as inArray9,isNotNull,isNull as isNull2,like,lt as lt2,lte,ne as ne2,notInArray,or as or2,sql as sql7}from"drizzle-orm";import{drizzle}from"drizzle-orm/node-postgres";import{Elysia as Elysia11,t as t9}from"elysia";import{inArray as inArray8}from"drizzle-orm";function accountLinkFor(links,table){if(!links?.length||!table)return null;let byTable={};for(let link of links)if(link?.table)byTable[link.table]=link;return pickByName(byTable,table)??null}function accountIdsIn(rows,userColumn){if(!userColumn)return[];let ids=new Set;for(let row of rows){let value=pickByName(row,userColumn),id=String(value??"").trim();if(id)ids.add(id)}return[...ids]}async function closeAccounts(deps,userIds){let ids=[...new Set(userIds.map((id)=>String(id??"").trim()).filter(Boolean))];if(ids.length===0||!deps.usersTable)return{closed:0,signedOut:!0,closedIds:[]};let idColumn=pickByName(deps.usersTable,"id"),activeColumn=pickByName(deps.usersTable,"is_active");if(!idColumn||!activeColumn)return{closed:0,signedOut:!1,closedIds:[]};try{await deps.db.update(deps.usersTable).set({isActive:!1}).where(inArray8(idColumn,ids))}catch(error){if(deps.onError?.(error),deps.atomic)throw error;return{closed:0,signedOut:!1,closedIds:[]}}let sessionUser=deps.sessionsTable?pickByName(deps.sessionsTable,"user_id"):void 0;if(!deps.sessionsTable||!sessionUser)return{closed:ids.length,signedOut:!1,closedIds:ids};try{return await deps.db.delete(deps.sessionsTable).where(inArray8(sessionUser,ids)),{closed:ids.length,signedOut:!0,closedIds:ids}}catch(error){if(deps.onError?.(error),deps.atomic)throw error;return{closed:ids.length,signedOut:!1,closedIds:ids}}}init_Authorization();init_utils5();function decideRoleAssign(params){let{callerIsGod,callerRoleNames,allowRoles,targetRoleName,subjectIsGodmin,godminRoleName}=params,callerIsGodmin=callerIsGod||callerRoleNames.includes(godminRoleName);if(!(callerIsGodmin||callerRoleNames.some((name2)=>allowRoles.includes(name2))))return{allowed:!1,status:403,reason:"not_privileged"};if(targetRoleName===godminRoleName&&!callerIsGodmin)return{allowed:!1,status:403,reason:"godmin_assignment_forbidden"};if(subjectIsGodmin&&!callerIsGodmin)return{allowed:!1,status:403,reason:"target_is_godmin"};return{allowed:!0,callerIsGodmin}}var ROLE_ASSIGN_REFUSALS={not_privileged:"Rol atamak i\xE7in yetkiniz yok.",godmin_assignment_forbidden:"Bu rol\xFC yaln\u0131zca sistem y\xF6neticisi verebilir.",target_is_godmin:"Bu ki\u015Finin rolleri yaln\u0131zca sistem y\xF6neticisi taraf\u0131ndan de\u011Fi\u015Ftirilebilir."};init_adminGuard();init_sensitiveColumns();var snakeToCamel2=(s)=>s.replace(/_([a-z])/g,(_,l)=>l.toUpperCase()),SENSITIVE_SYSTEM_TABLE_SNAKE=["domain_hostnames","domain_registrations","domain_provider_records","domain_verification_challenges","domain_events","payment_sub_merchants","payment_invoices","payment_subscriptions","payment_customers","payment_transactions","payment_methods","payment_products","payment_prices","payment_commission_splits","payment_splits","payment_reserves","payment_ledger_entries","payment_payout_requests","payment_settlement_policies","payment_disputes","payment_webhook_logs","verifications","api_keys","magic_link_tokens","user_sessions","trusted_devices","integration_sources","integration_endpoints","integration_mappings"],SENSITIVE_SYSTEM_TABLES=new Set(SENSITIVE_SYSTEM_TABLE_SNAKE.flatMap((name2)=>[name2,snakeToCamel2(name2)]));function isSensitiveSystemTable(tableName){return SENSITIVE_SYSTEM_TABLES.has(tableName)}function delegatedWriteRoles(question){if(question.isRbacTable)return new Set;let roles=(question.featureSet??[]).flatMap((feature)=>question.featureAdminRoles?.[feature]??[]);return new Set(roles.map((role)=>role.toLowerCase()))}function isFeatureAdmin(question){let allowed=delegatedWriteRoles(question);if(allowed.size===0)return!1;return question.callerRoles.some((role)=>allowed.has(role.toLowerCase()))}init_storage2();function isAnonymousCreate(table,payload){let rule=table.anonymous_create;if(!rule)return!1;if(rule===!0)return!0;let column=rule.column;if(!column)return!1;let value=payload[column]??payload[toCamelCase3(column)]??payload[toSnakeCase2(column)];return isTruthy(value)}function isTruthy(value){if(typeof value==="boolean")return value;if(typeof value==="number")return value!==0;if(typeof value==="string"){let normalized=value.trim().toLowerCase();return normalized==="true"||normalized==="1"||normalized==="yes"||normalized==="on"}return!1}function createAuditIdentity(anonymous,userId,headers){if(anonymous)return{userId:void 0,ipAddress:"anonymous",userAgent:"anonymous"};return{userId:userId||void 0,ipAddress:headers.get("x-forwarded-for")?.split(",")[0]?.trim()||headers.get("x-real-ip")?.trim()||"unknown",userAgent:headers.get("user-agent")||"unknown"}}function toCamelCase3(value){return value.replace(/_([a-z0-9])/g,(_m,c)=>c.toUpperCase())}function toSnakeCase2(value){return value.replace(/[A-Z]/g,(c)=>`_${c.toLowerCase()}`)}var snakeToCamel3=(s)=>s.replace(/_([a-z])/g,(_,l)=>l.toUpperCase());function forceCreateScope(payload,authResult,resolveColumn){let scopeFilters=authResult?.scopeFilters;if(!scopeFilters)return{ok:!0};for(let[field,value]of Object.entries(scopeFilters)){if(!resolveColumn(field))return{ok:!1,field};payload[snakeToCamel3(field)]=value}return{ok:!0}}function decideRelationExpansion(params){let{authEnabled,targetTable,relAuth,isTargetPublicGet}=params;if(!authEnabled||!targetTable)return{expand:!0};if(relAuth===null)return isTargetPublicGet?{expand:!0}:{expand:!1};if(!relAuth.authorized)return{expand:!1};let scope=relAuth.scopeFilters;if(scope&&Object.keys(scope).length>0)return{expand:!0,scope};return{expand:!0}}function resolveRelationScopeColumn(fields,key2,toCamel5){if(Object.hasOwn(fields,key2))return fields[key2];let camel=toCamel5(key2);return Object.hasOwn(fields,camel)?fields[camel]:void 0}init_Authorization();init_types3();function targetFromBody(body){let record=body??{},read=(...keys)=>{for(let key2 of keys){let value=record[key2];if(typeof value==="string"&&value.length>0)return value}return null};return{userId:read("userId","user_id"),roleId:read("roleId","role_id")}}async function readRow(db,userRolesTable,rowId,logger2){try{let{eq:eq28}=await import("drizzle-orm"),columns=userRolesTable,row=(await db.select().from(userRolesTable).where(eq28(columns.id,rowId)).limit(1))[0];if(!row)return{userId:null,roleId:null};let text=(value)=>typeof value==="string"&&value.length>0?value:null;return{userId:text(row.userId??row.user_id),roleId:text(row.roleId??row.role_id)}}catch(err){return logger2.warn("[UserRoleWrite] Failed to read the user_roles row",{error:err instanceof Error?err.message:String(err)}),{userId:null,roleId:null}}}async function roleNameOf(db,rolesTable,roleId,logger2){try{let{eq:eq28}=await import("drizzle-orm"),columns=rolesTable,name2=(await db.select({name:columns.name}).from(rolesTable).where(eq28(columns.id,roleId)).limit(1))[0]?.name;return typeof name2==="string"&&name2.length>0?name2:null}catch(err){return logger2.warn("[UserRoleWrite] Failed to read the role name",{error:err instanceof Error?err.message:String(err)}),null}}async function isGodmin3(db,userRolesTable,rolesTable,userId,logger2){try{let{eq:eq28}=await import("drizzle-orm"),ur=userRolesTable,r=rolesTable;return(await db.select({roleName:r.name}).from(userRolesTable).innerJoin(rolesTable,eq28(ur.roleId,r.id)).where(eq28(ur.userId,userId))).some((row)=>isGodminRole(String(row.roleName??"")))}catch(err){return logger2.warn("[UserRoleWrite] Failed to check whether the subject is a godmin",{error:err instanceof Error?err.message:String(err)}),!0}}async function resolveUserRoleSubject(deps,write){let{db,schemaTables,logger:logger2}=deps,userRolesTable=schemaTables[AUTHORIZATION_TABLE_KEYS.userRoles],rolesTable=schemaTables[AUTHORIZATION_TABLE_KEYS.roles];if(!db||!userRolesTable||!rolesTable)return{targetRoleName:null,subjectIsGodmin:!0};let fromBody=targetFromBody(write.body),fromRow=write.rowId?await readRow(db,userRolesTable,write.rowId,logger2):{userId:null,roleId:null},roleIds=[fromRow.roleId,fromBody.roleId].filter((id)=>Boolean(id)),userIds=[fromRow.userId,fromBody.userId].filter((id)=>Boolean(id));if(roleIds.length===0||userIds.length===0)return{targetRoleName:null,subjectIsGodmin:!0};let names2=await Promise.all(roleIds.map((id)=>roleNameOf(db,rolesTable,id,logger2)));if(names2.some((name2)=>name2===null))return{targetRoleName:null,subjectIsGodmin:!0};let readable=names2.filter((name2)=>name2!==null),targetRoleName=readable.find((name2)=>isGodminRole(name2))??readable[0]??null,godminFlags=await Promise.all(userIds.map((id)=>isGodmin3(db,userRolesTable,rolesTable,id,logger2)));return{targetRoleName,subjectIsGodmin:godminFlags.some(Boolean)}}import{t as t8}from"elysia";function buildBodySchemaFromEntityColumns(entityColumns){let properties={};if(!entityColumns||entityColumns.length===0)return t8.Object({},{additionalProperties:!0});for(let col8 of entityColumns)switch(col8.type?.toLowerCase()||"string"){case"integer":case"int":case"serial":case"bigserial":case"numeric":case"decimal":properties[col8.name]=col8.notNull?t8.Number():t8.Optional(t8.Number());break;case"boolean":properties[col8.name]=col8.notNull?t8.Boolean():t8.Optional(t8.Boolean());break;case"timestamp":case"timestamptz":case"date":properties[col8.name]=col8.notNull?t8.String({format:"date-time"}):t8.Optional(t8.String({format:"date-time"}));break;case"json":case"jsonb":properties[col8.name]=t8.Optional(t8.Unknown());break;case"uuid":properties[col8.name]=col8.notNull?t8.String({format:"uuid"}):t8.Optional(t8.String({format:"uuid"}));break;default:properties[col8.name]=col8.notNull?t8.String():t8.Optional(t8.String())}return t8.Object(properties,{additionalProperties:!0})}function createBulkUpdateSchema(entityColumns){return t8.Array(t8.Object({id:t8.String(),data:t8.Partial(buildBodySchemaFromEntityColumns(entityColumns))}))}var MAX_BULK_ITEMS=500;function collectFilterFields(filter,out=[]){if(filter.operator==="or"||filter.operator==="and"){let group=Array.isArray(filter.value)?filter.value:[];for(let f of group)collectFilterFields(f,out)}else if(filter.field)out.push(String(filter.field));return out}function firstUnknownField(fields,resolveCol){for(let field of fields){let trimmed=field.trim();if(trimmed!==""&&!resolveCol(trimmed))return trimmed}return null}function buildFilterCondition(filter,resolveCol){if(filter.operator==="or"||filter.operator==="and"){let subs=(Array.isArray(filter.value)?filter.value:[]).map((f)=>buildFilterCondition(f,resolveCol)).filter((c)=>c!==null);if(subs.length===0)return null;return(filter.operator==="or"?or2(...subs):and13(...subs))??null}if(!filter.field)return null;let col8=resolveCol(filter.field);if(!col8)return null;let sqlCol=col8,dataType=col8.dataType,coerce2=(v)=>dataType==="date"&&(typeof v==="string"||typeof v==="number")?new Date(v):v;switch(filter.operator){case"eq":return eq28(sqlCol,coerce2(filter.value));case"neq":return ne2(sqlCol,coerce2(filter.value));case"gt":return gt(sqlCol,coerce2(filter.value));case"gte":return gte(sqlCol,coerce2(filter.value));case"lt":return lt2(sqlCol,coerce2(filter.value));case"lte":return lte(sqlCol,coerce2(filter.value));case"like":return like(sqlCol,filter.value);case"ilike":return ilike(sqlCol,filter.value);case"in":return inArray9(sqlCol,filter.value);case"notIn":return notInArray(sqlCol,filter.value);case"arrayOverlaps":return arrayOverlaps(sqlCol,filter.value??[]);case"arrayContains":return arrayContains(sqlCol,filter.value??[]);case"arrayEmpty":return sql7`cardinality(${sqlCol}) = 0`;case"isNull":return isNull2(sqlCol);case"isNotNull":return isNotNull(sqlCol);default:return null}}function createEntityRoutes(app,config){let{db,schemaTables,schemaRelations,entities,logger:logger2,dbPool,storage,cdnMedia,authorization,authMode,idpUrl,featureAdminRoles}=config,getRegistry=()=>config.getTenantRegistry?config.getTenantRegistry():config.tenantRegistry??null,getReqSchema=(request)=>{let tenantRegistry=getRegistry();if(!tenantRegistry)return{tables:schemaTables,relations:schemaRelations};let schemaName=request.headers.get("x-tenant-schema");if(!schemaName)return{tables:schemaTables,relations:schemaRelations};let ctx=tenantRegistry.getSchemaContext(schemaName);return ctx?{tables:ctx.schemaTables,relations:ctx.schemaRelations}:{tables:schemaTables,relations:schemaRelations}},storageConfig=mergeStorageConfig(storage),warmUploadedMedia=(uploaded)=>{if(!cdnMedia||!uploaded||uploaded.success.length===0)return;scheduleUploadMediaProcessing(uploaded.success,{storagePath:storageConfig.basePath,media:cdnMedia,logger:logger2})},authEnabled=authorization?.enabled??!1,enforceFieldWrites=authEnabled&&authorization?.enforceFieldWriteClaims!==!1,isConsumerMode=authMode==="consumer",filterWritePayload=(payload,authResult)=>{if(!enforceFieldWrites||!authResult?.allowedFields)return payload;return filterResponseFields(payload,authResult.allowedFields)},auditPathContext=(request)=>{let url=new URL(request.url);return{path:url.pathname,query:url.search}},auditIdentityFor=(table,payload,userId,headers)=>createAuditIdentity(isAnonymousCreate(table,payload),userId,headers),UUID_RE=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,auditEntityId=(id)=>{let s=id==null?"":String(id);return UUID_RE.test(s)?s:null},projectWrittenRow=(row,authResult)=>{let scoped2=authEnabled&&authResult?.allowedFields?filterResponseFields(row,[...authResult.allowedFields,...authResult.allowedRelations??[]]):row;return stripUnclaimedSensitive(redactSensitiveOutput(scoped2),authResult?.allowedFields)};if(!db)return app;function snakeToCamel4(s){return s.replace(/_([a-z])/g,(_,l)=>l.toUpperCase())}let{entities:mergedEntities}=resolveEntities(SYSTEM_TABLES,entities),extendedByName=new Map(mergedEntities.filter((t10)=>entities.some((e)=>e.table_name===t10.table_name&&e.extends===!0)).map((t10)=>[t10.table_name,t10])),effectiveEntities=entities.map((e)=>extendedByName.get(e.table_name)??e),allTables=Object.keys(schemaTables),entityTableNames=effectiveEntities.map((e)=>snakeToCamel4(e.table_name)),systemTableNames=allTables.filter((tbl)=>!entityTableNames.includes(tbl)),systemTableDefMap=new Map(SYSTEM_TABLES.map((t10)=>[snakeToCamel4(t10.table_name),t10])),asMeta=(def)=>def??void 0,hasUnmetRequirement=(def)=>{let requires=def?.requires;if(!requires||requires.length===0)return null;for(let req of requires)if(req==="email"&&!config.isEmailServiceAvailable?.())return"email";return null},deriveGroupName=(def,fallback)=>{if(def?.group_name)return def.group_name;let primaryFeature=def?.feature_set?.[0];if(!primaryFeature)return fallback;return primaryFeature.charAt(0).toUpperCase()+primaryFeature.slice(1)},systemTables2=systemTableNames.filter((name2)=>{let unmet=hasUnmetRequirement(asMeta(systemTableDefMap.get(name2)));if(unmet)return logger2.info(`Skipping ${name2} routes - missing required dependency: ${unmet}`),!1;return!0}).map((name2)=>{let def=systemTableDefMap.get(name2),meta=asMeta(def);return{table_name:def?.table_name??name2,group_name:deriveGroupName(meta,name2),is_form_data:def?.is_form_data===!0,bulk_endpoints_enabled:def?.bulk_endpoints_enabled??!1,excluded_methods:def?.excluded_methods?[...def.excluded_methods]:[],columns:def?.columns?[...def.columns]:void 0}}),allEntities=[...effectiveEntities,...systemTables2],publicGetEntities=new Set;for(let e of allEntities)if(e.is_public?.GET===!0)publicGetEntities.add(e.table_name),publicGetEntities.add(snakeToCamel4(e.table_name));logger2.info(`All entities: ${allEntities.map((e)=>e.table_name).join(", ")}`);for(let table of allEntities){let rawTableName=table.table_name,tableName=snakeToCamel4(rawTableName),swaggerTag=table.group_name||rawTableName,writeFields=enforceFieldWrites?table.columns?.map((c)=>c.name):void 0,defaultDrizzleTable=schemaTables[tableName];if(!defaultDrizzleTable)continue;let tableRelations=schemaRelations[`${tableName}Relations`];logger2.info(`Creating routes for table: ${tableName}`);let relationTargetTable={};{let rels=tableRelations;if(rels?.table&&typeof rels?.config==="function")try{let built=rels.config(createTableRelationsHelpers(rels.table));for(let[relName,rel]of Object.entries(built))if(rel?.referencedTable)relationTargetTable[relName]=getTableName(rel.referencedTable)}catch(err){logger2.warn(`[Authorization] Could not map relations for ${tableName}`,{error:err instanceof Error?err.message:String(err)})}}let defaultTableColumns=defaultDrizzleTable,defaultIdCol=defaultTableColumns.id,database=db,drizzleTable=defaultDrizzleTable,tableColumns=defaultTableColumns,idCol=defaultIdCol,resolveCol=(field)=>{if(Object.hasOwn(tableColumns,field))return tableColumns[field];let camel=snakeToCamel4(field);return Object.hasOwn(tableColumns,camel)?tableColumns[camel]:void 0},getTableForRequest=(request)=>{if(!getRegistry())return{drizzleTable,tableColumns,idCol,resolveCol,schemaTables,schemaRelations};let reqSchema=getReqSchema(request),reqTable=reqSchema.tables[tableName]||drizzleTable,reqCols=reqTable,reqIdCol=reqCols.id;return{drizzleTable:reqTable,tableColumns:reqCols,idCol:reqIdCol,resolveCol:(field)=>{if(Object.hasOwn(reqCols,field))return reqCols[field];let camel=snakeToCamel4(field);return Object.hasOwn(reqCols,camel)?reqCols[camel]:void 0},schemaTables:reqSchema.tables,schemaRelations:reqSchema.relations}},bulkUpdateSchema=createBulkUpdateSchema(table.columns),bulkDeleteSchema=t9.Array(t9.String()),authzLog=logger2.scoped("authorization.check"),performAuthCheck=async(request,method,reqFields,reqRelations)=>{let result=await runAuthCheck(request,method,reqFields,reqRelations);if(result){let userId=request.headers.get("x-user-id"),requestId=request.headers.get("x-request-id")||void 0;if(!result.authorized)authzLog.warn(`Denied ${method} ${table.table_name}`,{requestId,userId,entity:table.table_name,method,reason:result.reason||"no reason provided",mode:isConsumerMode?idpUrl?"idp":"jwt":"local"});else if(result.scopeFilters||result.allowedFields||result.allowedRelations)authzLog.debug(`Allowed ${method} ${table.table_name} (restricted)`,{requestId,userId,entity:table.table_name,method,scopeFilters:result.scopeFilters,allowedFieldCount:result.allowedFields?.length,allowedRelations:result.allowedRelations})}return result},scopeConditionsFor=(authResult,resolveColumn)=>{if(!authEnabled||!authResult?.scopeFilters)return[];let{conditions,unresolvedFields}=buildScopeConditions(authResult.scopeFilters,resolveColumn);if(unresolvedFields.length>0)authzLog.error(`Scope references unknown column(s) on ${table.table_name}; failing closed (0 rows)`,{entity:table.table_name,unresolvedFields});return conditions},runAuthCheck=async(request,method,reqFields,reqRelations,entityName=table.table_name)=>{let userId=request.headers.get("x-user-id");if(!authEnabled||!userId)return null;if(isConsumerMode){let userClaims=decodeHeaderList(request.headers.get("x-user-claims")),userRoles=decodeHeaderList(request.headers.get("x-user-roles")),userClaimScopes=decodeClaimScopesHeader(request.headers.get("x-user-claim-scopes"));if(idpUrl&&authorization?.jwtClaimsMode==="resolve"){let accessToken=request.headers.get("x-access-token")||(request.headers.get("cookie")||"").match(/access_token=([^;]+)/)?.[1]||"";return checkAuthorizationViaIDP({idpUrl,accessToken,method,entity:entityName,requestedFields:reqFields,requestedRelations:reqRelations,logger:logger2})}return checkAuthorizationFromJWT({userClaims,userRoles,method,entity:entityName,requestedFields:reqFields,requestedRelations:reqRelations,logger:logger2,requireClaimSpecificity:authorization?.requireClaimSpecificity,claimScopes:userClaimScopes})}let reqCtx=getTableForRequest(request);return checkAuthorization({userId,method,entity:entityName,requestedFields:reqFields,requestedRelations:reqRelations,db:database,schemaTables:reqCtx.schemaTables,logger:logger2,requireClaimSpecificity:authorization?.requireClaimSpecificity,getUserData:async()=>{if(!database)return;let usersTbl=reqCtx.schemaTables[AUTHORIZATION_TABLE_KEYS.users];if(!usersTbl)return;let idCol2=usersTbl.id;if(!idCol2)return;return(await database.select().from(usersTbl).where(eq28(idCol2,userId)).limit(1))[0]}})},entityRoutes=new Elysia11({prefix:`/${tableName}`}),listLog=logger2.scoped("entity.list"),isRbacTable=tableName===AUTHORIZATION_TABLE_KEYS.roles||tableName===AUTHORIZATION_TABLE_KEYS.claims||tableName===AUTHORIZATION_TABLE_KEYS.roleClaims,isUserRoleTable=tableName===AUTHORIZATION_TABLE_KEYS.userRoles,roleAssignRoles=featureAdminRoles?.authorization??[];if(isRbacTable||isUserRoleTable||isSensitiveSystemTable(tableName)){let denyMessage=isRbacTable?"Forbidden: managing roles and claims requires godmin privileges":isUserRoleTable?"Forbidden: assigning roles requires godmin privileges":`Forbidden: writing to '${tableName}' via the generic entity API requires godmin privileges \u2014 use the dedicated route`;entityRoutes.onBeforeHandle(async({request,set,body,params})=>{let method=request.method.toUpperCase();if(method==="GET"||method==="HEAD"||method==="OPTIONS")return;if(hasGodminRole(request))return;if(isFeatureAdmin({isRbacTable:isRbacTable||isUserRoleTable,featureSet:table.feature_set,featureAdminRoles,callerRoles:decodeHeaderList(request.headers.get("x-user-roles"))}))return;if(isUserRoleTable&&roleAssignRoles.length>0){let subject=await resolveUserRoleSubject({db,schemaTables:getReqSchema(request).tables,logger:logger2},{rowId:typeof params?.id==="string"?params.id:null,body}),decision=decideRoleAssign({callerIsGod:!1,callerRoleNames:decodeHeaderList(request.headers.get("x-user-roles")),allowRoles:roleAssignRoles,targetRoleName:subject.targetRoleName??GODMIN_ROLE_NAME,subjectIsGodmin:subject.subjectIsGodmin,godminRoleName:GODMIN_ROLE_NAME});if(decision.allowed)return;if(await userHasGodminRoleInDb(db,schemaTables,request.headers.get("x-user-id"),logger2))return;return set.status=403,{success:!1,reason:decision.reason,message:ROLE_ASSIGN_REFUSALS[decision.reason]}}if(await userHasGodminRoleInDb(db,schemaTables,request.headers.get("x-user-id"),logger2))return;return set.status=403,{success:!1,message:denyMessage}})}if(!table.excluded_methods?.includes("GET"))entityRoutes.get("/",async(ctx)=>{if(!database)return{success:!1,message:"DB not initialized"};let{drizzleTable:drizzleTable2,resolveCol:resolveCol2,schemaRelations:schemaRelations2}=getTableForRequest(ctx.request),requestedFields=table.columns?.map((c)=>c.name),requestedRelations=Object.keys(schemaRelations2).filter((k)=>k.startsWith(`${tableName}Relations`)).map((k)=>k.replace("Relations","")),authResult=await performAuthCheck(ctx.request,"GET",requestedFields,requestedRelations);if(authResult&&!authResult.authorized)return ctx.set.status=403,{success:!1,message:authResult.reason||"Forbidden"};let fieldQueryable=(field)=>{if(isSensitiveOutputKey(field))return!1;if(!sensitiveFieldQueryable(field,{authEnabled,allowedFields:authResult?.allowedFields}))return!1;if(authEnabled&&authResult?.allowedFields&&!authResult.allowedFields.includes(field))return!1;return!0},q=parseQueryParams(ctx.query),conditions=[];if(conditions.push(...scopeConditionsFor(authResult,resolveCol2)),q.search&&q.searchFields){for(let f of q.searchFields)if(!fieldQueryable(f.trim()))return ctx.set.status=403,{success:!1,message:`Cannot search on field: ${f.trim()}`};let unknown=firstUnknownField(q.searchFields,resolveCol2);if(unknown)return ctx.set.status=400,{success:!1,message:`Unknown field in search: ${unknown}`};let searchConditions=q.searchFields.map((f)=>ilike(resolveCol2(f.trim()),`%${q.search}%`)).filter((c)=>c!==null);if(searchConditions.length>0){let orCondition=or2(...searchConditions);if(orCondition)conditions.push(orCondition)}}if(Array.isArray(q.filters))for(let filter of q.filters){let referenced=collectFilterFields(filter);for(let f of referenced)if(!fieldQueryable(f))return ctx.set.status=403,{success:!1,message:`Cannot filter on field: ${f}`};let unknownFilterField=firstUnknownField(referenced,resolveCol2);if(unknownFilterField)return ctx.set.status=400,{success:!1,message:`Unknown field in filter: ${unknownFilterField}`};let cond=buildFilterCondition(filter,resolveCol2);if(cond)conditions.push(cond)}let projection;if(q.select&&q.select.length>0){let requested=[...new Set(["id",...q.select.map((f)=>f.trim())])].filter(Boolean),columns={};for(let field of requested){if(!fieldQueryable(field))return ctx.set.status=403,{success:!1,message:`Cannot select field: ${field}`};let col8=resolveCol2(field);if(!col8)return ctx.set.status=400,{success:!1,message:`Unknown field in select: ${field}`};columns[field]=col8}if(Object.keys(columns).length>0)projection=columns}let unprojected=database.select().from(drizzleTable2),baseQuery=projection?database.select(projection).from(drizzleTable2):unprojected;if(conditions.length>0){let combined=and13(...conditions);if(combined)baseQuery=baseQuery.where(combined)}if(q.sort&&q.sort.length>0){for(let s of q.sort)if(!fieldQueryable(s.field))return ctx.set.status=403,{success:!1,message:`Cannot sort on field: ${s.field}`};let orderClauses=q.sort.map((s)=>{let col8=resolveCol2(s.field);if(!col8)return null;return s.direction==="desc"?desc5(col8):asc(col8)}).filter((o)=>o!==null);if(orderClauses.length>0)baseQuery=baseQuery.orderBy(...orderClauses)}let page=q.page??1,limit=q.limit??20,offset=q.offset??(page-1)*limit;if(q.groupBy){let field=q.groupBy.trim();if(!fieldQueryable(field))return ctx.set.status=403,{success:!1,message:`Cannot group by field: ${field}`};let groupCol=resolveCol2(field);if(!groupCol)return ctx.set.status=400,{success:!1,message:`Unknown field in groupBy: ${field}`};let where=conditions.length>0?and13(...conditions):void 0,col8=groupCol,distinctCount=await database.select({n:sql7`count(distinct ${col8})::int`}).from(drizzleTable2).where(where),totalGroups=Number(distinctCount[0]?.n??0);return{success:!0,data:{items:(await database.select({value:col8,count:sql7`count(*)::int`}).from(drizzleTable2).where(where).groupBy(col8).orderBy(sql7`count(*) desc`,col8).limit(limit).offset(offset)).map((g)=>({value:g.value,count:Number(g.count)})),meta:buildPaginationMeta(page,limit,offset,totalGroups)}}}let queryStart=performance.now(),combinedCount=conditions.length>0?and13(...conditions):void 0,countResult=await database.select({n:sql7`count(*)::int`}).from(drizzleTable2).where(combinedCount),totalItems=Number(countResult[0]?.n??0);baseQuery=baseQuery.limit(limit).offset(offset);let items=await baseQuery,meta=buildPaginationMeta(page,limit,offset,totalItems);if(listLog.debug(`List ${rawTableName}: ${items.length}/${totalItems} rows`,{requestId:ctx.request.headers.get("x-request-id")||void 0,table:rawTableName,page,limit,totalItems,returned:items.length,conditionCount:conditions.length,search:q.search||void 0,sort:Array.isArray(q.sort)?q.sort.map((s)=>`${s.field}:${s.direction}`):void 0,queryMs:Math.round(performance.now()-queryStart)}),authEnabled&&authResult?.allowedFields)items=filterResponseFields(items,authResult.allowedFields);return{success:!0,data:{items:items.map((r)=>stripUnclaimedSensitive(redactSensitiveOutput(r),authResult?.allowedFields)),meta}}},{detail:{tags:[swaggerTag],summary:`List ${tableName}`,description:`Get paginated list of ${tableName} records with filtering, sorting, and search`}}),entityRoutes.get("/:id",async(ctx)=>{let{drizzleTable:drizzleTable2,idCol:idCol2,schemaTables:schemaTables2,schemaRelations:schemaRelations2,resolveCol:resolveCol2}=getTableForRequest(ctx.request);if(!database||!idCol2)return{success:!1,message:"No id column or DB"};let params=ctx.params,q=parseQueryParams(ctx.query),requestedFields=table.columns?.map((c)=>c.name),requestedRelations=q.with?.map((w)=>w.name),authResult=await performAuthCheck(ctx.request,"GET",requestedFields,requestedRelations);if(authResult&&!authResult.authorized)return ctx.set.status=403,{success:!1,message:authResult.reason||"Forbidden"};let getScope=scopeConditionsFor(authResult,resolveCol2),getWhere=getScope.length>0?and13(eq28(idCol2,params.id),...getScope):eq28(idCol2,params.id);if(q.with&&q.with.length>0&&tableRelations&&dbPool){let allowedWith=authEnabled&&authResult?.allowedRelations?q.with.filter((w)=>authResult.allowedRelations?.includes(w.name)??!1):q.with,dbWithRelations=drizzle(dbPool,{schema:{...schemaTables2,...schemaRelations2}}),withClause={};for(let rel of allowedWith){let targetTable=relationTargetTable[rel.name],relAuth=authEnabled&&targetTable?await runAuthCheck(ctx.request,"GET",void 0,void 0,targetTable):null,decision=decideRelationExpansion({authEnabled,targetTable,relAuth,isTargetPublicGet:targetTable?publicGetEntities.has(targetTable):!1});if(!decision.expand)continue;let relScope=decision.scope;if(relScope&&Object.keys(relScope).length>0)withClause[rel.name]={...rel.limit?{limit:rel.limit}:{},where:(fields,ops)=>{let preds=[],unresolved=!1;for(let[k,v]of Object.entries(relScope)){let col8=resolveRelationScopeColumn(fields,k,snakeToCamel4);if(col8)preds.push(ops.eq(col8,v));else unresolved=!0}if(unresolved)return sql7`1 = 0`;return preds.length>0?ops.and(...preds):void 0}};else withClause[rel.name]=rel.limit?{limit:rel.limit}:!0}let result2=await dbWithRelations.query[tableName]?.findFirst({where:getWhere,with:withClause});if(authEnabled&&authResult?.allowedFields&&result2)result2=filterResponseFields(result2,[...authResult.allowedFields,...authResult.allowedRelations??[]]);if(authEnabled&&authResult?.allowedRelations&&result2)result2=filterResponseRelations(result2,authResult.allowedRelations);return{success:!0,data:stripUnclaimedSensitive(redactSensitiveOutput(result2||null),authResult?.allowedFields)}}let result=(await database.select().from(drizzleTable2).where(getWhere))[0]||null;if(authEnabled&&authResult?.allowedFields&&result)result=filterResponseFields(result,authResult.allowedFields);return{success:!0,data:stripUnclaimedSensitive(redactSensitiveOutput(result),authResult?.allowedFields)}},{detail:{tags:[swaggerTag],summary:`Get ${tableName} by ID`,description:`Get a single ${tableName} record by its ID with optional relations`}}),entityRoutes.get("/distinct/:field",async(ctx)=>{let{drizzleTable:drizzleTable2,resolveCol:resolveCol2}=getTableForRequest(ctx.request);if(!database)return{success:!1,message:"DB not initialized"};let params=ctx.params,authResult=await performAuthCheck(ctx.request,"GET",[params.field],[]);if(authResult&&!authResult.authorized)return ctx.set.status=403,{success:!1,message:authResult.reason||"Forbidden"};if(authEnabled&&authResult?.allowedFields&&!authResult.allowedFields.includes(params.field))return ctx.set.status=403,{success:!1,message:"Forbidden: field not permitted"};if(isSensitiveOutputKey(params.field))return ctx.set.status=403,{success:!1,message:"Forbidden: field not permitted"};if(!sensitiveFieldQueryable(params.field,{authEnabled,allowedFields:authResult?.allowedFields}))return ctx.set.status=403,{success:!1,message:"Forbidden: field not permitted"};let col8=resolveCol2(params.field);if(!col8)return{success:!1,message:"Field not found"};let distinctScope=scopeConditionsFor(authResult,resolveCol2),distinctQuery=database.selectDistinct({value:col8}).from(drizzleTable2);return{success:!0,data:distinctScope.length>0?await distinctQuery.where(and13(...distinctScope)):await distinctQuery}},{detail:{tags:[swaggerTag],summary:`Get distinct ${tableName} values`,description:`Get distinct values for a specific field in ${tableName}`}});if(!table.excluded_methods?.includes("POST"))if(table.is_form_data&&storageConfig.enabled)entityRoutes.post("/",async(ctx)=>{let{drizzleTable:drizzleTable2,resolveCol:resolveCol2}=getTableForRequest(ctx.request);if(!database)return{success:!1,message:"DB not initialized"};let userId=ctx.request.headers.get("x-user-id"),postFormAuthResult=await performAuthCheck(ctx.request,"POST",writeFields);if(postFormAuthResult&&!postFormAuthResult.authorized)return ctx.set.status=403,{success:!1,message:postFormAuthResult.reason||"Forbidden"};let{data,files}=parseFormDataBody(ctx.body,storageConfig),payload=data,uploadedFiles=null;if(files.length>0){if(uploadedFiles=await uploadFiles(files,storageConfig,table.table_name),uploadedFiles.failed.length>0&&uploadedFiles.success.length===0)return{success:!1,message:"File upload failed",errors:uploadedFiles.failed};warmUploadedMedia(uploadedFiles)}let mergeUploadedMetadata=()=>{let firstFile=uploadedFiles?.success[0];if(firstFile)payload={...payload,...buildFileRecordPayload(firstFile,userId)}};if(table.columns)payload=sanitizePayload(payload,table.columns,{isFormData:table.is_form_data===!0}),payload=filterWritePayload(payload,postFormAuthResult),mergeUploadedMetadata();else mergeUploadedMetadata();let scopedForm=forceCreateScope(payload,postFormAuthResult,resolveCol2);if(!scopedForm.ok)return ctx.set.status=403,{success:!1,message:`Forbidden: ownership scope references a column '${scopedForm.field}' this entity does not have`};if(table.columns){let validation=validatePayload(payload,table.columns,!1);if(!validation.valid)return ctx.set.status=400,{success:!1,message:"Validation failed",errors:validation.errors}}let anonymous=isAnonymousCreate(table,payload);if(userId&&!anonymous)payload.createdBy=userId;let result=await database.insert(drizzleTable2).values(payload).returning();{let reqUrl=new URL(ctx.request.url);logger2.audit({entityName:table.table_name,entityId:String(result[0]?.id??""),operation:"CREATE",summary:`Created ${table.table_name}`,newValues:result[0],...createAuditIdentity(anonymous,userId,ctx.request.headers),path:reqUrl.pathname,query:reqUrl.search})}return{success:!0,data:stripUnclaimedSensitive(redactSensitiveOutput(result[0]),postFormAuthResult?.allowedFields)}},{type:"formdata",body:t9.Object({[storageConfig.formData.dataField]:t9.Optional(t9.Union([t9.String(),t9.Any()])),[storageConfig.formData.filesField]:t9.Optional(t9.Union([t9.File(),t9.Array(t9.File())]))}),detail:{tags:[swaggerTag],summary:`Create ${tableName} with files`,description:`Create a new ${tableName} record with file upload support`}});else entityRoutes.post("/",async(ctx)=>{let{drizzleTable:drizzleTable2,schemaTables:schemaTables2,resolveCol:resolveCol2}=getTableForRequest(ctx.request);if(!database)return{success:!1,message:"DB not initialized"};let payload=ctx.body,userId=ctx.request.headers.get("x-user-id"),postAuthResult=await performAuthCheck(ctx.request,"POST",writeFields);if(postAuthResult&&!postAuthResult.authorized)return ctx.set.status=403,{success:!1,message:postAuthResult.reason||"Forbidden"};if(table.columns)payload=sanitizePayload(payload,table.columns,{isFormData:table.is_form_data===!0}),payload=filterWritePayload(payload,postAuthResult);let scoped2=forceCreateScope(payload,postAuthResult,resolveCol2);if(!scoped2.ok)return ctx.set.status=403,{success:!1,message:`Forbidden: ownership scope references a column '${scoped2.field}' this entity does not have`};if(table.columns){let validation=validatePayload(payload,table.columns,!1);if(!validation.valid)return ctx.set.status=400,{success:!1,message:"Validation failed",errors:validation.errors}}let anonymous=isAnonymousCreate(table,payload);if(userId&&!anonymous)payload.createdBy=userId;if(tableName===AUTHORIZATION_TABLE_KEYS.userRoles&&payload.userId&&payload.roleId){let cols=drizzleTable2,existing=await database.select().from(drizzleTable2).where(and13(eq28(cols.userId,payload.userId),eq28(cols.roleId,payload.roleId))).limit(1);if(existing.length>0)return{success:!0,data:existing[0]}}let result=await database.insert(drizzleTable2).values(payload).returning();if(tableName===AUTHORIZATION_TABLE_KEYS.roleClaims&&config.claimsCache)config.claimsCache.invalidate().catch(()=>{});if(tableName===AUTHORIZATION_TABLE_KEYS.userRoles&&payload.roleId&&payload.userId)try{let rolesTable=schemaTables2[AUTHORIZATION_TABLE_KEYS.roles],usersTable=schemaTables2[AUTHORIZATION_TABLE_KEYS.users];if(rolesTable&&usersTable){let roleName=(await database.select().from(rolesTable).where(eq28(rolesTable.id,payload.roleId)).limit(1))[0]?.name;if(roleName===GODMIN_ROLE_NAME)await database.update(usersTable).set({isGod:!0}).where(eq28(usersTable.id,payload.userId));if(roleName)config.onRoleChanged?.({userId:String(payload.userId),roleName,assigned:!0,actorId:userId??void 0})}}catch(_e){logger2.warn("[Entity] Failed to sync is_god flag on userRole create")}{let reqUrl=new URL(ctx.request.url);logger2.audit({entityName:table.table_name,entityId:String(result[0]?.id??""),operation:"CREATE",summary:`Created ${table.table_name}`,newValues:result[0],...createAuditIdentity(anonymous,userId,ctx.request.headers),path:reqUrl.pathname,query:reqUrl.search})}return{success:!0,data:stripUnclaimedSensitive(redactSensitiveOutput(result[0]),postAuthResult?.allowedFields)}},{body:t9.Object({},{additionalProperties:!0}),detail:{tags:[swaggerTag],summary:`Create ${tableName}`,description:`Create a new ${tableName} record`}});if(!table.excluded_methods?.includes("PUT"))if(table.is_form_data&&storageConfig.enabled)entityRoutes.put("/:id",async(ctx)=>{let{drizzleTable:drizzleTable2,idCol:idCol2,resolveCol:resolveCol2}=getTableForRequest(ctx.request);if(!database||!idCol2)return{success:!1,message:"No id column or DB"};let params=ctx.params,userId=ctx.request.headers.get("x-user-id"),putFormAuthResult=await performAuthCheck(ctx.request,"PUT",writeFields);if(putFormAuthResult&&!putFormAuthResult.authorized)return ctx.set.status=403,{success:!1,message:putFormAuthResult.reason||"Forbidden"};let putFormScope=scopeConditionsFor(putFormAuthResult,resolveCol2),putFormWhere=putFormScope.length>0?and13(eq28(idCol2,params.id),...putFormScope):eq28(idCol2,params.id),{data,files}=parseFormDataBody(ctx.body,storageConfig),payload=data,oldRecord=await database.select().from(drizzleTable2).where(putFormWhere).limit(1);if(putFormScope.length>0&&oldRecord.length===0)return ctx.set.status=403,{success:!1,message:"Forbidden"};if(table.columns){payload=sanitizePayload(payload,table.columns,{isFormData:table.is_form_data===!0}),payload=filterWritePayload(payload,putFormAuthResult);let validation=validatePayload(payload,table.columns,!1);if(!validation.valid)return ctx.set.status=400,{success:!1,message:"Validation failed",errors:validation.errors}}let uploadedFiles=null;if(files.length>0)uploadedFiles=await uploadFiles(files,storageConfig,table.table_name),warmUploadedMedia(uploadedFiles);let result=await database.update(drizzleTable2).set(payload).where(putFormWhere).returning();{let reqUrl=new URL(ctx.request.url);logger2.audit({entityName:table.table_name,entityId:params.id,operation:"UPDATE",userId:userId||void 0,summary:`Updated ${table.table_name} (${params.id})`,oldValues:oldRecord[0],newValues:result[0],ipAddress:ctx.request.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||ctx.request.headers.get("x-real-ip")?.trim()||"unknown",userAgent:ctx.request.headers.get("user-agent")||"unknown",path:reqUrl.pathname,query:reqUrl.search})}return{success:!0,data:{record:result[0],files:uploadedFiles?.success||[],fileErrors:uploadedFiles?.failed||[]}}},{type:"formdata",body:t9.Object({[storageConfig.formData.dataField]:t9.Optional(t9.Union([t9.String(),t9.Any()])),[storageConfig.formData.filesField]:t9.Optional(t9.Union([t9.File(),t9.Array(t9.File())]))}),detail:{tags:[swaggerTag],summary:`Update ${tableName} with files`,description:`Full update of ${tableName} record with file upload support`}});else entityRoutes.put("/:id",async(ctx)=>{let{drizzleTable:drizzleTable2,idCol:idCol2,resolveCol:resolveCol2}=getTableForRequest(ctx.request);if(!database||!idCol2)return{success:!1,message:"No id column or DB"};let{params,body:payload}=ctx,userId=ctx.request.headers.get("x-user-id"),putAuthResult=await performAuthCheck(ctx.request,"PUT",writeFields);if(putAuthResult&&!putAuthResult.authorized)return ctx.set.status=403,{success:!1,message:putAuthResult.reason||"Forbidden"};let putScope=scopeConditionsFor(putAuthResult,resolveCol2),putWhere=putScope.length>0?and13(eq28(idCol2,params.id),...putScope):eq28(idCol2,params.id),oldRecord=await database.select().from(drizzleTable2).where(putWhere).limit(1);if(putScope.length>0&&oldRecord.length===0)return ctx.set.status=403,{success:!1,message:"Forbidden"};if(table.columns){payload=sanitizePayload(payload,table.columns,{isFormData:table.is_form_data===!0}),payload=filterWritePayload(payload,putAuthResult);let validation=validatePayload(payload,table.columns,!1);if(!validation.valid)return ctx.set.status=400,{success:!1,message:"Validation failed",errors:validation.errors}}if(payload.updatedAt=new Date,userId)payload.updatedBy=userId;let result=await database.update(drizzleTable2).set(payload).where(putWhere).returning();{let reqUrl=new URL(ctx.request.url);logger2.audit({entityName:table.table_name,entityId:params.id,operation:"UPDATE",userId:userId||void 0,summary:`Updated ${table.table_name} (${params.id})`,oldValues:oldRecord[0],newValues:result[0],ipAddress:ctx.request.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||ctx.request.headers.get("x-real-ip")?.trim()||"unknown",userAgent:ctx.request.headers.get("user-agent")||"unknown",path:reqUrl.pathname,query:reqUrl.search})}return{success:!0,data:stripUnclaimedSensitive(redactSensitiveOutput(result[0]),putAuthResult?.allowedFields)}},{body:t9.Object({},{additionalProperties:!0}),detail:{tags:[swaggerTag],summary:`Update ${tableName}`,description:`Full update of ${tableName} record`}});if(!table.excluded_methods?.includes("PATCH"))entityRoutes.patch("/:id",async(ctx)=>{let{drizzleTable:drizzleTable2,idCol:idCol2,resolveCol:resolveCol2}=getTableForRequest(ctx.request);if(!database||!idCol2)return{success:!1,message:"No id column or DB"};let{params,body:payload}=ctx,userId=ctx.request.headers.get("x-user-id"),patchAuthResult=await performAuthCheck(ctx.request,"PATCH",writeFields);if(patchAuthResult&&!patchAuthResult.authorized)return ctx.set.status=403,{success:!1,message:patchAuthResult.reason||"Forbidden"};let patchScope=scopeConditionsFor(patchAuthResult,resolveCol2),patchWhere=patchScope.length>0?and13(eq28(idCol2,params.id),...patchScope):eq28(idCol2,params.id),oldRecord=await database.select().from(drizzleTable2).where(patchWhere).limit(1);if(patchScope.length>0&&oldRecord.length===0)return ctx.set.status=403,{success:!1,message:"Forbidden"};if(table.columns){payload=sanitizePayload(payload,table.columns,{isFormData:table.is_form_data===!0}),payload=filterWritePayload(payload,patchAuthResult);let validation=validatePayload(payload,table.columns,!0);if(!validation.valid)return ctx.set.status=400,{success:!1,message:"Validation failed",errors:validation.errors}}if(payload.updatedAt=new Date,userId)payload.updatedBy=userId;let result=await database.update(drizzleTable2).set(payload).where(patchWhere).returning();{let reqUrl=new URL(ctx.request.url);logger2.audit({entityName:table.table_name,entityId:params.id,operation:"PATCH",userId:userId||void 0,summary:`Patched ${table.table_name} (${params.id})`,oldValues:oldRecord[0],newValues:result[0],ipAddress:ctx.request.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||ctx.request.headers.get("x-real-ip")?.trim()||"unknown",userAgent:ctx.request.headers.get("user-agent")||"unknown",path:reqUrl.pathname,query:reqUrl.search})}return{success:!0,data:stripUnclaimedSensitive(redactSensitiveOutput(result[0]),patchAuthResult?.allowedFields)}},{body:t9.Object({},{additionalProperties:!0}),detail:{tags:[swaggerTag],summary:`Patch ${tableName}`,description:`Partial update of ${tableName} record`}});if(!table.excluded_methods?.includes("DELETE"))entityRoutes.delete("/:id",async(ctx)=>{let{drizzleTable:drizzleTable2,idCol:idCol2,schemaTables:schemaTables2,resolveCol:resolveCol2}=getTableForRequest(ctx.request);if(!database||!idCol2)return{success:!1,message:"No id column or DB"};let params=ctx.params,userId=ctx.request.headers.get("x-user-id"),deleteAuthResult=await performAuthCheck(ctx.request,"DELETE");if(deleteAuthResult&&!deleteAuthResult.authorized)return ctx.set.status=403,{success:!1,message:deleteAuthResult.reason||"Forbidden"};let deleteScope=scopeConditionsFor(deleteAuthResult,resolveCol2),deleteWhere=deleteScope.length>0?and13(eq28(idCol2,params.id),...deleteScope):eq28(idCol2,params.id),oldRecord=await database.select().from(drizzleTable2).where(deleteWhere).limit(1);if(deleteScope.length>0&&oldRecord.length===0)return ctx.set.status=403,{success:!1,message:"Forbidden"};if(await database.delete(drizzleTable2).where(deleteWhere),table.is_form_data&&storageConfig.enabled&&oldRecord[0]){let rec=oldRecord[0],filePath=rec.path,fileName=rec.name;if(typeof filePath==="string"&&typeof fileName==="string"){if(!await deleteFile(filePath,fileName,storageConfig.basePath))logger2.warn(`[Entity] Blob cleanup failed for ${table.table_name} (${params.id})`)}}if(oldRecord[0]){let link=accountLinkFor(config.accountLinks,tableName),userIds=link?accountIdsIn([oldRecord[0]],link.userColumn):[];if(userIds.length>0){let authTables=resolveAuthTablesForRequest(ctx.request,{usersTable:schemaTables2[AUTHORIZATION_TABLE_KEYS.users],sessionsTable:schemaTables2.userSessions??schemaTables2.sessions,schemaTables:schemaTables2,tenantRegistry:config.tenantRegistry,getTenantRegistry:config.getTenantRegistry}),result=await closeAccounts({db:database,usersTable:authTables.usersTable,sessionsTable:authTables.sessionsTable,onError:(error)=>logger2.error(`[Entity] ${tableName} ${params.id} was deleted but its account could not be closed`,{error})},userIds);if(result.closed>0&&!result.signedOut)logger2.warn(`[Entity] Account behind ${tableName} ${params.id} was deactivated but its open sessions were not cleared`)}}if(tableName===AUTHORIZATION_TABLE_KEYS.roleClaims&&config.claimsCache)config.claimsCache.invalidate().catch(()=>{});if(tableName===AUTHORIZATION_TABLE_KEYS.userRoles&&oldRecord[0])try{let deletedUserRole=oldRecord[0],rolesTable=schemaTables2[AUTHORIZATION_TABLE_KEYS.roles],usersTable=schemaTables2[AUTHORIZATION_TABLE_KEYS.users];if(rolesTable&&usersTable&&deletedUserRole.roleId&&deletedUserRole.userId){let roleName=(await database.select().from(rolesTable).where(eq28(rolesTable.id,deletedUserRole.roleId)).limit(1))[0]?.name;if(roleName===GODMIN_ROLE_NAME)await database.update(usersTable).set({isGod:!1}).where(eq28(usersTable.id,deletedUserRole.userId));if(roleName)config.onRoleChanged?.({userId:String(deletedUserRole.userId),roleName,assigned:!1,actorId:ctx.request.headers.get("x-user-id")??void 0})}}catch(_e){logger2.warn("[Entity] Failed to sync is_god flag on userRole delete")}{let reqUrl=new URL(ctx.request.url);logger2.audit({entityName:table.table_name,entityId:params.id,operation:"DELETE",userId:userId||void 0,summary:`Deleted ${table.table_name} (${params.id})`,oldValues:oldRecord[0],ipAddress:ctx.request.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||ctx.request.headers.get("x-real-ip")?.trim()||"unknown",userAgent:ctx.request.headers.get("user-agent")||"unknown",path:reqUrl.pathname,query:reqUrl.search})}return{success:!0,data:null}},{detail:{tags:[swaggerTag],summary:`Delete ${tableName}`,description:`Delete a ${tableName} record`}});if(table.bulk_endpoints_enabled){if(!table.excluded_methods?.includes("POST"))entityRoutes.post("/bulk",async(ctx)=>{let{drizzleTable:drizzleTable2,resolveCol:resolveCol2}=getTableForRequest(ctx.request);if(!database)return{success:!1,message:"DB not initialized"};let items=ctx.body;if(!Array.isArray(items))return{success:!1,message:"Body must be an array"};if(items.length>MAX_BULK_ITEMS)return ctx.set.status=400,{success:!1,message:`Bulk request exceeds ${MAX_BULK_ITEMS} items`};let userId=ctx.request.headers.get("x-user-id"),bulkPostAuth=await performAuthCheck(ctx.request,"POST",writeFields);if(bulkPostAuth&&!bulkPostAuth.authorized)return ctx.set.status=403,{success:!1,message:bulkPostAuth.reason||"Forbidden"};let sanitizedItems=[];for(let raw of items){let payload=raw;if(table.columns)payload=sanitizePayload(payload,table.columns,{isFormData:table.is_form_data===!0}),payload=filterWritePayload(payload,bulkPostAuth);let scopedItem=forceCreateScope(payload,bulkPostAuth,resolveCol2);if(!scopedItem.ok)return ctx.set.status=403,{success:!1,message:`Forbidden: ownership scope references a column '${scopedItem.field}' this entity does not have`};if(table.columns){let validation=validatePayload(payload,table.columns,!1);if(!validation.valid)return ctx.set.status=400,{success:!1,message:"Validation failed",errors:validation.errors}}if(userId&&!isAnonymousCreate(table,payload))payload.createdBy=userId;sanitizedItems.push(payload)}let txResult=await database.transaction(async(tx)=>{let results=[];for(let payload of sanitizedItems){let result=await tx.insert(drizzleTable2).values(payload).returning();results.push(result[0])}return results}),auditPath=auditPathContext(ctx.request);for(let[i,row]of txResult.entries())await logger2.audit({entityName:table.table_name,entityId:auditEntityId(row.id),operation:"CREATE",summary:`Bulk created ${table.table_name} (${row.id})`,newValues:row,...auditIdentityFor(table,sanitizedItems[i]??{},userId,ctx.request.headers),...auditPath});return{success:!0,data:txResult.map((r)=>projectWrittenRow(r,bulkPostAuth))}},{body:t9.Array(t9.Object({},{additionalProperties:!0})),detail:{tags:[swaggerTag],summary:`Bulk create ${tableName}`,description:`Create multiple ${tableName} records`}});if(!table.excluded_methods?.includes("PUT"))entityRoutes.put("/bulk",async(ctx)=>{let{drizzleTable:drizzleTable2,idCol:idCol2,resolveCol:resolveCol2}=getTableForRequest(ctx.request);if(!database||!idCol2)return{success:!1,message:"No id column or DB"};let items=ctx.body;if(!Array.isArray(items))return{success:!1,message:"Body must be an array"};if(items.length>MAX_BULK_ITEMS)return ctx.set.status=400,{success:!1,message:`Bulk request exceeds ${MAX_BULK_ITEMS} items`};let userId=ctx.request.headers.get("x-user-id"),bulkPutAuth=await performAuthCheck(ctx.request,"PUT",writeFields);if(bulkPutAuth&&!bulkPutAuth.authorized)return ctx.set.status=403,{success:!1,message:bulkPutAuth.reason||"Forbidden"};let bulkPutScope=scopeConditionsFor(bulkPutAuth,resolveCol2),prepared=[];for(let item of items){let payload=item.data;if(table.columns){payload=sanitizePayload(payload,table.columns,{isFormData:table.is_form_data===!0}),payload=filterWritePayload(payload,bulkPutAuth);let validation=validatePayload(payload,table.columns,!0);if(!validation.valid)return ctx.set.status=400,{success:!1,message:"Validation failed",errors:validation.errors}}if(payload.updatedAt=new Date,userId)payload.updatedBy=userId;prepared.push({id:item.id,payload})}let beforeById=new Map,txResult=await database.transaction(async(tx)=>{if(prepared.length>0){let idFilter=inArray9(idCol2,prepared.map((p)=>p.id)),beforeRows=await tx.select().from(drizzleTable2).where(bulkPutScope.length>0?and13(idFilter,...bulkPutScope):idFilter);for(let row of beforeRows)if(row.id!=null)beforeById.set(String(row.id),row)}let results=[];for(let{id,payload}of prepared){let result=await tx.update(drizzleTable2).set(payload).where(bulkPutScope.length>0?and13(eq28(idCol2,id),...bulkPutScope):eq28(idCol2,id)).returning();if(result[0])results.push(result[0])}return results}),auditPath=auditPathContext(ctx.request);for(let row of txResult){let rowId=String(row.id);await logger2.audit({entityName:table.table_name,entityId:auditEntityId(row.id),operation:"UPDATE",userId:userId||void 0,summary:`Bulk updated ${table.table_name} (${rowId})`,oldValues:beforeById.get(rowId),newValues:row,...auditPath})}return{success:!0,data:txResult.map((r)=>projectWrittenRow(r,bulkPutAuth))}},{body:bulkUpdateSchema,detail:{tags:[swaggerTag],summary:`Bulk update ${tableName}`,description:`Update multiple ${tableName} records`}});if(!table.excluded_methods?.includes("DELETE"))entityRoutes.delete("/bulk",async(ctx)=>{let{drizzleTable:drizzleTable2,idCol:idCol2,resolveCol:resolveCol2}=getTableForRequest(ctx.request);if(!database||!idCol2)return{success:!1,message:"No id column or DB"};let ids=ctx.body;if(!Array.isArray(ids))return{success:!1,message:"Body must be an array of ids"};if(ids.length>MAX_BULK_ITEMS)return ctx.set.status=400,{success:!1,message:`Bulk request exceeds ${MAX_BULK_ITEMS} items`};let bulkDeleteAuth=await performAuthCheck(ctx.request,"DELETE");if(bulkDeleteAuth&&!bulkDeleteAuth.authorized)return ctx.set.status=403,{success:!1,message:bulkDeleteAuth.reason||"Forbidden"};let bulkDeleteScope=scopeConditionsFor(bulkDeleteAuth,resolveCol2),userId=ctx.request.headers.get("x-user-id"),removed=[];await database.transaction(async(tx)=>{for(let id of ids){let r=await tx.delete(drizzleTable2).where(bulkDeleteScope.length>0?and13(eq28(idCol2,id),...bulkDeleteScope):eq28(idCol2,id)).returning();removed.push(...r)}});{let link=accountLinkFor(config.accountLinks,tableName),bulkUserIds=link?accountIdsIn(removed,link.userColumn):[];if(bulkUserIds.length>0){let authTables=resolveAuthTablesForRequest(ctx.request,{usersTable:schemaTables[AUTHORIZATION_TABLE_KEYS.users],sessionsTable:schemaTables.userSessions??schemaTables.sessions,schemaTables,tenantRegistry:config.tenantRegistry,getTenantRegistry:config.getTenantRegistry}),result=await closeAccounts({db:database,usersTable:authTables.usersTable,sessionsTable:authTables.sessionsTable,onError:(error)=>logger2.error(`[Entity] ${removed.length} ${tableName} rows were deleted but their accounts could not be closed`,{error})},bulkUserIds);if(result.closed>0&&!result.signedOut)logger2.warn(`[Entity] ${result.closed} account(s) behind deleted ${tableName} rows were deactivated but their open sessions were not cleared`)}}let auditPath=auditPathContext(ctx.request);for(let row of removed)await logger2.audit({entityName:table.table_name,entityId:auditEntityId(row.id),operation:"DELETE",userId:userId||void 0,summary:`Bulk deleted ${table.table_name} (${row.id})`,oldValues:row,...auditPath});return{success:!0,data:{deleted:removed.length}}},{body:bulkDeleteSchema,detail:{tags:[swaggerTag],summary:`Bulk delete ${tableName}`,description:`Delete multiple ${tableName} records`}})}app.use(entityRoutes)}return app}import Elysia13,{t as t11}from"elysia";import{randomUUID as randomUUID7}from"crypto";var LOCK_TTL_SECONDS2=60,RENEW_INTERVAL_MS=20000,lockKeyFor=(mappingId)=>`integrations:run:${mappingId}`;async function acquireRunLock(store,mappingId,deps={}){let key2=lockKeyFor(mappingId),now=deps.now??Date.now,ttl=deps.ttlSeconds??LOCK_TTL_SECONDS2,token=randomUUID7(),existing=await store.read(key2);if(!existing.success)return{ok:!1,reason:"unavailable",error:existing.error};if(existing.data)return{ok:!1,reason:"held",heldSince:existing.data.acquiredAt??null};let created=await store.create(key2,{token,acquiredAt:now()},ttl);if(!created.success)return{ok:!1,reason:"unavailable",error:created.error};let readBack=await store.read(key2);if(!readBack.success)return{ok:!1,reason:"unavailable",error:readBack.error};if(readBack.data?.token!==token)return{ok:!1,reason:"held",heldSince:readBack.data?.acquiredAt??null};let held=!0,timer=setInterval(()=>{(async()=>{let current=await store.read(key2);if(!current.success)return;if(current.data?.token!==token){held=!1,clearInterval(timer),deps.logger?.warn("[Integrations] Run lock was taken over",{mappingId});return}await store.create(key2,current.data,ttl)})()},RENEW_INTERVAL_MS);return timer.unref?.(),{ok:!0,handle:{token,isHeld:()=>held,release:async()=>{if(clearInterval(timer),!held)return;held=!1;let current=await store.read(key2);if(current.success&¤t.data?.token===token)await store.remove(key2)}}}}import{createHash as createHash2}from"crypto";function buildUrl(baseUrl,path8,params){let base=baseUrl.trim().replace(/\/+$/,"");if(!base)return{ok:!1,error:"The source has no base address."};let raw=(path8??"").trim();if(/^[a-z][a-z0-9+.-]*:\/\//i.test(raw)||raw.startsWith("//"))return{ok:!1,error:`The endpoint path points at another host (${raw}). A path must be relative to the source address.`};let suffix=raw===""?"":raw.startsWith("/")?raw:`/${raw}`,url;try{url=new URL(`${base}${suffix}`)}catch{return{ok:!1,error:`The source address is not a valid URL: ${baseUrl}`}}for(let[key2,value]of Object.entries(params??{})){if(value==null)continue;url.searchParams.set(key2,String(value))}return{ok:!0,url}}function applyAuth(source,url){let headers={accept:"application/json",...source.extraHeaders??{}},token=source.token?.trim();if(!token)return{headers};switch(source.authType){case"bearer":case"oauth2":headers[source.authHeaderName||"Authorization"]=`Bearer ${token}`;break;case"api_key":if(source.authQueryParam)url.searchParams.set(source.authQueryParam,token);else headers[source.authHeaderName||"X-API-Key"]=token;break;case"basic":headers.Authorization=`Basic ${token}`;break;default:break}return{headers}}function describeTransportError(error){let message=error instanceof Error?error.message:String(error),cause=error?.cause,code=cause?.code??"",blob=`${message} ${code} ${cause?.message??""}`;if(/UNABLE_TO_GET_ISSUER_CERT|SELF_SIGNED|self.signed|CERT_|unable to verify|ERR_TLS|altnames/i.test(blob))return`Certificate verification failed (${code||"incomplete chain"}). If this server's certificate is knowingly self-signed or incomplete, turn off certificate verification for this source and try again.`;if(/ENOTFOUND|EAI_AGAIN|getaddrinfo|Unable to resolve/i.test(blob))return`The address could not be resolved (DNS${code?`: ${code}`:""}). Check the source address.`;if(/ECONNREFUSED/i.test(blob))return`The connection was refused (${code||"ECONNREFUSED"}). The address and port are reachable but nothing is listening.`;if(/ETIMEDOUT|timeout|timed out|aborted|AbortError|UND_ERR/i.test(blob))return`The connection timed out (${code||"timeout"}). Check network and firewall access to this address.`;if(/ECONNRESET|EPIPE/i.test(blob))return`The connection was closed by the other side (${code||"ECONNRESET"}).`;return`Connection error: ${message}`}async function fetchOnce(source,request,deps={}){let impl=deps.fetchImpl??fetch,headers={...request.headers},method=request.method.toUpperCase(),hasBody=request.body!==void 0&&method!=="GET"&&method!=="HEAD";if(hasBody&&!headers["content-type"]&&!headers["Content-Type"])headers["content-type"]="application/json";let init={method,headers,cache:"no-store",signal:AbortSignal.timeout(source.timeoutMs??30000),tls:{rejectUnauthorized:source.tlsVerify!==!1},...hasBody?{body:typeof request.body==="string"?request.body:JSON.stringify(request.body)}:{}},response;try{response=await impl(request.url.toString(),init)}catch(error){return deps.logger?.warn("[Integrations] Outbound request failed",{sourceId:source.id,url:request.url.origin+request.url.pathname,error:error instanceof Error?error.message:String(error)}),{ok:!1,status:0,body:null,linkHeader:null,error:describeTransportError(error)}}let text=await response.text().catch(()=>""),body=null;if(text)try{body=JSON.parse(text)}catch{body=text}let linkHeader=response.headers.get("link");if(!response.ok){let detail=typeof body==="string"?body:body==null?"":JSON.stringify(body);return{ok:!1,status:response.status,body,linkHeader,error:`The source returned HTTP ${response.status}${detail?` \u2014 ${detail.slice(0,300)}`:""}`}}return{ok:!0,status:response.status,body,linkHeader}}var EXPIRY_SKEW_MS=5000,DEFAULT_TTL_MS=300000,DEFAULT_REFRESH_TTL_MS=1800000,FIELD_SEPARATOR="\x00";function credentialFingerprint(config){let material=[config.tokenUrl,config.grantType,config.clientId??"",config.clientSecret??"",config.username??"",config.password??"",config.scope??"",config.clientAuth??"basic"].join(FIELD_SEPARATOR);return createHash2("sha256").update(material).digest("hex").slice(0,32)}class TokenCache{entries=new Map;get(sourceId,fingerprint){let entry=this.entries.get(sourceId);if(!entry)return null;if(entry.fingerprint!==fingerprint)return this.entries.delete(sourceId),null;return entry}set(sourceId,token){this.entries.set(sourceId,token)}invalidate(sourceId){this.entries.delete(sourceId)}clear(){this.entries.clear()}}var isUsable=(token,now)=>token.expiresAt>now+EXPIRY_SKEW_MS,canRefresh=(token,now)=>Boolean(token.refreshToken)&&(token.refreshExpiresAt??0)>now+EXPIRY_SKEW_MS;function buildTokenRequest(config,form){let headers={"content-type":"application/x-www-form-urlencoded",accept:"application/json"};if(config.scope&&!form.has("scope"))form.set("scope",config.scope);let clientId=config.clientId??"",clientSecret=config.clientSecret??"";if((config.clientAuth??"basic")==="basic")headers.authorization=`Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString("base64")}`;else{if(clientId)form.set("client_id",clientId);if(clientSecret)form.set("client_secret",clientSecret)}return{headers,body:form.toString()}}async function requestToken(config,form,now,fetchImpl){let{headers,body}=buildTokenRequest(config,form),response;try{response=await fetchImpl(config.tokenUrl,{method:"POST",headers,body,cache:"no-store",signal:AbortSignal.timeout(config.timeoutMs??30000),tls:{rejectUnauthorized:config.tlsVerify!==!1}})}catch(error){return{ok:!1,error:`Token request failed \u2014 ${describeTransportError(error)}`}}let text=await response.text().catch(()=>""),json={};try{json=text?JSON.parse(text):{}}catch{}if(!response.ok||!json.access_token){let detail=json.error_description||json.error||text.slice(0,200);return{ok:!1,error:`Could not obtain an OAuth2 token (HTTP ${response.status})${detail?`: ${detail}`:""}`}}return{ok:!0,token:{accessToken:json.access_token,expiresAt:now+(json.expires_in?json.expires_in*1000:DEFAULT_TTL_MS),refreshToken:json.refresh_token,refreshExpiresAt:json.refresh_token?now+(json.refresh_expires_in?json.refresh_expires_in*1000:DEFAULT_REFRESH_TTL_MS):void 0,fingerprint:credentialFingerprint(config)}}}async function getAccessToken(config,cache,deps={}){let fetchImpl=deps.fetchImpl??fetch,now=deps.now?.()??Date.now();if(!config.tokenUrl?.trim())return{ok:!1,error:"No token URL is configured for this source."};let fingerprint=credentialFingerprint(config),cached=cache.get(config.sourceId,fingerprint);if(cached&&isUsable(cached,now))return{ok:!0,accessToken:cached.accessToken,fromCache:!0};if(cached&&canRefresh(cached,now)){let refreshed=await requestToken(config,new URLSearchParams({grant_type:"refresh_token",refresh_token:cached.refreshToken}),now,fetchImpl);if(refreshed.ok)return cache.set(config.sourceId,refreshed.token),{ok:!0,accessToken:refreshed.token.accessToken,fromCache:!1}}let form=new URLSearchParams({grant_type:config.grantType});if(config.grantType==="password")form.set("username",config.username??""),form.set("password",config.password??"");let minted=await requestToken(config,form,now,fetchImpl);if(!minted.ok)return{ok:!1,error:minted.error};return cache.set(config.sourceId,minted.token),{ok:!0,accessToken:minted.token.accessToken,fromCache:!1}}import{and as and14,eq as eq29,inArray as inArray10}from"drizzle-orm";var DEFAULT_IGNORED=["updatedAt","updated_at","updatedBy","updated_by"];function planRevert(input){let ignored=new Set([...DEFAULT_IGNORED,...input.ignoreColumns??[]]),ops={deletes:[],restores:[],reinserts:[],conflicts:[]};for(let image of input.preImages)switch(image.action){case"create":{if(!image.rowId)break;let now=input.current.get(image.rowId);if(!now)break;if(!input.force&&changedSince(image.after,now,ignored)){ops.conflicts.push({id:image.rowId,reason:"This record was edited after the import; deleting it would discard that edit."});break}ops.deletes.push(image.rowId);break}case"update":case"deactivate":{if(!image.rowId||!image.before)break;let now=input.current.get(image.rowId);if(!now)break;if(!input.force&&changedSince(image.after,now,ignored)){ops.conflicts.push({id:image.rowId,reason:"This record was edited after the import; restoring it would discard that edit."});break}ops.restores.push({id:image.rowId,row:image.before});break}case"delete":{if(!image.before)break;if(image.rowId&&input.current.has(image.rowId)){ops.conflicts.push({id:image.rowId,reason:"A record with this identifier exists again; it was not replaced."});break}ops.reinserts.push(image.before);break}default:break}return ops}function changedSince(after,now,ignored){if(!after)return!1;for(let[key2,value]of Object.entries(after)){if(ignored.has(key2))continue;if(!sameValue(value,now[key2]))return!0}return!1}function sameValue(a,b){if(a===b)return!0;if(a==null&&b==null)return!0;if(a instanceof Date&&b instanceof Date)return a.getTime()===b.getTime();if(a instanceof Date||b instanceof Date){let da=a instanceof Date?a:new Date(String(a)),db=b instanceof Date?b:new Date(String(b));return!Number.isNaN(da.getTime())&&!Number.isNaN(db.getTime())?da.getTime()===db.getTime():!1}if(typeof a==="object"||typeof b==="object")try{return JSON.stringify(a)===JSON.stringify(b)}catch{return!1}return String(a)===String(b)}var CHUNK=500;async function applyRevert(deps,ops,meta){let idCol=deps.resolveCol("id");if(!idCol)return{ok:!1,conflicts:ops.conflicts.length,error:`"${meta.targetEntity}" has no id column; its rows cannot be addressed.`};let now=new Date;try{let work=async(tx)=>{let deleted=0,restored=0,reinserted=0;for(let i=0;i<ops.deletes.length;i+=CHUNK){let chunk=ops.deletes.slice(i,i+CHUNK),removed=await tx.delete(deps.drizzleTable).where(inArray10(idCol,chunk)).returning();deleted+=removed.length}for(let restore of ops.restores){let{id:_id,createdAt:_c,createdBy:_cb,...rest}=restore.row,written=await tx.update(deps.drizzleTable).set({...rest,updatedAt:now,updatedBy:meta.userId}).where(and14(eq29(idCol,restore.id))).returning();restored+=written.length}if(ops.reinserts.length>0)for(let i=0;i<ops.reinserts.length;i+=CHUNK){let chunk=ops.reinserts.slice(i,i+CHUNK),written=await tx.insert(deps.drizzleTable).values(chunk).returning();reinserted+=written.length}return{deleted,restored,reinserted}};return{ok:!0,...meta.tx?await work(meta.tx):await deps.db.transaction(work),conflicts:ops.conflicts.length}}catch(error){return deps.logger.error("[Integrations] Revert transaction failed",{targetEntity:meta.targetEntity,error:error instanceof Error?error.message:String(error)}),{ok:!1,conflicts:ops.conflicts.length,error:"The database rejected this undo; it was rolled back and nothing changed."}}}function groupPreImagesByEntity(preImages){let byEntity=new Map;for(let image of preImages){let list2=byEntity.get(image.targetEntity);if(list2)list2.push(image);else byEntity.set(image.targetEntity,[image])}return[...byEntity.entries()].map(([targetEntity,images])=>({targetEntity,preImages:images}))}function touchedRowIds(preImages){let ids=new Set;for(let image of preImages)if(image.rowId)ids.add(image.rowId);return[...ids]}var TREE_PARENT_KEY="__treeParent";function flattenTree(records,childrenPath){let out=[],truncated=!1,visit=(node,parent,depth)=>{if(!node||typeof node!=="object")return;if(depth>64){truncated=!0;return}let source=node,children=source[childrenPath],{[childrenPath]:_nested,...own}=source;if(out.push({...own,["__depth"]:depth,["__treeParent"]:parent??null}),!Array.isArray(children))return;for(let child of children)visit(child,own,depth+1)};for(let root of records)visit(root,null,0);return{records:out,truncated}}function treeChildrenPath(value){let trimmed=(value??"").trim();return trimmed.length>0?trimmed:null}function getByPath(obj,path8){if(!path8)return;let cur=obj;for(let part of path8.split(".")){if(cur==null||typeof cur!=="object")return;cur=cur[part]}return cur}function readSourceValue(external,parent,path8){return readOne(external,parent,path8)}function readOne(external,parent,path8){return path8.startsWith("__parent.")?getByPath(parent,path8.slice(9)):getByPath(external,path8)}var TEMPLATE_TOKEN=/\{([^{}]+)\}/g;function isTemplateSource(source){return TEMPLATE_TOKEN.lastIndex=0,TEMPLATE_TOKEN.test(source)}function renderTemplate(template,external,parent){let treeParentAbsent=external!=null&&typeof external==="object"&&TREE_PARENT_KEY in external&&external[TREE_PARENT_KEY]==null,readsTreeParent=(text)=>text.includes(`{${TREE_PARENT_KEY}.`),readToken=(token)=>{let[path8="",transform]=token.split("|"),value=readOne(external,parent,path8.trim());if(transform===void 0)return value;let result=applyTransform(value,transform.trim());return result.ok?result.value:value};for(let alternative of template.split("||")){let candidate=alternative.trim();if(candidate==="")continue;if(treeParentAbsent&&readsTreeParent(candidate))continue;let complete=!0,rendered=candidate.replace(TEMPLATE_TOKEN,(_match,token)=>{let value=readToken(token);if(value==null||String(value).trim()==="")complete=!1;return value==null?"":String(value)});if(complete&&rendered.trim()!=="")return rendered}let last=template.split("||").pop()??template;if(treeParentAbsent&&readsTreeParent(last))return"";return last.trim().replace(TEMPLATE_TOKEN,(_match,token)=>{let value=readToken(token);return value==null?"":String(value)})}function extractRecords(body,rootPath){if(rootPath){let at=getByPath(body,rootPath);if(Array.isArray(at))return at;return at&&typeof at==="object"?[at]:[]}let candidate=firstArrayLike(body)??deepFirstArrayOfObjects(body);return Array.isArray(candidate)?candidate:[]}var ENVELOPE_KEYS=["content","items","data","results","records","rows","list","value","responseObject"];function firstArrayLike(body){if(Array.isArray(body))return body;if(!body||typeof body!=="object")return;let b=body;for(let key2 of ENVELOPE_KEYS){let v=b[key2];if(Array.isArray(v))return v;if(v&&typeof v==="object"){let nested=v.items;if(Array.isArray(nested))return nested}}return}function deepFirstArrayOfObjects(body,depth=0){if(depth>5||body==null||typeof body!=="object"||body instanceof Date)return;if(Array.isArray(body))return body.length>0&&typeof body[0]==="object"&&body[0]!==null?body:void 0;let entries=Object.values(body);for(let v of entries)if(Array.isArray(v)&&v.length>0&&typeof v[0]==="object"&&v[0]!==null)return v;for(let v of entries)if(v&&typeof v==="object"&&!Array.isArray(v)){let found=deepFirstArrayOfObjects(v,depth+1);if(found)return found}for(let v of entries)if(Array.isArray(v))return v;return}var FOLD={\u{131}:"i",\u{130}:"I",\u{15f}:"s",\u{15e}:"S",\u{11f}:"g",\u{11e}:"G",\u{f8}:"o",\u{d8}:"O",\u{e6}:"ae",\u{c6}:"AE",\u{df}:"ss",\u{111}:"d",\u{110}:"D",\u{142}:"l",\u{141}:"L"};function foldToAscii(value){return value.replace(/[\u0131\u0130\u015F\u015E\u011F\u011E\u00F8\u00D8\u00E6\u00C6\u00DF\u0111\u0110\u0142\u0141]/g,(ch)=>FOLD[ch]??ch).normalize("NFD").replace(/[\u0300-\u036f]/g,"")}var TRUTHY=new Set(["true","1","yes","y","evet","e","on"]),FALSY=new Set(["false","0","no","n","hayir","hay\u0131r","h","off"]);function applyTransform(value,transform,locale){if(value==null)return{ok:!0,value};switch(transform){case"trim":return{ok:!0,value:String(value).trim()};case"upper":return{ok:!0,value:String(value).trim().toLocaleUpperCase(locale)};case"lower":return{ok:!0,value:String(value).trim().toLocaleLowerCase(locale)};case"toString":return{ok:!0,value:String(value)};case"toNumber":{if(typeof value==="boolean")return{ok:!1,reason:"not a number",raw:value};let s=String(value).trim();if(s==="")return{ok:!0,value:null};let n=Number(s);return Number.isFinite(n)?{ok:!0,value:n}:{ok:!1,reason:"not a number",raw:value}}case"toBoolean":{if(typeof value==="boolean")return{ok:!0,value};let s=String(value).trim().toLocaleLowerCase("tr-TR");if(s==="")return{ok:!0,value:null};if(TRUTHY.has(s))return{ok:!0,value:!0};if(FALSY.has(s))return{ok:!0,value:!1};return{ok:!1,reason:"not a yes/no value",raw:value}}case"emailSafe":return{ok:!0,value:foldToAscii(String(value)).toLowerCase().trim().replace(/[^a-z0-9._@+-]+/g,".").replace(/\.{2,}/g,".").replace(/\.*@\.*/g,"@").replace(/^[.\-_]+|[.\-_]+$/g,"")};case"slug":return{ok:!0,value:foldToAscii(String(value)).toLowerCase().trim().replace(/[^a-z0-9]+/g,"-").replace(/-{2,}/g,"-").replace(/^-+|-+$/g,"")};case"pathLeaf":{let parts=String(value).split(/[/\\>\u203A\u00BB]|->/).map((part)=>part.trim()).filter((part)=>part!=="");return{ok:!0,value:parts.length>0?parts[parts.length-1]:""}}case"toList":{if(Array.isArray(value))return{ok:!0,value};let s=String(value).trim();if(s==="")return{ok:!0,value:[]};return{ok:!0,value:s.split(",").map((part)=>part.trim()).filter((part)=>part!=="")}}case"dateOnly":{let s=String(value).trim();if(s==="")return{ok:!0,value:null};let leading=s.match(/^\d{4}-\d{2}-\d{2}/);if(leading)return{ok:!0,value:leading[0]};let d=new Date(s);return Number.isNaN(d.getTime())?{ok:!1,reason:"not a date",raw:value}:{ok:!0,value:d.toISOString().slice(0,10)}}default:return{ok:!0,value}}}function isEmpty(v){return v==null||typeof v==="string"&&v.trim()===""}function mapRecord(external,mappings,parent){let row={},problems=[];for(let fm of mappings){if(!fm.target)continue;let value;if(fm.constant!=null&&fm.constant!=="")value=fm.constant;else{let raw=isTemplateSource(fm.source)?renderTemplate(fm.source,external,parent):readOne(external,parent,fm.source),result=applyTransform(raw,fm.transform);if(!result.ok)problems.push(`${fm.source} \u2192 ${fm.target}: ${result.reason} (${String(result.raw)})`),value=null;else value=result.value}if(isEmpty(value)&&fm.fallback!=null&&fm.fallback!==""){let raw=isTemplateSource(fm.fallback)?renderTemplate(fm.fallback,external,parent):fm.fallback,result=applyTransform(raw,fm.transform);if(result.ok)value=result.value;else problems.push(`fallback \u2192 ${fm.target}: ${result.reason} (${String(result.raw)})`),value=null}if(value!==void 0)row[fm.target]=value}return{row,problems}}function buildMappedRecords(externalRecords,mappings,dedupTargetField,parents){let records=[],issues=[];return externalRecords.forEach((ext,i)=>{let{row,problems}=mapRecord(ext,mappings,parents?.[i]);for(let message of problems)issues.push({sourceIndex:i,kind:"invalid_value",message});let dedupKey=dedupTargetField&&!isEmpty(row[dedupTargetField])?String(row[dedupTargetField]).trim():null;records.push({data:row,dedupKey,sourceIndex:i,external:ext,parent:parents?.[i]})}),{records,issues}}function flattenKeys(obj,prefix="",out=[],depth=0){if(out.length>200||depth>4||obj==null||typeof obj!=="object")return out;if(Array.isArray(obj)){if(prefix)out.push(prefix);return out}for(let[k,v]of Object.entries(obj)){let path8=prefix?`${prefix}.${k}`:k;if(v!=null&&typeof v==="object"&&!Array.isArray(v))flattenKeys(v,path8,out,depth+1);else out.push(path8)}return out}var MAX_FANOUT_COMBINATIONS=5000;function resolvePath2(rawPath,values){let missing=new Set,used=new Set;return{path:rawPath.replace(/\{([a-zA-Z_][\w-]*)\}|:([a-zA-Z_]\w*)/g,(_full,brace,colon)=>{let key2=brace??colon,v=values[key2];if(v==null||v==="")return missing.add(key2),brace?`{${key2}}`:`:${key2}`;return used.add(key2),encodeURIComponent(String(v))}),missing:[...missing],used}}function planFetchOrder(endpoints,roots){let byId=new Map(endpoints.map((e)=>[e.id,e])),order=[],settled=new Set,onPath=[],onPathSet=new Set,visit=(id,requiredBy)=>{if(settled.has(id))return null;if(onPathSet.has(id))return{ok:!1,reason:"cycle",chain:[...onPath.slice(onPath.indexOf(id)),id]};let node=byId.get(id);if(!node)return{ok:!1,reason:"unknown_endpoint",missing:id,requiredBy:requiredBy??id};onPath.push(id),onPathSet.add(id);for(let binding of node.paramBindings??[]){if(binding.from!=="endpoint")continue;let failure=visit(binding.endpointId,id);if(failure)return failure}return onPath.pop(),onPathSet.delete(id),settled.add(id),order.push(id),null};for(let id of roots??endpoints.map((e)=>e.id)){let failure=visit(id,null);if(failure)return failure}return{ok:!0,order}}function expandBindings(bindings,sources,limit=MAX_FANOUT_COMBINATIONS){if(!bindings||bindings.length===0)return{ok:!0,calls:[{values:{}}]};let axes=[];for(let binding of bindings){if(binding.from==="static"){axes.push({param:binding.param,options:[{value:binding.value}]});continue}if(binding.from==="endpoint"){let options=(sources.parents?.[binding.endpointId]??[]).map((record)=>({value:getByPath(record,binding.field),parent:record})).filter((o)=>o.value!=null&&o.value!=="");axes.push({param:binding.param,options});continue}let values=sources.entityValues?.[`${binding.entity}.${binding.field}`]??[];axes.push({param:binding.param,options:values.filter((v)=>v!=null&&v!=="").map((value)=>({value}))})}if(axes.some((a)=>a.options.length===0))return{ok:!0,calls:[]};let combinations=axes.reduce((n,a)=>n*a.options.length,1);if(combinations>limit)return{ok:!1,reason:"too_many",combinations,limit};let calls=[{values:{}}];for(let axis of axes){let next=[];for(let call of calls)for(let option of axis.options)next.push({values:{...call.values,[axis.param]:option.value},parent:option.parent??call.parent});calls=next}return{ok:!0,calls}}function parentEndpointIds(bindings){let ids=new Set;for(let b of bindings??[])if(b.from==="endpoint")ids.add(b.endpointId);return[...ids]}function entityValueKeys(bindings){let keys=new Set;for(let b of bindings??[])if(b.from==="entity")keys.add(`${b.entity}.${b.field}`);return[...keys]}var MAX_PAGES=1000,DEFAULT_PAGE_SIZE=200,initialState2=()=>({pagesFetched:0,recordsFetched:0,cursor:null});function firstPageParams(profile){switch(profile.kind){case"page_number":{let params={[profile.pageParam]:String(profile.firstPage??0)};if(profile.sizeParam)params[profile.sizeParam]=String(pageSize(profile));return params}case"offset":return{[profile.offsetParam]:"0",[profile.limitParam]:String(pageSize(profile))};case"cursor":{let params={};if(profile.sizeParam)params[profile.sizeParam]=String(pageSize(profile));return params}case"link_header":{let params={};if(profile.sizeParam)params[profile.sizeParam]=String(pageSize(profile));return params}default:return{}}}function reportedTotal(profile,body){let path8=profile.kind==="page_number"||profile.kind==="offset"?profile.totalPath:void 0;if(!path8)return null;let raw=getByPath(body,path8);if(typeof raw==="number"&&Number.isFinite(raw)&&raw>=0)return Math.floor(raw);if(typeof raw==="string"&&raw.trim()!==""){let n=Number(raw);if(Number.isFinite(n)&&n>=0)return Math.floor(n)}return null}function nextPage(profile,state,observed){if(profile.kind==="none")return{kind:"done",reason:"single request"};if(state.pagesFetched>=MAX_PAGES)return{kind:"failed",reason:`Paging stopped after ${MAX_PAGES} requests without reaching the end. The source may not be honouring the paging parameters; importing this would be a partial read.`};if(observed.recordCount===0)return{kind:"done",reason:"empty page"};switch(profile.kind){case"page_number":{if(isLastPage(profile.lastPagePath,observed.body))return{kind:"done",reason:"source reported the last page"};let total=reportedTotal(profile,observed.body);if(total!==null&&state.recordsFetched>=total)return{kind:"done",reason:"reported total reached"};if(observed.recordCount<pageSize(profile))return{kind:"done",reason:"short page"};let next=(profile.firstPage??0)+state.pagesFetched,params={[profile.pageParam]:String(next)};if(profile.sizeParam)params[profile.sizeParam]=String(pageSize(profile));return{kind:"params",params}}case"offset":{let total=reportedTotal(profile,observed.body);if(total!==null&&state.recordsFetched>=total)return{kind:"done",reason:"reported total reached"};if(observed.recordCount<pageSize(profile))return{kind:"done",reason:"short page"};return{kind:"params",params:{[profile.offsetParam]:String(state.recordsFetched),[profile.limitParam]:String(pageSize(profile))}}}case"cursor":{let raw=getByPath(observed.body,profile.nextCursorPath),next=raw==null?"":String(raw).trim();if(next==="")return{kind:"done",reason:"no further cursor"};if(state.cursor!=null&&next===state.cursor)return{kind:"failed",reason:`The source returned the same cursor twice (${next}); paging would not advance.`};let params={[profile.cursorParam]:next};if(profile.sizeParam)params[profile.sizeParam]=String(pageSize(profile));return{kind:"params",params}}case"link_header":{let url=parseNextLink(observed.linkHeader);if(!url)return{kind:"done",reason:"no rel=next link"};return{kind:"url",url}}default:return{kind:"done",reason:"single request"}}}function pageSize(profile){let declared="pageSize"in profile?profile.pageSize:void 0;return declared&&declared>0?declared:DEFAULT_PAGE_SIZE}function isLastPage(path8,body){if(!path8)return!1;let raw=getByPath(body,path8);if(typeof raw==="boolean")return raw;if(typeof raw==="string")return raw.trim().toLowerCase()==="true";return!1}function parseNextLink(header){if(!header)return null;for(let part of splitLinks(header)){let match=part.match(/<([^>]*)>(.*)/);if(!match)continue;let url=(match[1]??"").trim(),attrs=match[2]??"";if(!url)continue;if(/;\s*rel\s*=\s*["']?\s*next\s*["']?(\s*;|\s*$)/i.test(attrs))return url}return null}function splitLinks(header){let parts=[],depth=0,current="";for(let ch of header){if(ch==="<")depth++;else if(ch===">")depth--;if(ch===","&&depth===0){parts.push(current),current="";continue}current+=ch}if(current.trim()!=="")parts.push(current);return parts}var DEFAULT_MAX_CONCURRENT=4,DEFAULT_MAX_RECORDS=50000;async function collectOne(source,endpoint,params,deps,counters){let profile=endpoint.pagination??{kind:"none"},maxRecords=deps.maxRecords??DEFAULT_MAX_RECORDS,values={...endpoint.queryParams??{},...params.values},resolved=resolvePath2(endpoint.path,values);if(resolved.missing.length>0)return{ok:!1,error:`This endpoint needs path parameter(s) ${resolved.missing.map((m)=>`{${m}}`).join(", ")} and nothing supplies them. Add a parameter binding, or a static value.`};let baseQuery={};for(let[key2,value]of Object.entries(values)){if(value==null||resolved.used.has(key2))continue;baseQuery[key2]=value}let records=[],total=null,state=initialState2(),pageParams=firstPageParams(profile),absoluteUrl=null;for(;;){if(deps.isCancelled?.())return{ok:!1,error:"Cancelled."};let url;if(absoluteUrl)try{url=new URL(absoluteUrl)}catch{return{ok:!1,error:`The source returned an unusable next-page link: ${absoluteUrl}`}}else{let built=buildUrl(source.baseUrl,resolved.path,{...baseQuery,...pageParams});if(!built.ok)return{ok:!1,error:built.error};url=built.url}let headers={accept:"application/json"};if(deps.bearerToken)headers.Authorization=`Bearer ${deps.bearerToken}`;counters.calls++;let outcome=await fetchOnce({...source,token:deps.bearerToken??source.token},{method:endpoint.method,url,headers,body:endpoint.method.toUpperCase()==="GET"?void 0:endpoint.requestBody??{}},{fetchImpl:deps.fetchImpl});if(!outcome.ok)return{ok:!1,error:outcome.error??`HTTP ${outcome.status}`};let raw=extractRecords(outcome.body,endpoint.responseRootPath),childrenPath=treeChildrenPath(endpoint.treeChildrenPath),flattened=childrenPath?flattenTree(raw,childrenPath):null;if(flattened?.truncated)return{ok:!1,error:"This source answered with a structure that nests into itself. Nothing was imported \u2014 a company that contains itself has no order to write it in."};let page=flattened?flattened.records:raw;if(records.push(...page),counters.records+=page.length,total===null)total=reportedTotal(profile,outcome.body);if(counters.records>maxRecords)return{ok:!1,error:`This run would hold more than ${maxRecords} records at once. Narrow the source with a filter, or raise maxRecordsPerRun.`};deps.onProgress?.(counters.records),state={pagesFetched:state.pagesFetched+1,recordsFetched:records.length,cursor:pageParams[cursorParamOf(profile)??""]??state.cursor};let next=nextPage(profile,state,{recordCount:page.length,body:outcome.body,linkHeader:outcome.linkHeader});if(next.kind==="done")break;if(next.kind==="failed")return{ok:!1,error:next.reason};if(next.kind==="url"){absoluteUrl=next.url,pageParams={};continue}absoluteUrl=null,pageParams=next.params}return{ok:!0,records,total}}function cursorParamOf(profile){return profile.kind==="cursor"?profile.cursorParam:null}function describeCallFailure(call,error){let params=call.values??{},named=Object.entries(params).map(([key2,value])=>`${key2}=${String(value)}`).join(", ");return named?`${named}: ${error}`:error}async function collectEndpoint(source,endpoint,sources,deps={}){let counters={calls:0,records:0},expansion=expandBindings(endpoint.paramBindings??void 0,sources);if(!expansion.ok)return{ok:!1,callCount:0,error:`This endpoint would be called ${expansion.combinations} times (the ceiling is ${expansion.limit}). Narrow the parent list, or remove one of the parameter bindings.`};if(expansion.calls.length===0)return{ok:!0,records:[],reportedTotal:null,callCount:0};let limit=Math.max(1,deps.maxConcurrent??DEFAULT_MAX_CONCURRENT),collected=[],total=null,failure=null,partial=[],cursor=0,worker=async()=>{for(;;){if(failure||deps.isCancelled?.())return;let index=cursor++,call=expansion.calls[index];if(!call)return;let result=await collectOne(source,endpoint,call,deps,counters);if(!result.ok){if(expansion.calls.length>1){partial.push(describeCallFailure(call,result.error));continue}failure??=result.error;return}for(let record of result.records)collected.push({record,parent:call.parent});if(expansion.calls.length===1)total=result.total}};if(await Promise.all(Array.from({length:Math.min(limit,expansion.calls.length)},worker)),failure)return{ok:!1,error:failure,callCount:counters.calls};if(deps.isCancelled?.())return{ok:!1,error:"Cancelled.",callCount:counters.calls};if(partial.length>0&&collected.length===0&&partial.length===expansion.calls.length)return{ok:!1,error:`Every call to this endpoint failed. First: ${partial[0]}`,callCount:counters.calls};return{ok:!0,records:collected,reportedTotal:total,callCount:counters.calls,...partial.length>0?{partialFailures:partial}:{}}}function isDestructive(writeMode,missingPolicy){return writeMode==="replace"||missingPolicy==="delete"||missingPolicy==="deactivate"}function destructiveGate(input){if(!isDestructive(input.writeMode,input.missingPolicy))return{allowed:!0};if(input.partialFailures>0&&!input.scopedRemoval)return{allowed:!1,kind:"incomplete_source",message:`${input.partialFailures} call(s) in this source never answered, so part of it was not read. This run removes records the source does not send, and those unread records would be removed as if the source had dropped them. Fix the failing call, or switch this mapping to leave missing records alone.`};if(input.fetched===0)return{allowed:!1,kind:"incomplete_source",message:"The source returned no records at all. This run removes what the source does not send, so it would empty the target table. A source that is genuinely empty and one that could "+"not be read look the same from here, so this will not proceed on its own \u2014 preview it, "+"and if the source really is empty, remove the rows deliberately."};if(input.reported!==null&&input.fetched<input.reported)return{allowed:!1,kind:"incomplete_source",message:`The source reports ${input.reported} records but only ${input.fetched} were read. This run deletes what the source does not send, so it will not proceed on a partial read. Check the paging settings for this endpoint.`};return{allowed:!0}}function checkPlanVolume(input){if(input.maxShare<=0)return{allowed:!0};if(input.removing===0||input.existing===0)return{allowed:!0};let share=input.removing/input.existing;if(share<=input.maxShare)return{allowed:!0};let asPercent=(value)=>`${Math.round(value*100)}%`;return{allowed:!1,kind:"incomplete_source",message:`This run would remove ${input.removing} of ${input.existing} rows (${asPercent(share)}), which is above the ${asPercent(input.maxShare)} this mapping allows unattended. `+"A source can return perfectly good records and still produce a removal this large \u2014 a "+"changed dedup column, a repointed endpoint, a filter added upstream. Preview the run; if the removal is right, apply it deliberately."}}function orphanLinkNote(input){let{made,unresolved}=input;if(unresolved<=0)return null;let total=made+unresolved,share=total>0?unresolved/total:1,column=input.column?` (${input.column})`:"",consequence=`${unresolved} kay\u0131t ba\u011Flanaca\u011F\u0131 \xFCst\xFC bulamad\u0131${column} \u2014 bunlar a\u011Fac\u0131n EN \xDCST\xDCNDE, `+"genel m\xFCd\xFCrle ayn\u0131 seviyede g\xF6r\xFCn\xFCr.";if(share>=0.2)return`${consequence} Bu, ba\u011Flanabilenlerin (${made}) yan\u0131nda b\xFCy\xFCk bir oran: kaynak ya bu ki\u015Filerin `+"\xFCst\xFCn\xFC g\xF6ndermiyor ya da e\u015Fle\u015Ftirme alanlar\u0131ndan biri iki yerde farkl\u0131 yaz\u0131lm\u0131\u015F. "+"\u015Eemay\u0131 do\u011Fru sanmadan \xF6nce kayna\u011Fa bak\u0131n.";return`${consequence} ${made} ba\u011F kuruldu.`}function looksLikeKeyDrift(input){if(input.existing<=0)return!1;if(input.creating<=0||input.unmatched<=0)return!1;return input.creating/input.existing>=0.1&&input.unmatched/input.existing>=0.1}function keyDriftWarning(input){if(!looksLikeKeyDrift(input))return null;return`Bu ko\u015Fu ${input.creating} sat\u0131r ekleyecek ve burada duran ${input.unmatched} sat\u0131r\u0131 `+"kaynak art\u0131k g\xF6ndermiyor. \u0130kisinin birden bu kadar b\xFCy\xFCk olmas\u0131, kaynaktaki e\u015Fle\u015Ftirme "+"de\u011Ferlerinin de\u011Fi\u015Fti\u011Fine i\u015Faret eder \u2014 yani bunlar yeni kay\u0131tlar de\u011Fil, ayn\u0131 kay\u0131tlar\u0131n "+"yeni adlar\u0131. \u201CKaynakta olmayanlar: dokunma\u201D ile \xE7al\u0131\u015Ft\u0131r\u0131rsan\u0131z eskisi de yenisi de "+`kal\u0131r ve tablo ${input.existing+input.creating} sat\u0131ra \xE7\u0131kar; birbirine ba\u011Fl\u0131 `+"kay\u0131tlarda (organizasyon a\u011Fac\u0131 gibi) yeni sat\u0131rlar eski \xFCstlerini bulamaz ve yap\u0131 bozulur. "+"Ya politikay\u0131 silme/pasifle\u015Ftirme yap\u0131p bir kez temizleyin, ya da e\u015Fle\u015Ftirme s\xFCtununu "+"kayna\u011F\u0131n yeni de\u011Ferine g\xF6re d\xFCzeltin."}var referenceKey=(check)=>`${check.entity}.${check.entityColumn}`,pointsAtOwnTable=(check,targetEntity)=>check.entity===targetEntity;function referenceValuesOf(raw){if(Array.isArray(raw))return{values:raw.map((item)=>String(item??"").trim()).filter((item)=>item!==""),wasList:!0};if(raw===null||raw===void 0)return{values:[],wasList:!1};let single=String(raw).trim();return{values:single===""?[]:[single],wasList:!1}}var isEmptyReference=(raw)=>referenceValuesOf(raw).values.length===0;function resolveReference(raw,ids){let{values,wasList}=referenceValuesOf(raw),found=[],unmatched=[];for(let value of values){let id=ids?.[value];if(id===void 0)unmatched.push(value);else if(!found.includes(id))found.push(id)}return{ids:found,unmatched,wasList}}function resolvedColumnValue(resolution){return resolution.wasList?resolution.ids:resolution.ids[0]??null}function applyReferenceIds(row,references,ids,targetEntity){let next={...row},deferred=[];for(let check of references){if(!check.writeIdTo)continue;let raw=row[check.column];if(pointsAtOwnTable(check,targetEntity)){if(next[check.writeIdTo]=Array.isArray(raw)?[]:null,!isEmptyReference(raw))deferred.push({check,raw});continue}next[check.writeIdTo]=resolvedColumnValue(resolveReference(raw,ids[referenceKey(check)]))}return{row:next,deferred}}function unambiguousIds(rows){let seen=new Map;for(let row of rows){if(row.value==null||row.id==null)continue;let key2=String(row.value).trim();if(key2==="")continue;seen.set(key2,seen.has(key2)?null:String(row.id))}let ids={};for(let[key2,id]of seen)if(id!==null)ids[key2]=id;return ids}function ambiguousValues(rows){let counts=new Map;for(let row of rows){if(row.value==null||row.id==null)continue;let key2=String(row.value).trim();if(key2==="")continue;counts.set(key2,(counts.get(key2)??0)+1)}return[...counts.entries()].filter(([,n])=>n>1).map(([key2])=>key2)}var UNRESOLVED_TEMPLATE=/^\s*(\$\{[^}]*\}|\{\{[^}]*\}\})\s*$/,isEmpty2=(v)=>v==null||typeof v==="string"&&(v.trim()===""||UNRESOLVED_TEMPLATE.test(v));function displayValue(value){if(value!==null&&typeof value==="object")try{return JSON.stringify(value)}catch{return"(a value that cannot be shown)"}return String(value)}function buildFallbackIdentifier(format2,data){let complete=!0,rendered=format2.replace(/\{([^{}]+)\}/g,(_match,path8)=>{let value=data[path8.trim()];if(value==null||String(value).trim()==="")complete=!1;return value==null?"":String(value)});if(!complete)return null;let cleaned=foldToAscii(rendered).toLowerCase().trim().replace(/[^a-z0-9._@+-]+/g,".").replace(/\.{2,}/g,".").replace(/\.*@\.*/g,"@").replace(/^[.\-_]+|[.\-_]+$/g,"");return cleaned===""?null:cleaned}function missingReferences(row,references,known){let broken=[];for(let check of references){let raw=row[check.column];if(isEmpty2(raw))continue;let value=displayValue(raw).trim(),present=known[`${check.entity}.${check.entityColumn}`];if(!present)continue;if(!present.has(value))broken.push({check,value,raw})}return broken}async function loadReferenceValues(references,read){let values={};for(let check of references){let key2=`${check.entity}.${check.entityColumn}`;if(values[key2])continue;let rows=await read(check.entity,check.entityColumn);values[key2]=new Set(rows.filter((v)=>!isEmpty2(v)).map((v)=>String(v).trim()))}return values}async function loadReferenceIds(references,targetEntity,read){let ids={},ambiguous={};for(let check of references){if(!check.writeIdTo)continue;if(pointsAtOwnTable(check,targetEntity))continue;let key2=referenceKey(check);if(ids[key2])continue;let pairs=await read(check.entity,check.entityColumn);ids[key2]=unambiguousIds(pairs);let shared=ambiguousValues(pairs);if(shared.length>0)ambiguous[key2]=shared}return{ids,ambiguous}}function ambiguityWarnings(ambiguous){return Object.entries(ambiguous).map(([key2,values])=>{let shown=values.slice(0,5).join(", "),rest=values.length>5?` and ${values.length-5} more`:"";return`${values.length} value(s) in ${key2} belong to more than one row \u2014 ${shown}${rest}. Records pointing at them are left unlinked rather than linked to whichever row came first.`})}function planWrites(input){let{records,existing,dedupTargetField,writeMode,missingPolicy,missingColumn,missingValue,removalScope=null,originColumn,originValue,requiredFields=[],uniqueFields=[],createDefaults={},accountRule=null,existingAccounts={},references=[],referenceValues={},referenceIds={},targetEntity=""}=input,issues=[],warnings=[],creates=[],referenceInserts=[],accountInserts=[],accountJoinInserts=[],plannedAccounts=new Set,plannedRefs=new Set,updates=[],deletes=[],deactivates=[],departures=[],deferredLinks=[],dedupConfigured=Boolean(dedupTargetField),accountClaims=new Map,accountIdIsUnique=accountRule?uniqueFields.includes(accountRule.idColumn):!1,fillIdentifier=(data)=>{let format2=accountRule?.emailFormat?.trim();if(!accountRule||!format2)return data;if(!isEmpty2(data[accountRule.matchFrom]))return data;let built=buildFallbackIdentifier(format2,data);return built===null?data:{...data,[accountRule.matchFrom]:built}},withAccount=(record,input2)=>{if(!accountRule)return input2;let data=fillIdentifier(input2),raw=data[accountRule.matchFrom];if(isEmpty2(raw))return issues.push({sourceIndex:record.sourceIndex,kind:"account_unmatched",field:accountRule.matchFrom,message:`${accountRule.matchFrom} is empty, so this record gets no account \u2014 it is imported without one.`,dedupKey:record.dedupKey,row:data}),data;let value=String(raw).trim(),claimedBy=accountClaims.get(value);if(claimedBy&&accountIdIsUnique)return issues.push({sourceIndex:record.sourceIndex,kind:"duplicate_value",field:accountRule.matchFrom,value:String(value),message:`${accountRule.matchFrom} is \u201C${value}\u201D, which another record in this import already uses \u2014 and ${accountRule.idColumn} allows one record per account. This one is left out.`,dedupKey:record.dedupKey,row:data,keptRow:claimedBy.data}),null;accountClaims.set(value,record);let existingId=existingAccounts[value];if(existingId)return{...data,[accountRule.idColumn]:existingId};if(!plannedAccounts.has(value)){plannedAccounts.add(value);let accountData={[accountRule.matchColumn]:value};for(let pair of accountRule.values??[]){let from=data[pair.from];if(!isEmpty2(from))accountData[pair.column]=from}accountInserts.push({entity:accountRule.entity,matchColumn:accountRule.matchColumn,matchValue:value,data:accountData});for(let join7 of accountRule.joins??[])accountJoinInserts.push({entity:join7.entity,accountColumn:join7.accountColumn,values:join7.values,matchValue:value})}return data},hasDefaults=Object.keys(createDefaults).length>0,stamp2=originColumn?{[originColumn]:originValue}:{},newRecord=(data)=>hasDefaults?{...createDefaults,...data,...stamp2}:{...data,...stamp2},existingByKey=new Map;if(dedupTargetField)for(let row of existing){let value=row.row[dedupTargetField];if(!isEmpty2(value))existingByKey.set(String(value).trim(),row)}let claimedUnique=new Map;for(let field of uniqueFields){let taken=new Map;for(let existingRow of existing){let value=existingRow.row[field];if(!isEmpty2(value))taken.set(String(value).trim(),existingRow.id)}claimedUnique.set(field,taken)}let ownsRow=(row)=>{if(!originColumn)return!0;let value=row.row[originColumn];return String(value??"")===String(originValue??"")},matchedIds=new Set,seenIds=new Set,seenInBatch=new Map;for(let sourceRecord of records){let broken=missingReferences(sourceRecord.data,references,referenceValues),resolvedRow=applyReferenceIds(sourceRecord.data,references,referenceIds,targetEntity),record={...sourceRecord,data:fillIdentifier(resolvedRow.row)};if(record.dedupKey!=null){let carried=existingByKey.get(record.dedupKey);if(carried)seenIds.add(carried.id)}for(let link of resolvedRow.deferred){if(!dedupTargetField)continue;let matchValue=record.data[dedupTargetField];if(isEmpty2(matchValue))continue;deferredLinks.push({matchColumn:dedupTargetField,matchValue:String(matchValue).trim(),writeIdTo:link.check.writeIdTo,lookupColumn:link.check.entityColumn,raw:link.raw,isList:Array.isArray(link.raw)})}let blocking=broken.find((b)=>b.check.onMissing==="skipRecord");if(blocking){let{check,value}=blocking;issues.push({sourceIndex:record.sourceIndex,kind:"missing_reference",message:typeof blocking.raw==="object"&&blocking.raw!==null?`${check.column} is not a single value but a whole object \u2014 ${value}. Point the mapping at one field of it, e.g. \`${check.column}.code\`, and it will have something to match against ${check.entity}.${check.entityColumn}.`:`${check.column} is \u201C${value}\u201D, which does not exist in ${check.entity}.${check.entityColumn} \u2014 this record is left out.`,dedupKey:record.dedupKey,row:record.data,reference:{column:check.column,value,entity:check.entity,entityColumn:check.entityColumn}});continue}let keepReferences=()=>{for(let{check,value}of broken){if(check.onMissing!=="create")continue;let token=`${check.entity}.${check.entityColumn}::${value}`;if(plannedRefs.has(token))continue;plannedRefs.add(token);let data={};for(let pair of check.createValues??[]){let fromSource=isTemplateSource(pair.from)?renderTemplate(pair.from,record.external,record.parent):readSourceValue(record.external,record.parent,pair.from),value2=isEmpty2(fromSource)?record.data[pair.from]:fromSource;if(!isEmpty2(value2))data[pair.column]=value2}referenceInserts.push({entity:check.entity,column:check.entityColumn,value,...Object.keys(data).length>0?{data}:{}})}},uniqueCollision=(data,ownRowId)=>{for(let field of uniqueFields){let raw=data[field];if(isEmpty2(raw))continue;let value=String(raw).trim(),holder2=claimedUnique.get(field)?.get(value);if(holder2===void 0)continue;if(holder2!==null&&holder2===ownRowId)continue;return{field,value}}return null},claimUnique=(data,rowId)=>{for(let field of uniqueFields){let raw=data[field];if(isEmpty2(raw))continue;claimedUnique.get(field)?.set(String(raw).trim(),rowId)}},collide=(field,value)=>{issues.push({sourceIndex:record.sourceIndex,kind:"duplicate_value",field,value:String(value),message:`${field} is \u201C${value}\u201D, which something else already has \u2014 ${field} has to be unique, so this record is left out.`,dedupKey:record.dedupKey,row:record.data})},missingRequired=requiredFields.filter((f)=>isEmpty2(record.data[f])&&isEmpty2(createDefaults[f]));if(missingRequired.length>0){issues.push({sourceIndex:record.sourceIndex,kind:"missing_required",field:missingRequired.join(", "),message:`Required field(s) empty: ${missingRequired.join(", ")}`,dedupKey:record.dedupKey,row:record.data});continue}if(!dedupConfigured){let clash2=uniqueCollision(record.data,null);if(clash2){collide(clash2.field,clash2.value);continue}keepReferences(),claimUnique(record.data,null);let withLogin=withAccount(record,newRecord(record.data));if(!withLogin)continue;creates.push({data:withLogin,sourceIndex:record.sourceIndex});continue}if(record.dedupKey==null){let clash2=uniqueCollision(record.data,null);if(clash2){collide(clash2.field,clash2.value);continue}issues.push({sourceIndex:record.sourceIndex,kind:"missing_dedup_key",message:"Deduplication field is empty on this record \u2014 it will be added as new."}),keepReferences(),claimUnique(record.data,null);let withLogin=withAccount(record,newRecord(record.data));if(!withLogin)continue;creates.push({data:withLogin,sourceIndex:record.sourceIndex});continue}let claimedBy=seenInBatch.get(record.dedupKey);if(claimedBy){issues.push({sourceIndex:record.sourceIndex,kind:"duplicate_in_batch",value:String(record.dedupKey??""),message:`The source carries this key more than once: ${record.dedupKey} \u2014 this occurrence is skipped.`,dedupKey:record.dedupKey,row:record.data,keptRow:claimedBy});continue}if(seenInBatch.set(record.dedupKey,record.data),writeMode==="replace"||writeMode==="append"){let clash2=uniqueCollision(record.data,null);if(clash2&&!(writeMode==="replace"&&claimedUnique.get(clash2.field)?.get(clash2.value))){collide(clash2.field,clash2.value);continue}keepReferences(),claimUnique(record.data,null);let withLogin=withAccount(record,newRecord(record.data));if(!withLogin)continue;creates.push({data:withLogin,sourceIndex:record.sourceIndex});continue}let match=existingByKey.get(record.dedupKey),clash=uniqueCollision(record.data,match?.id??null);if(clash){collide(clash.field,clash.value);continue}if(keepReferences(),claimUnique(record.data,match?.id??null),match)matchedIds.add(match.id),updates.push({id:match.id,data:{...record.data,...stamp2},before:match.row,sourceIndex:record.sourceIndex});else{let withLogin=withAccount(record,newRecord(record.data));if(!withLogin)continue;creates.push({data:withLogin,sourceIndex:record.sourceIndex})}}if(writeMode==="replace")deletes.push(...existing);else if(writeMode==="upsert"&&missingPolicy!=="ignore"){let wasRead=(row)=>{if(!removalScope)return!0;let value=row.row[removalScope.column];if(isEmpty2(value))return!1;return removalScope.readValues.includes(String(value).trim())},gone=existing.filter((row)=>!seenIds.has(row.id)).filter((row)=>ownsRow(row)).filter(wasRead);if(missingPolicy==="delete")deletes.push(...gone);else deactivates.push(...gone);departures.push(...gone)}if(writeMode==="upsert"&&missingPolicy==="ignore"){let owned=existing.filter((row)=>ownsRow(row)),unmatched=owned.filter((row)=>!seenIds.has(row.id)).length,drift=keyDriftWarning({creating:creates.length,unmatched,existing:owned.length});if(drift)warnings.push(drift)}if(!dedupConfigured&&writeMode==="upsert")warnings.push("No deduplication field is set. Nothing can be matched against what is already here, so every record is added as new and each run will duplicate the last.");if(dedupConfigured&&records.length>0&&records.every((r)=>r.dedupKey==null))warnings.push(`The deduplication field is empty on every record \u2014 it is probably not among the mapped fields. As it stands nothing can ever match: all ${records.length} records will be re-added on every run.`);if(writeMode==="append"&&dedupConfigured)warnings.push("Append mode ignores the deduplication field: records already here will be added again.");if(writeMode==="replace"){if(warnings.push(`Replace mode: all ${existing.length} rows currently in the table are deleted and rebuilt from the source. Row identifiers change, so anything referring to them by id breaks.`),dedupConfigured)warnings.push('A deduplication field is set, so "update existing" would keep the current rows and their identifiers. Replace mode is only necessary when records cannot be matched at all.')}if(deactivates.length>0&&(!missingColumn||isEmpty2(missingValue)))warnings.push('The policy for records missing from the source is "deactivate", but no column and value are configured \u2014 those rows will be left untouched.'),deactivates.length=0;return{creates,updates,deletes,deactivates,departures,deferredLinks,issues,warnings,referenceInserts,accountInserts,accountJoinInserts}}var SKIPPING_ISSUE_KINDS=new Set(["missing_required","duplicate_in_batch","duplicate_value","invalid_value","missing_reference"]);function skippedRecordCount(issues){let records=new Set;for(let issue of issues){if(!SKIPPING_ISSUE_KINDS.has(issue.kind))continue;if(issue.sourceIndex<0)continue;records.add(issue.sourceIndex)}return records.size}function summarize(ops,meta){let sampleSize=meta.sampleSize??8,sample=[...ops.creates.map((c)=>c.data),...ops.updates.map((u)=>u.data)].slice(0,sampleSize);return{targetEntity:meta.targetEntity,writeMode:meta.writeMode,totalFetched:meta.totalFetched,reportedTotal:meta.reportedTotal,toCreate:ops.creates.length,toUpdate:ops.updates.length,toSkip:skippedRecordCount(ops.issues),missing:ops.deletes.length+ops.deactivates.length,missingPolicy:meta.missingPolicy,existingCount:meta.existingCount,dedupConfigured:meta.dedupConfigured,issues:ops.issues,warnings:ops.warnings,referenceInserts:ops.referenceInserts,accountsToCreate:ops.accountInserts.length,sample}}function removalScopeFor(column,records){if(!column)return null;let readValues=new Set;for(let record of records){let value=record.data[column];if(!isEmpty2(value))readValues.add(String(value).trim())}return{column,readValues:[...readValues]}}import{and as and15,eq as eq30,inArray as inArray11}from"drizzle-orm";var INSERT_CHUNK=500,DELETE_CHUNK=1000;function validateAll(ops,columns,validatePayload2){let issues=[];for(let op of ops.creates){let result=validatePayload2(op.data,columns,!1);if(!result.valid)issues.push({sourceIndex:op.sourceIndex,kind:"invalid_value",message:result.errors.map((e)=>`${e.field}: ${e.message}`).join("; "),row:op.data})}for(let op of ops.updates){let result=validatePayload2(op.data,columns,!0);if(!result.valid)issues.push({sourceIndex:op.sourceIndex,kind:"invalid_value",message:result.errors.map((e)=>`${e.field}: ${e.message}`).join("; "),row:op.data})}return issues}function referenceRow(columns,column,value,extra){let row={...extra,[column]:value},unfillable=[];for(let col8 of columns){let name2=camel(col8.name);if(name2===column)continue;if(SYSTEM_COLUMNS.has(name2))continue;if(row[name2]!==void 0)continue;if(!(col8.notNull===!0&&col8.default===void 0&&!col8.defaultRaw&&!col8.nullable))continue;if(TEXTUAL_TYPES.has(String(col8.type)))row[name2]=value;else unfillable.push(name2)}return unfillable.length>0?{ok:!1,unfillable}:{ok:!0,row}}var SYSTEM_COLUMNS=new Set(["id","createdAt","updatedAt","createdBy","updatedBy"]),TEXTUAL_TYPES=new Set(["text","varchar","char"]),camel=(s)=>s.replace(/_([a-z])/g,(_m,l)=>l.toUpperCase());function linkAccount(data,rule,idByValue){let value=data[rule.matchFrom];if(value==null)return{};let id=idByValue.get(String(value).trim());return id?{[rule.idColumn]:id}:{}}function groupDeferred(links){let groups=new Map;for(let link of links){let key2=`${link.writeIdTo}|${link.lookupColumn}|${link.matchColumn}`,group=groups.get(key2)??{writeIdTo:link.writeIdTo,lookupColumn:link.lookupColumn,matchColumn:link.matchColumn,links:[]};group.links.push(link),groups.set(key2,group)}return[...groups.values()]}async function applyWrites(deps,input){let{ops,targetEntity,userId}=input,scope=input.scopeConditions??[],writeIssues=[],cancelled=()=>input.isCancelled?.()===!0,invalid=validateAll(ops,deps.columns,deps.validatePayload);if(invalid.length>0)return{ok:!1,failure:{kind:"validation_failed",message:`${invalid.length} record(s) did not pass validation; nothing was written.`,issues:invalid}};let refGroups=new Map;for(let insert of ops.referenceInserts){let resolved=deps.resolveEntity?.(insert.entity);if(!resolved)return{ok:!1,failure:{kind:"write_failed",message:`This mapping would add \u201C${insert.value}\u201D to "${insert.entity}", which does not exist.`}};let built=referenceRow(resolved.columns,insert.column,insert.value,insert.data);if(!built.ok)return{ok:!1,failure:{kind:"write_failed",message:`\u201C${insert.value}\u201D cannot be added to "${insert.entity}" automatically: ${built.unfillable.join(", ")} is required and cannot be filled from a ${insert.column}. Add the missing ${insert.entity} by hand, or set this reference to leave those records out.`}};let group=refGroups.get(insert.entity)??{table:resolved.table,rows:[]};group.rows.push(built.row),refGroups.set(insert.entity,group)}let accountRule=input.account??null,accountEntity=ops.accountInserts[0]?.entity,accountTable=accountEntity?deps.resolveEntity?.(accountEntity):null;if(ops.accountInserts.length>0&&(!accountRule||!accountTable))return{ok:!1,failure:{kind:"write_failed",message:accountRule?`This import creates accounts in "${accountEntity}", which does not exist.`:"This import creates accounts but no password was supplied, so nothing was written."}};if(cancelled())return{ok:!1,failure:{kind:"cancelled",message:"Cancelled before writing."}};let idCol=deps.resolveCol("id");if(!idCol)return{ok:!1,failure:{kind:"write_failed",message:`Target "${targetEntity}" has no id column; the engine cannot address its rows.`}};let preImages=[],now=new Date,deactivating=ops.deactivates.length>0&&input.missingColumn&&input.missingValue!=null?{column:input.missingColumn,value:input.missingValue}:null;try{let linksMade=0,linksUnresolved=0;return{ok:!0,...await deps.db.transaction(async(tx)=>{let created=0,accountsCreated=0,referencesCreated=0,updated=0,deleted=0,deactivated=0,accountsClosed=0;if(ops.deletes.length>0){let ids=ops.deletes.map((r)=>r.id);for(let i=0;i<ids.length;i+=DELETE_CHUNK){if(cancelled())throw new CancelledError;let chunk=ids.slice(i,i+DELETE_CHUNK),where=scope.length?and15(inArray11(idCol,chunk),...scope):inArray11(idCol,chunk),removed=await tx.delete(deps.drizzleTable).where(where).returning();deleted+=removed.length;for(let row of removed)preImages.push({targetEntity,rowId:String(row.id),action:"delete",before:row,after:null})}}for(let op of ops.updates){if(cancelled())throw new CancelledError;let where=scope.length?and15(eq30(idCol,op.id),...scope):eq30(idCol,op.id),written=await tx.update(deps.drizzleTable).set({...op.data,updatedAt:now,updatedBy:userId}).where(where).returning();if(written.length===0)throw new ScopeError(op.id);updated+=written.length,preImages.push({targetEntity,rowId:op.id,action:"update",before:op.before,after:written[0]??null})}if(deactivating){let ids=ops.deactivates.map((r)=>r.id);for(let i=0;i<ids.length;i+=DELETE_CHUNK){if(cancelled())throw new CancelledError;let chunk=ids.slice(i,i+DELETE_CHUNK),where=scope.length?and15(inArray11(idCol,chunk),...scope):inArray11(idCol,chunk),written=await tx.update(deps.drizzleTable).set({[deactivating.column]:deactivating.value,updatedAt:now,updatedBy:userId}).where(where).returning();deactivated+=written.length;let beforeById=new Map(ops.deactivates.map((r)=>[r.id,r.row]));for(let row of written){let id=String(row.id);preImages.push({targetEntity,rowId:id,action:"deactivate",before:beforeById.get(id)??null,after:row})}}}if(deps.accountClosure){let written=new Set(preImages.filter((image)=>image.action==="delete"||image.action==="deactivate").map((image)=>image.rowId)),removedRows=ops.departures.filter((row)=>written.has(row.id)).map((row)=>row.row),leaverIds=accountIdsIn(removedRows,deps.accountClosure.userColumn);if(leaverIds.length>0){let closed=await closeAccounts({db:tx,usersTable:deps.accountClosure.usersTable,sessionsTable:deps.accountClosure.sessionsTable,atomic:!0,onError:(error)=>{deps.logger.error("[Integrations] A departure\u2019s account stayed open",{error})}},leaverIds);accountsClosed=closed.closed;for(let userId2 of closed.closedIds)preImages.push({targetEntity:deps.accountClosure.accountEntity,rowId:userId2,action:"update",before:{isActive:!0},after:{isActive:!1}});if(closed.closed>0&&!closed.signedOut)writeIssues.push({sourceIndex:-1,kind:"account_sessions_not_cleared",value:String(closed.closed),message:`${closed.closed} account(s) behind removed records were deactivated, but their open sessions could not be cleared \u2014 those people stay signed in until the session expires.`})}}for(let[entity,group]of refGroups){let rows=group.rows.map((r)=>({...r,createdAt:now,updatedAt:now,createdBy:userId}));for(let i=0;i<rows.length;i+=INSERT_CHUNK){if(cancelled())throw new CancelledError;let written=await tx.insert(group.table).values(rows.slice(i,i+INSERT_CHUNK)).returning();referencesCreated+=written.length;for(let row of written)preImages.push({targetEntity:entity,rowId:row.id?String(row.id):null,action:"create",before:null,after:row})}}let accountIdByValue=new Map;if(accountRule&&accountTable&&ops.accountInserts.length>0){let rows=ops.accountInserts.map((account)=>({...account.data,[accountRule.passwordColumn]:accountRule.passwordHash,createdAt:now,updatedAt:now,createdBy:userId}));for(let i=0;i<rows.length;i+=INSERT_CHUNK){if(cancelled())throw new CancelledError;let written=await tx.insert(accountTable.table).values(rows.slice(i,i+INSERT_CHUNK)).returning();accountsCreated+=written.length;for(let row of written){let value=row[accountRule.matchColumn];if(row.id!=null&&value!=null)accountIdByValue.set(String(value).trim(),String(row.id));preImages.push({targetEntity:ops.accountInserts[0]?.entity??"",rowId:row.id?String(row.id):null,action:"create",before:null,after:row})}}}if(accountRule&&ops.accountJoinInserts.length>0){let byEntity=new Map;for(let join7 of ops.accountJoinInserts){let accountId=accountIdByValue.get(join7.matchValue);if(!accountId){writeIssues.push({sourceIndex:-1,kind:"account_role_missing",message:`No account was found for \u201C${join7.matchValue}\u201D, so its ${join7.entity} row was not written \u2014 that person can sign in and do nothing.`});continue}let rows=byEntity.get(join7.entity)??[];rows.push({...join7.values,[join7.accountColumn]:accountId,createdAt:now,updatedAt:now,createdBy:userId}),byEntity.set(join7.entity,rows)}for(let[entity,rows]of byEntity){let resolved=deps.resolveEntity?.(entity);if(!resolved){writeIssues.push({sourceIndex:-1,kind:"account_role_missing",message:`The \u201C${entity}\u201D table is not available here, so ${rows.length} role membership(s) were not written. The accounts exist but hold no role.`});continue}for(let i=0;i<rows.length;i+=INSERT_CHUNK){if(cancelled())throw new CancelledError;let written=await tx.insert(resolved.table).values(rows.slice(i,i+INSERT_CHUNK)).returning();for(let row of written)preImages.push({targetEntity:entity,rowId:row.id?String(row.id):null,action:"create",before:null,after:row})}}}if(ops.creates.length>0){let rows=ops.creates.map((c)=>({...c.data,...accountRule&&c.data[accountRule.idColumn]==null?linkAccount(c.data,accountRule,accountIdByValue):{},createdAt:now,updatedAt:now,createdBy:userId}));for(let i=0;i<rows.length;i+=INSERT_CHUNK){if(cancelled())throw new CancelledError;let chunk=rows.slice(i,i+INSERT_CHUNK),written=await tx.insert(deps.drizzleTable).values(chunk).returning();created+=written.length;for(let row of written)preImages.push({targetEntity,rowId:row.id?String(row.id):null,action:"create",before:null,after:row})}}if(ops.deferredLinks.length>0)for(let group of groupDeferred(ops.deferredLinks)){if(cancelled())throw new CancelledError;let lookupCol=deps.resolveCol(group.lookupColumn),matchCol=deps.resolveCol(group.matchColumn),targetCol=deps.resolveCol(group.writeIdTo);if(!lookupCol||!matchCol||!targetCol){deps.logger.error(`[Integrations] Cannot fill "${group.writeIdTo}": ${[!lookupCol?group.lookupColumn:null,!matchCol?group.matchColumn:null,!targetCol?group.writeIdTo:null].filter(Boolean).join(", ")} is not a column of "${targetEntity}".`);continue}let rows=await tx.select({v:lookupCol,id:idCol}).from(deps.drizzleTable),idByValue={};for(let row of rows){if(row.v==null||row.v===""||row.id==null)continue;let key2=String(row.v).trim();if(!idByValue[key2])idByValue[key2]=String(row.id)}let imageByMatch=new Map;for(let image of preImages){let value=image.after?.[group.matchColumn];if(value!=null)imageByMatch.set(String(value).trim(),image)}for(let link of group.links){let resolution=resolveReference(link.raw,idByValue);if(resolution.ids.length===0){linksUnresolved+=1;continue}let value=link.isList?resolution.ids:resolution.ids[0],where=scope.length?and15(eq30(matchCol,link.matchValue),...scope):eq30(matchCol,link.matchValue);if((await tx.update(deps.drizzleTable).set({[group.writeIdTo]:value}).where(where).returning()).length===0){linksUnresolved+=1;continue}linksMade+=1;let image=imageByMatch.get(String(link.matchValue).trim());if(image?.after)image.after={...image.after,[group.writeIdTo]:value}}}return{created,accountsCreated,referencesCreated,updated,deleted,deactivated,accountsClosed,linksMade,linksUnresolved}}),preImages,issues:writeIssues}}catch(error){if(error instanceof CancelledError)return{ok:!1,failure:{kind:"cancelled",message:"Cancelled while writing; the transaction was rolled back and nothing changed."}};if(error instanceof ScopeError)return{ok:!1,failure:{kind:"write_failed",message:`Row ${error.rowId} is outside what this account may write. Nothing was written.`}};return deps.logger.error(`[Integrations] Write transaction failed for "${targetEntity}": ${reasonOf2(error)}`),{ok:!1,failure:{kind:"write_failed",message:"The database rejected this import; it was rolled back and nothing changed."}}}}function reasonOf2(error){if(!(error instanceof Error))return String(error);let extra=error;return[error.message,extra.detail?`detail: ${String(extra.detail)}`:"",extra.constraint?`constraint: ${String(extra.constraint)}`:"",extra.hint?`hint: ${String(extra.hint)}`:"",extra.code?`code: ${String(extra.code)}`:""].filter(Boolean).join(" \u2014 ")}class CancelledError extends Error{constructor(){super("cancelled");this.name="CancelledError"}}class ScopeError extends Error{rowId;constructor(rowId){super(`row ${rowId} outside scope`);this.rowId=rowId;this.name="ScopeError"}}var DAY_MS=86400000;async function executeRun(context,deps,lock){let{mapping,source}=context,empty={runId:null,status:"failed",failure:null,plan:null,created:0,accountsCreated:0,referencesCreated:0,updated:0,deleted:0,deactivated:0,externalCalls:0,issues:[]},opened=await deps.repo.openRun({mappingId:mapping.id,targetEntity:mapping.targetEntity,writeMode:mapping.writeMode,trigger:context.trigger,userId:context.userId});if(!opened.ok)return{...empty,failure:{kind:"write_failed",message:`Could not open a run record: ${opened.error}`}};let runId=opened.runId;deps.onRunOpened?.(runId);let cancelChecked=0,cancelSeen=!1,isCancelled=()=>{if(cancelSeen)return!0;if(deps.abortSignal?.aborted)return cancelSeen=!0,!0;if(!lock.isHeld())return cancelSeen=!0,!0;return!1},refreshCancelFlag=async()=>{if(cancelChecked++,await deps.repo.isCancelRequested(runId))cancelSeen=!0},progress=(p)=>deps.publishProgress?.({runId,...p}),preImagesStored=!0,finish=async(outcome)=>{let revertible=outcome.status==="succeeded"&&preImagesStored;return await deps.repo.closeRun(runId,{status:outcome.status,totalFetched:outcome.plan?.totalFetched??0,sourceReportedTotal:outcome.plan?.reportedTotal??null,createdCount:outcome.created,accountsCreatedCount:outcome.accountsCreated,referencesCreatedCount:outcome.referencesCreated,updatedCount:outcome.updated,skippedCount:outcome.plan?.toSkip??0,deletedCount:outcome.deleted,deactivatedCount:outcome.deactivated,errorCount:outcome.failure?1:0,externalCallCount:outcome.externalCalls,issues:outcome.issues,errors:outcome.failure?[outcome.failure.message]:[],finishedAt:new Date,preImagesExpireAt:revertible?new Date(Date.now()+(deps.retainPreImagesMs??30*DAY_MS)):null}),progress({phase:"done",message:outcome.failure?.message}),{runId,...outcome}};progress({phase:"fetching"});let nodes=context.endpoints.map((e)=>({id:e.id,paramBindings:e.paramBindings??void 0})),order=planFetchOrder(nodes,[context.rootEndpointId]);if(!order.ok){let failure=order.reason==="cycle"?{kind:"cycle_detected",message:`These endpoints depend on each other in a loop (${order.chain.join(" \u2192 ")}), so there is no correct place to start.`,chain:order.chain}:{kind:"fetch_failed",message:`"${order.requiredBy}" takes a parameter from an endpoint that no longer exists (${order.missing}).`};return finish({...empty,failure,status:"failed"})}let bearerToken=null;if(context.oauth){let token=await getAccessToken(context.oauth,deps.tokenCache,{fetchImpl:deps.fetchImpl});if(!token.ok)return finish({...empty,failure:{kind:"fetch_failed",message:token.error}});bearerToken=token.accessToken}let byId=new Map(context.endpoints.map((e)=>[e.id,e])),parents={},entityValues={},externalCalls=0,rootRecords=[],fetchWarnings=[],reportedTotal2=null;for(let endpointId of order.order){let endpoint=byId.get(endpointId);if(!endpoint)continue;if(await refreshCancelFlag(),isCancelled())return finish({...empty,status:"cancelled",externalCalls,failure:{kind:"cancelled",message:"Cancelled before anything was written."}});for(let key2 of entityValueKeys(endpoint.paramBindings??void 0)){if(entityValues[key2])continue;let[entity,field]=key2.split(".");entityValues[key2]=await deps.repo.readEntityColumn(entity,field)}let collected=await collectEndpoint(source,endpoint,{parents,entityValues},{fetchImpl:deps.fetchImpl,bearerToken,maxConcurrent:deps.maxConcurrentFanout,maxRecords:deps.maxRecordsPerRun,isCancelled,onProgress:(n)=>progress({phase:"fetching",processed:n})});if(externalCalls+=collected.callCount,!collected.ok){let cancelled=isCancelled();return finish({...empty,externalCalls,status:cancelled?"cancelled":"failed",failure:cancelled?{kind:"cancelled",message:"Cancelled before anything was written."}:{kind:"fetch_failed",message:collected.error}})}if(collected.partialFailures?.length)fetchWarnings.push(...collected.partialFailures.map((failure)=>`Could not read part of this source \u2014 ${failure}`));if(parents[endpointId]=collected.records.map((r)=>r.record),endpointId===context.rootEndpointId)rootRecords=collected.records,reportedTotal2=collected.reportedTotal}for(let id of Object.keys(parents))if(!(id===context.rootEndpointId||context.endpoints.some((e)=>parentEndpointIds(e.paramBindings??void 0).includes(id))))delete parents[id];let verdict=destructiveGate({writeMode:mapping.writeMode,missingPolicy:mapping.missingPolicy,fetched:rootRecords.length,reported:reportedTotal2,partialFailures:fetchWarnings.length,scopedRemoval:Boolean(mapping.removalScopeColumn)});if(!verdict.allowed)return finish({...empty,externalCalls,failure:{kind:verdict.kind,message:fetchWarnings.length?`${verdict.message}
|
|
533
538
|
|
|
534
539
|
${fetchWarnings.join(`
|
|
@@ -1981,7 +1986,7 @@ data: ${JSON.stringify(data)}
|
|
|
1981
1986
|
</body>
|
|
1982
1987
|
</html>`;var Kind=Symbol.for("TypeBox.Kind"),toOpenAPIPath=(path8)=>path8.split("/").map((x)=>{if(x.startsWith(":")){if(x=x.slice(1,x.length),x.endsWith("?"))x=x.slice(0,-1);x=`{${x}}`}return x}).join("/"),mapProperties=(name2,schema,models)=>{if(schema===void 0)return[];if(typeof schema==="string")if(schema in models)schema=models[schema];else throw Error(`Can't find model ${schema}`);return Object.entries(schema?.properties??[]).map(([key2,value])=>{let{type:valueType=void 0,description,examples,...schemaKeywords}=value;return{description,examples,schema:{type:valueType,...schemaKeywords},in:name2,name:key2,required:schema.required?.includes(key2)??!1}})},mapTypesResponse=(types18,schema)=>{if(typeof schema==="object"&&["void","undefined","null"].includes(schema.type))return;let responses={};for(let type of types18)responses[type]={schema:typeof schema==="string"?{$ref:`#/components/schemas/${schema}`}:("$ref"in schema)&&(Kind in schema)&&schema[Kind]==="Ref"?{...schema,$ref:`#/components/schemas/${schema.$ref}`}:replaceSchemaType({...schema},{from:t22.Ref(""),to:({$ref,...options})=>{if(!$ref.startsWith("#/components/schemas/"))return t22.Ref(`#/components/schemas/${$ref}`,options);return t22.Ref($ref,options)}})};return responses},capitalize=(word)=>word.charAt(0).toUpperCase()+word.slice(1),generateOperationId=(method,paths)=>{let operationId=method.toLowerCase();if(paths==="/")return operationId+"Index";for(let path8 of paths.split("/"))if(path8.charCodeAt(0)===123)operationId+="By"+capitalize(path8.slice(1,-1));else operationId+=capitalize(path8);return operationId},cloneHook=(hook)=>{if(!hook)return;if(typeof hook==="string")return hook;if(Array.isArray(hook))return[...hook];return{...hook}},registerSchemaPath=({schema,path:path8,method,hook,models})=>{if(hook=cloneHook(hook),hook.parse&&!Array.isArray(hook.parse))hook.parse=[hook.parse];let contentType=hook.parse?.map((x)=>{switch(typeof x){case"string":return x;case"object":if(x&&typeof x?.fn!=="string")return;switch(x?.fn){case"json":case"application/json":return"application/json";case"text":case"text/plain":return"text/plain";case"urlencoded":case"application/x-www-form-urlencoded":return"application/x-www-form-urlencoded";case"arrayBuffer":case"application/octet-stream":return"application/octet-stream";case"formdata":case"multipart/form-data":return"multipart/form-data"}}}).filter((x)=>x!==void 0);if(!contentType||contentType.length===0)contentType=["application/json","multipart/form-data","text/plain"];path8=toOpenAPIPath(path8);let contentTypes=typeof contentType==="string"?[contentType]:contentType??["application/json"],bodySchema=cloneHook(hook?.body),paramsSchema=cloneHook(hook?.params),headerSchema=cloneHook(hook?.headers),querySchema=cloneHook(hook?.query),responseSchema=cloneHook(hook?.response);if(typeof responseSchema==="object")if(Kind in responseSchema){let{type,properties,required,additionalProperties,patternProperties,$ref,...rest}=responseSchema;responseSchema={"200":{...rest,description:rest.description,content:mapTypesResponse(contentTypes,type==="object"||type==="array"?{type,properties,patternProperties,items:responseSchema.items,required}:responseSchema)}}}else Object.entries(responseSchema).forEach(([key2,value])=>{if(typeof value==="string"){if(!models[value])return;let{type,properties,required,additionalProperties:_1,patternProperties:_2,...rest}=models[value];responseSchema[key2]={...rest,description:rest.description,content:mapTypesResponse(contentTypes,value)}}else{let{type,properties,required,additionalProperties,patternProperties,...rest}=value;responseSchema[key2]={...rest,description:rest.description,content:mapTypesResponse(contentTypes,type==="object"||type==="array"?{type,properties,patternProperties,items:value.items,required}:value)}}});else if(typeof responseSchema==="string"){if(!(responseSchema in models))return;let{type,properties,required,$ref,additionalProperties:_1,patternProperties:_2,...rest}=models[responseSchema];responseSchema={"200":{...rest,content:mapTypesResponse(contentTypes,responseSchema)}}}let parameters2=[...mapProperties("header",headerSchema,models),...mapProperties("path",paramsSchema,models),...mapProperties("query",querySchema,models)];schema[path8]={...schema[path8]?schema[path8]:{},[method.toLowerCase()]:{...headerSchema||paramsSchema||querySchema||bodySchema?{parameters:parameters2}:{},...responseSchema?{responses:responseSchema}:{},operationId:hook?.detail?.operationId??generateOperationId(method,path8),...hook?.detail,...bodySchema?{requestBody:{required:!0,content:mapTypesResponse(contentTypes,typeof bodySchema==="string"?{$ref:`#/components/schemas/${bodySchema}`}:bodySchema)}}:null}}},filterPaths=(paths,{excludeStaticFile=!0,exclude=[]})=>{let newPaths={};for(let[key2,value]of Object.entries(paths))if(!exclude.some((x)=>{if(typeof x==="string")return key2===x;return x.test(key2)})&&!key2.includes("*")&&(excludeStaticFile?!key2.includes("."):!0))Object.keys(value).forEach((method)=>{let schema=value[method];if(key2.includes("{")){if(!schema.parameters)schema.parameters=[];schema.parameters=[...key2.split("/").filter((x)=>x.startsWith("{")&&!schema.parameters.find((params)=>params.in==="path"&¶ms.name===x.slice(1,x.length-1))).map((x)=>({schema:{type:"string"},in:"path",name:x.slice(1,x.length-1),required:!0})),...schema.parameters]}if(!schema.responses)schema.responses={200:{}}}),newPaths[key2]=value;return newPaths},swagger=({provider="scalar",scalarVersion="latest",scalarCDN="",scalarConfig={},documentation={},version="5.9.0",excludeStaticFile=!0,path:path8="/swagger",specPath=`${path8}/json`,exclude=[],swaggerOptions={},theme=`https://unpkg.com/swagger-ui-dist@${version}/swagger-ui.css`,autoDarkMode=!0,excludeMethods=["OPTIONS"],excludeTags=[]}={})=>{let schema={},totalRoutes=0;if(!version)version=`https://unpkg.com/swagger-ui-dist@${version}/swagger-ui.css`;let info={title:"Elysia Documentation",description:"Development documentation",version:"0.0.0",...documentation.info},relativePath=specPath.startsWith("/")?specPath.slice(1):specPath,app=new Elysia25({name:"@elysiajs/swagger"}),page=new Response(provider==="swagger-ui"?SwaggerUIRender(info,version,theme,JSON.stringify({url:relativePath,dom_id:"#swagger-ui",...swaggerOptions},(_,value)=>typeof value==="function"?void 0:value),autoDarkMode):ScalarRender(info,scalarVersion,{spec:{url:relativePath,...scalarConfig.spec},...scalarConfig,_integration:"elysiajs"},scalarCDN),{headers:{"content-type":"text/html; charset=utf8"}});return app.get(path8,page,{detail:{hide:!0}}).get(specPath,function(){let routes=app.getGlobalRoutes();if(routes.length!==totalRoutes){let ALLOWED_METHODS=["GET","PUT","POST","DELETE","OPTIONS","HEAD","PATCH","TRACE"];totalRoutes=routes.length,routes.forEach((route)=>{if(route.hooks?.detail?.hide===!0)return;if(excludeMethods.includes(route.method))return;if(ALLOWED_METHODS.includes(route.method)===!1&&route.method!=="ALL")return;if(route.method==="ALL")ALLOWED_METHODS.forEach((method)=>{registerSchemaPath({schema,hook:route.hooks,method,path:route.path,models:app.getGlobalDefinitions?.().type,contentType:route.hooks.type})});else registerSchemaPath({schema,hook:route.hooks,method:route.method,path:route.path,models:app.getGlobalDefinitions?.().type,contentType:route.hooks.type})})}return{openapi:"3.0.3",...{...documentation,tags:documentation.tags?.filter((tag)=>!excludeTags?.includes(tag?.name)),info:{title:"Elysia Documentation",description:"Development documentation",version:"0.0.0",...documentation.info}},paths:{...filterPaths(schema,{excludeStaticFile,exclude:Array.isArray(exclude)?exclude:[exclude]}),...documentation.paths},components:{...documentation.components,schemas:{...app.getGlobalDefinitions?.().type,...documentation.components?.schemas}}}},{detail:{hide:!0}}),app};function createSwaggerPlugin(config){if(config?.enabled===!1)return null;let swaggerConfig={path:config?.path??"/swagger",provider:config?.provider??"scalar",excludeStaticFile:config?.excludeStaticFile??!0,exclude:config?.exclude??[],documentation:{info:{title:config?.documentation?.info?.title??"Nucleus API",description:config?.documentation?.info?.description??"Auto-generated API documentation",version:config?.documentation?.info?.version??"1.0.0",contact:config?.documentation?.info?.contact,license:config?.documentation?.info?.license},tags:config?.documentation?.tags??[],servers:config?.documentation?.servers},scalarConfig:config?.scalarConfig};return swagger(swaggerConfig)}init_utils5();function asText(value){return typeof value==="string"&&value.trim()?value.trim():void 0}function fieldOf(path8){let text2=asText(path8);if(!text2)return;return text2.replace(/^\//,"").replace(/\//g,".")||void 0}function fromValidator(error){let candidate=error;if(typeof candidate?.validator?.Errors!=="function")return;try{let fields=[],reason;for(let item of candidate.validator.Errors(candidate.value)){let field=fieldOf(item?.path);if(field&&!fields.includes(field))fields.push(field);if(reason??=asText(item?.message),fields.length>=4)break}return fields.length||reason?{fields,reason}:void 0}catch{return}}function compose(where,reason){if(where&&reason)return`Invalid request: ${where} \u2014 ${reason}`;if(where)return`Invalid request: ${where}`;if(reason)return`Invalid request: ${reason}`;return"Invalid request"}function fromMessage(raw){let text2=asText(raw);if(!text2)return"Invalid request";let payload;try{payload=JSON.parse(text2)}catch{return}if(!payload||typeof payload!=="object"||payload.type!=="validation")return;let on=asText(payload.on),property=fieldOf(payload.property),reason=asText(payload.summary)??asText(payload.message),where=property&&property!=="root"?`${on?`${on}.`:""}${property}`:on?`the request ${on}`:void 0;return compose(where,reason)}function describeValidationError(error){if(typeof error!=="string"&&error){let detail=fromValidator(error);if(detail){let on=asText(error.type),where=detail.fields.length?detail.fields.map((field)=>on?`${on}.${field}`:field).join(", "):on?`the request ${on}`:void 0;return compose(where,detail.reason)}return fromMessage(error.message)}return fromMessage(error)}function statusOfError(code,error){if(typeof code==="number")return code;let carried=error?.status;if(typeof carried==="number"&&carried>=100&&carried<=599)return carried;return 500}init_auth();init_backup();init_payment();init_marketplace();init_storage2();var mergeEntitiesByName=(entities)=>{let entityMap=new Map;for(let entity of entities){let existing=entityMap.get(entity.table_name),mergedColumns=entity.columns??existing?.columns;entityMap.set(entity.table_name,{...existing||{},...entity,columns:mergedColumns})}return Array.from(entityMap.values())},effectiveConfigEntities=(configEntities)=>{if(!configEntities.some((e)=>e.extends))return configEntities;let{entities:resolved}=resolveEntities(SYSTEM_TABLES,configEntities),byName=new Map(resolved.map((t43)=>[t43.table_name,t43]));return configEntities.map((e)=>e.extends?byName.get(e.table_name)??e:e)},normalizeSystemTable=(table)=>({table_name:table.table_name,excluded_methods:table.excluded_methods?[...table.excluded_methods]:void 0,columns:table.columns?table.columns.map((column)=>({name:column.name,type:column.type})):void 0}),extractSchemaTableEntities=(schemaTables)=>{let entities=[];for(let[_key,tableValue]of Object.entries(schemaTables)){if(!tableValue||typeof tableValue!=="object")continue;let tableObj=tableValue,underscoreMeta=tableObj._;if(underscoreMeta?.name){entities.push({table_name:underscoreMeta.name});continue}let symbols3=Object.getOwnPropertySymbols(tableObj);for(let sym of symbols3){let symValue=tableObj[sym];if(symValue&&typeof symValue==="object"){let symMeta=symValue;if(symMeta.name&&typeof symMeta.name==="string"){entities.push({table_name:symMeta.name});break}}}}return entities};async function NucleusElysiaPlugin(config){let plugin=new Elysia52;if(plugin.get("/health",()=>({status:"ok",timestamp:Date.now()})),config.staticAssets!==!1){let path9=__require("path"),fs4=__require("fs"),assetsPath;if(typeof config.staticAssets==="string")assetsPath=config.staticAssets;else{let localPath=path9.join(process.cwd(),"public"),resolvedPkgPath="";for(let pkgName of["nucleus-core-ts","nucleus-core"])try{let pkgJson=__require.resolve(`${pkgName}/package.json`),candidate=path9.join(path9.dirname(pkgJson),"public");if(fs4.existsSync(candidate)){resolvedPkgPath=candidate;break}}catch{}if(resolvedPkgPath)assetsPath=resolvedPkgPath;else if(fs4.existsSync(localPath))assetsPath=localPath;else assetsPath=localPath}try{plugin.use(await staticPlugin({prefix:"/nucleus-core",assets:assetsPath}))}catch{}}let publicRoutes=[],resolvedOptions,configDir=process.cwd(),configFilePath=null;if(typeof config.options==="string"){let fs4=__require("fs"),path9=__require("path"),configPath=path9.isAbsolute(config.options)?config.options:path9.resolve(process.cwd(),config.options);configDir=path9.dirname(configPath),configFilePath=configPath;let configContent=fs4.readFileSync(configPath,"utf-8");resolvedOptions=JSON.parse(configContent)}else resolvedOptions=config.options;if(resolvedOptions.email?.gmail?.json_file_path){let path9=__require("path"),gmailPath=resolvedOptions.email.gmail.json_file_path;if(!path9.isAbsolute(gmailPath))resolvedOptions.email.gmail.json_file_path=path9.resolve(configDir,gmailPath)}let{authentication,audit,entities,database}=resolvedOptions,isDev=resolvedOptions.mode==="development",loggingConfig=resolvedOptions.logging,logger2=new Logger({service:resolvedOptions.appId||"nucleus",level:loggingConfig?.level||(isDev?"debug":"info"),prettyPrint:loggingConfig?.prettyPrint??isDev,colorize:loggingConfig?.colorize??isDev,includeCallerInfo:loggingConfig?.includeCallerInfo??isDev,redactKeys:loggingConfig?.redactKeys||[],auditEnabled:audit?.enabled??!1,...audit?.suppressReasons!==void 0?{auditSuppressReasons:audit.suppressReasons}:{},...audit?.minSeverity!==void 0?{auditMinSeverity:audit.minSeverity}:{},enabledScopes:loggingConfig?.scopes||["*"]});Logger.getInstance().configure({service:resolvedOptions.appId||"nucleus",level:loggingConfig?.level||(isDev?"debug":"info"),prettyPrint:loggingConfig?.prettyPrint??isDev,colorize:loggingConfig?.colorize??isDev,includeCallerInfo:loggingConfig?.includeCallerInfo??isDev,redactKeys:loggingConfig?.redactKeys||[],enabledScopes:loggingConfig?.scopes||["*"]});let serverLogsConfig=resolvedOptions.monitoring?.serverLogs,serverLogBuffer=serverLogsConfig?.enabled===!0?getServerLogBuffer({capacity:serverLogsConfig.capacity??2000,maxLineLength:serverLogsConfig.maxLineLength}):null;if(serverLogBuffer){let transport=new ServerLogTransport(serverLogBuffer);if(logger2.addTransport(transport),Logger.getInstance().addTransport(transport),serverLogsConfig?.captureStdout!==!1)attachStreamCapture(serverLogBuffer);logger2.info(`[ServerLogs] Buffer active (capacity: ${serverLogBuffer.getCapacity()}, stdout capture: ${serverLogsConfig?.captureStdout!==!1})`)}{let{entities:resolvedForBoot,errors:extendErrors,warnings:extendWarnings}=resolveEntities(SYSTEM_TABLES,entities??[],{consumerMode:authentication?.mode==="consumer"});for(let warning of extendWarnings)logger2.warn(warning);let syncErrors=[],syncMappings=resolvedOptions.authentication?.oauth?.profileSync?.mappings??[];if(syncMappings.length>0){let columnsFor=(name2)=>{return(resolvedForBoot.find((t43)=>t43.table_name===name2)?.columns??[]).map((c)=>c.name)};syncErrors.push(...validateProfileSyncTargets(syncMappings,{users:columnsFor("users"),profiles:columnsFor("profiles")}))}if(extendErrors.length>0||syncErrors.length>0){let detail=[...extendErrors.map((e)=>` ${e.code}: ${e.message}`),...syncErrors.map((m2)=>` PROFILE_SYNC_TARGET: ${m2}`)].join(`
|
|
1983
1988
|
`);throw Error(`Invalid Nucleus config:
|
|
1984
|
-
${detail}`)}let sensitiveNames=resolvedForBoot.flatMap((e)=>e.columns??[]).filter((c)=>c.sensitive===!0).map((c)=>c.name);{registerSensitiveColumns(sensitiveNames);let redactUnion=[...loggingConfig?.redactKeys||[],...sensitiveColumnNames()];if(logger2.configure({redactKeys:redactUnion}),Logger.getInstance().configure({redactKeys:redactUnion}),sensitiveNames.length>0)logger2.info("[Schema] Sensitive columns registered",{columns:sensitiveNames})}}let requestLogConfig={enabled:loggingConfig?.requests?.enabled!==!1,logArrival:loggingConfig?.requests?.logArrival===!0,includeQuery:loggingConfig?.requests?.includeQuery!==!1,slowThresholdMs:loggingConfig?.requests?.slowThresholdMs??3000,excludePaths:loggingConfig?.requests?.excludePaths??["/health"]},isRequestLogExcluded=(pathname)=>requestLogConfig.excludePaths.some((p)=>p.endsWith("*")?pathname.startsWith(p.slice(0,-1)):pathname===p),envValidation=validateEnvVariables(resolvedOptions);if(!envValidation.valid){for(let error3 of envValidation.errors)logger2.error(`[CONFIG] ${error3.message}`,{field:error3.field,envName:error3.envName});throw Error("Nucleus configuration error: Missing required environment variables. Check logs for details.")}let{resolved:envResolved}=envValidation;{let secretEntries=[["accessToken",envResolved.accessTokenSecret],["refreshToken",envResolved.refreshTokenSecret],["sessionToken",envResolved.sessionTokenSecret]];for(let[name2,value2]of secretEntries)if(value2&&value2.length<32)logger2.warn(`[Security] authentication.${name2}.secret is only ${value2.length} chars \u2014 use at least ${"32"} random bytes.`);let present=secretEntries.map(([,v])=>v).filter((v)=>!!v);if(present.length>1&&new Set(present).size<present.length)logger2.warn("[Security] Two or more of the access/refresh/session token secrets are identical \u2014 use a distinct secret for each.")}let tokenNames={access_token:authentication?.accessToken?.name||"access_token",refresh_token:authentication?.refreshToken?.name||"refresh_token",session_token:authentication?.sessionToken?.name||"session_token"},csrfConfig=resolveCsrfConfig(authentication?.csrf),csrfAuthCookieNames=[tokenNames.session_token,tokenNames.access_token],targetSchemaName=database?.sharedSchema||database?.schemas?.[0]||"main",targetSchema=pgSchema2(targetSchemaName);if(envResolved.databaseUrl)await ensureDatabaseExists(envResolved.databaseUrl,logger2,envResolved.databaseAuthMode);let db=null,dbPool=null,dbAuthMode=envResolved.databaseAuthMode||"password",backgroundIntervals=[],trackInterval=(timer)=>{timer.unref?.(),backgroundIntervals.push(timer)};if(envResolved.databaseUrl){let{Pool:Pool2}=await import("pg"),poolOptions=resolveDbPoolConfig(database?.pool);if(dbAuthMode==="password")dbPool=new Pool2({connectionString:envResolved.databaseUrl,...poolOptions});else{let{getPostgresToken:getPostgresToken2}=await Promise.resolve().then(() => (init_Azure(),exports_Azure));await getPostgresToken2(),dbPool=new Pool2({connectionString:envResolved.databaseUrl,password:getPostgresToken2,ssl:{rejectUnauthorized:!0},...poolOptions}),logger2.info(`[Database] Using Entra ID auth mode: ${dbAuthMode}`)}db=drizzle2(dbPool),dbPool.on("error",(err)=>{logger2.warn("[Database] idle pool client error",{error:err instanceof Error?err.message:String(err)})})}let isMultiTenant=database?.isMultiTenant===!0,tenantRegistry=null,schemaTables={},schemaRelations={},claimsCache=null;if(config.schema){let schemasPath=__require("path").resolve(process.cwd(),config.schema),schemas=__require(schemasPath);schemaTables=schemas.createAllTablesForSchema?schemas.createAllTablesForSchema(targetSchema):{}}if(config.relations){let relationsPath=__require("path").resolve(process.cwd(),config.relations);schemaRelations=__require(relationsPath)}let secretsService=null;if(resolvedOptions.secrets?.enabled){let masterKey=resolveMasterKey(resolvedOptions.secrets.encryptionKey);if(!db)logger2.warn("[Secrets] secrets.enabled=true but no database is configured \u2014 disabled");else if(!masterKey)logger2.error("[Secrets] secrets.enabled=true but no encryption key resolved \u2014 set secrets.encryptionKey or NUCLEUS_SECRETS_KEY. Credential storage is disabled; env and literal values still work.");else if(!schemaTables[SECRETS_TABLE])logger2.error(`[Secrets] secrets.enabled=true but the "${SECRETS_TABLE}" table is missing from the generated schema \u2014 re-run schema generation. Credential storage is disabled.`);else{secretsService=new SecretsService({store:new SecretsStore({db,resolveTable:(tableName)=>schemaTables[tableName],masterKey}),logger:logger2,refreshIntervalMs:resolvedOptions.secrets.refreshIntervalMs,getRedis:()=>getRedisManager()}),logger2.info("[Secrets] Credential store enabled");try{if(await secretsService.refresh(),secretsService.isReady())logger2.info("[Secrets] Credentials preloaded for boot-time resolution",{storedCredentials:secretsService.size()})}catch(error3){logger2.warn("[Secrets] Preload failed \u2014 env and literal values still resolve",{error:error3 instanceof Error?error3.message:String(error3)})}}}let resolveCredential=(scope,key2,configValue)=>{if(secretsService)return secretsService.value(scope,key2,configValue);if(!configValue)return;let fromEnv=process.env[configValue];if(fromEnv)return fromEnv;return/^[A-Z][A-Z0-9_]{2,}$/.test(configValue)?void 0:configValue},resolveRedirectUrl=(value2)=>{if(!value2)return;let fromEnv=process.env[value2];if(fromEnv)return fromEnv;return/^[A-Z][A-Z0-9_]{2,}$/.test(value2)?void 0:value2},withResolvedRedirects=(node,keys)=>{if(!node)return node;let resolved={...node};for(let key2 of keys)if(typeof node[key2]==="string")resolved[key2]=resolveRedirectUrl(node[key2]);return resolved},trustedAppOrigins=()=>{let configured=normalizeTrustedOrigins(resolvedOptions.authentication?.trustedAppOrigins);if(!secretsService)return configured;let resolved=secretsService.listValue("authentication","trustedAppOrigins",configured);return resolved.length>0?resolved:configured},liveOAuthProviders=(resolvedProviders)=>{if(!secretsService)return resolvedProviders;let declared=resolvedOptions.authentication?.oauth?.providers??{},live={};for(let[providerName,providerConfig]of Object.entries(resolvedProviders)){let declaredConfig=declared[providerName]??{},entry={...providerConfig};for(let key2 of["clientId","clientSecret","tenantId","redirectUri"]){let declaredValue=declaredConfig[key2],bootValue=providerConfig[key2];Object.defineProperty(entry,key2,{get:()=>{let resolved=secretsService?.value(`authentication.oauth.providers.${providerName}`,key2,typeof declaredValue==="string"?declaredValue:void 0);if(resolved!==void 0)return resolved;return looksLikeEnvName(typeof bootValue==="string"?bootValue:void 0)?void 0:bootValue},enumerable:!0,configurable:!0})}live[providerName]=entry}return live},storageProvider=null;if(resolvedOptions.storage?.enabled){let storageBase=resolvedOptions.storage.basePath||"./uploads";storageProvider=createStorageProvider({provider:resolvedOptions.storage.provider,basePath:storageBase,smb:resolvedOptions.storage.smb,resolveCredential},{logger:logger2}),setStorageProvider(storageProvider)}let buildStorageProvider=(kind)=>{if(!resolvedOptions.storage?.enabled)return null;return createStorageProvider({provider:kind,basePath:resolvedOptions.storage.basePath||"./uploads",smb:resolvedOptions.storage.smb,resolveCredential:(scope,key2,configValue)=>scope==="storage"&&key2==="provider"?kind:resolveCredential(scope,key2,configValue)},{logger:logger2})},swaggerPlugin=createSwaggerPlugin(config.swagger);if(swaggerPlugin)plugin.use(swaggerPlugin);let systemTables2=config.systemTables||[];publicRoutes=buildPublicRoutes(resolvedOptions,systemTables2,"",targetSchemaName),logger2.info(`[AUTH] Built ${publicRoutes.length} public routes`);let rateLimiter=null,monitoringService=null,liveMonitoringService=null,activeEmailProvider=()=>{let declared=resolveCredential("email","provider",resolvedOptions.email?.provider);if(declared==="azure"||declared==="gmail"||declared==="smtp")return emailProviderOn(declared)||resolvedOptions.email?.provider===declared?declared:null;if(emailProviderOn("azure"))return"azure";if(emailProviderOn("gmail"))return"gmail";if(emailProviderOn("smtp"))return"smtp";return null},emailProviderOn=(provider)=>{let configured=resolvedOptions.email?.[provider]?.enabled===!0;return secretsService?secretsService.flag(`email.${provider}`,"enabled",configured):configured},azureEmailCredentials=()=>{let azureConfig=resolvedOptions.email?.azure;return{enabled:!0,connectionString:resolveCredential("email.azure","connection_string",azureConfig?.connection_string)??"",senderAddress:resolveCredential("email.azure","sender_address",azureConfig?.sender_address)??"",fromName:resolveCredential("email.azure","from_name",azureConfig?.from_name)}},gmailCredentials=()=>{let gmailConfig=resolvedOptions.email?.gmail;return{enabled:!0,jsonFilePath:gmailConfig?.json_file_path,serviceAccountJson:resolveCredential("email.gmail","service_account_json",gmailConfig?.service_account_json),fromEmail:resolveCredential("email.gmail","from_email",gmailConfig?.from_email)??"",fromName:resolveCredential("email.gmail","from_name",gmailConfig?.from_name)}},smtpCredentials=()=>{let smtpConfig=resolvedOptions.email?.smtp,port=resolveCredential("email.smtp","port",smtpConfig?.port===void 0?void 0:String(smtpConfig.port)),secure=resolveCredential("email.smtp","secure",smtpConfig?.secure===void 0?void 0:String(smtpConfig.secure));return{enabled:!0,host:resolveCredential("email.smtp","host",smtpConfig?.host)??"",port:port?Number(port):void 0,secure:secure===void 0?void 0:String(secure)==="true",user:resolveCredential("email.smtp","user",smtpConfig?.user)??"",password:resolveCredential("email.smtp","password",smtpConfig?.password)??"",senderAddress:resolveCredential("email.smtp","sender_address",smtpConfig?.sender_address)??"",fromName:resolveCredential("email.smtp","from_name",smtpConfig?.from_name)}},azureService=null,gmailService=null,smtpService=null,getEmailService=()=>{let provider=activeEmailProvider();if(!provider)return null;if(provider==="azure"){if(!azureService)azureService=new AzureEmailService(azureEmailCredentials(),logger2),logger2.info("[AzureEmailService] Initialized",{available:azureService.isAvailable()});else azureService.reconfigure(azureEmailCredentials());return azureService}if(provider==="smtp"){if(!smtpService)smtpService=new SmtpEmailService(smtpCredentials(),logger2),logger2.info("[SmtpEmailService] Initialized",{available:smtpService.isAvailable()});else smtpService.applyConfig(smtpCredentials());return smtpService}if(!gmailService)gmailService=new GmailService(gmailCredentials(),logger2),logger2.info("[GmailService] Initialized",{available:gmailService.isAvailable()});else gmailService.reconfigure(gmailCredentials());return gmailService};if(plugin.decorate("nucleus",createNucleusRuntime({getEmailService,activeEmailProvider})),resolvedOptions.liveMonitoring?.enabled){let liveBasePath=resolvedOptions.liveMonitoring.basePath||"/monitoring",liveStreamInterval=resolvedOptions.liveMonitoring.streamInterval||150;plugin.use(createLiveMonitoringRoutes({getService:()=>liveMonitoringService,logger:logger2,basePath:liveBasePath,streamInterval:liveStreamInterval,db,schemaTables}))}if(resolvedOptions.monitoring?.enabled&&resolvedOptions.monitoring.endpoints?.enabled){let monitoringEndpoints=resolvedOptions.monitoring.endpoints;plugin.use(createMonitoringRoutes({getService:()=>monitoringService,logger:logger2,endpoints:{enabled:!0,basePath:monitoringEndpoints.basePath||"/monitoring",allowRoles:monitoringEndpoints.allowRoles,stream:{enabled:monitoringEndpoints.stream?.enabled!==!1,path:monitoringEndpoints.stream?.path||"/stream",interval:monitoringEndpoints.stream?.interval||"5s"},snapshot:{enabled:monitoringEndpoints.snapshot?.enabled!==!1,path:monitoringEndpoints.snapshot?.path||"/snapshot"},history:{enabled:monitoringEndpoints.history?.enabled!==!1,path:monitoringEndpoints.history?.path||"/history",maxMinutes:monitoringEndpoints.history?.maxMinutes||60},alerts:{enabled:monitoringEndpoints.alerts?.enabled!==!1,path:monitoringEndpoints.alerts?.path||"/alerts"}},db,schemaTables}))}if(serverLogBuffer)plugin.use(createServerLogRoutes({buffer:serverLogBuffer,logger:logger2,basePath:serverLogsConfig?.basePath||resolvedOptions.monitoring?.endpoints?.basePath||"/monitoring",path:serverLogsConfig?.path||"/server-logs",allowRoles:serverLogsConfig?.allowRoles,streamEnabled:serverLogsConfig?.stream!==!1,clearEnabled:serverLogsConfig?.allowClear!==!1,db,schemaTables}));let bootStep=async(name2,run)=>{try{return await run()}catch(error3){logger2.error(`[Boot] Step "${name2}" failed \u2014 continuing in a degraded state rather than crashing`,{error:error3 instanceof Error?error3.message:String(error3)});return}};plugin.onStart(async()=>{await bootStep("redis",()=>initiateRedisManager(resolvedOptions));let redis=getRedisManager();if(redis&&resolvedOptions.configManagement?.enabled)try{let{loadOverridesFromRedis:loadOverridesFromRedis2}=await Promise.resolve().then(() => (init_helpers3(),exports_helpers)),applied=await loadOverridesFromRedis2({read:async(key2)=>{let r2=await redis.read(key2);return{success:r2.success,data:r2.success?r2.data:null}}},resolvedOptions.appId||"nucleus",resolvedOptions);if(applied.length>0)logger2.info(`[ConfigManagement] Loaded ${applied.length} override(s) from Redis`,{sections:applied})}catch(err){logger2.warn("[ConfigManagement] Failed to load overrides from Redis",{error:err instanceof Error?err.message:String(err)})}if(redis&&resolvedOptions.rateLimit?.enabled!==!1)rateLimiter=new RateLimiter({redis,logger:logger2,config:resolvedOptions.rateLimit||{}}),logger2.info(`[RateLimit] Enabled with strategy: ${resolvedOptions.rateLimit?.strategy||"sliding-window"}`);{let channels=resolvedOptions.notification?.channels;if(channels?.telegram?.enabled&&(!channels.telegram.botToken||!channels.telegram.chatId))logger2.warn("[Notification] telegram channel is enabled but botToken/chatId is missing \u2014 telegram deliveries will be skipped");if(channels?.webhook?.enabled&&!channels.webhook.url)logger2.warn("[Notification] webhook channel is enabled but url is missing \u2014 webhook deliveries will be skipped")}if(redis&&resolvedOptions.monitoring?.enabled){let monitoringDb=db,monitoringMetricsTable=schemaTables.monitoringMetrics,monitoringPersistenceEnabled=resolvedOptions.monitoring.persistence?.enabled!==!1,monitoringRetentionDays=resolvedOptions.monitoring.persistence?.retentionDays??30,lastMetricsCleanupAt=0,monitoringDbQuery=monitoringDb?async(sqlText)=>{return(await monitoringDb.execute(sql13.raw(sqlText))).rows}:void 0,monitoringLoadPeaks=monitoringDb&&monitoringPersistenceEnabled&&monitoringMetricsTable?async()=>{let t43=monitoringMetricsTable;return(await monitoringDb.select({metricName:t43.metricName,value:t43.value,recordedAt:t43.recordedAt,tags:t43.tags}).from(t43).where(eq63(t43.metricType,"peak")).orderBy(desc7(t43.value))).map((r2)=>({metricName:String(r2.metricName),value:Number(r2.value??0),at:r2.recordedAt?new Date(r2.recordedAt).getTime():0,context:r2.tags??void 0}))}:void 0;if(monitoringPersistenceEnabled&&monitoringDb&&!monitoringMetricsTable)logger2.warn("[Monitoring] monitoring.persistence is enabled but the monitoring_metrics table is missing from the generated schema \u2014 re-run nucleus-generate to add it");let monitoringFlushToDb=monitoringDb&&monitoringPersistenceEnabled&&monitoringMetricsTable?async(metrics)=>{if(metrics.length===0)return;let metricsTable=monitoringMetricsTable;await monitoringDb.insert(metricsTable).values(metrics.map((m2)=>({metricType:m2.metricType,metricName:m2.metricName,value:m2.value,tags:m2.tags??null,recordedAt:new Date(m2.timestamp)})));let nowMs=Date.now();if(nowMs-lastMetricsCleanupAt>86400000){lastMetricsCleanupAt=nowMs;let cutoff=new Date(nowMs-monitoringRetentionDays*24*60*60*1000);await monitoringDb.delete(metricsTable).where(and23(lt3(metricsTable.recordedAt,cutoff),ne3(metricsTable.metricType,"peak")))}}:void 0;monitoringService=new MonitoringService({redis,logger:logger2,getEmailService,config:resolvedOptions.monitoring,appId:resolvedOptions.appId,dbQuery:monitoringDbQuery,flushToDb:monitoringFlushToDb,loadPeaks:monitoringLoadPeaks}),monitoringService.start(),logger2.info("[Monitoring] Service started")}if(resolvedOptions.liveMonitoring?.enabled)liveMonitoringService=new LiveMonitoringService(resolvedOptions.liveMonitoring),liveMonitoringService.start(),logger2.info("[LiveMonitoring] Service started");let isConsumerModeOnStart=authentication?.mode==="consumer",consumerAllowedTableKeys=isConsumerModeOnStart&&entities?new Set(entities.map((e)=>e.table_name.replace(/_([a-z])/g,(_,c)=>c.toUpperCase()))):null;if(consumerAllowedTableKeys){let opts=resolvedOptions,verificationEnabled=opts.verification?.enabled===!0,notificationEnabled=opts.notification?.enabled===!0,auditEnabled=opts.audit?.enabled===!0,chatEnabled=opts.chat?.enabled===!0,storageEnabled=opts.storage?.enabled===!0,paymentEnabled=opts.payment?.enabled===!0,backupEnabled=opts.backup?.enabled===!0,monitoringPersistenceOn=resolvedOptions.monitoring?.enabled===!0&&resolvedOptions.monitoring?.persistence?.enabled!==!1,featureEnabled={verification:verificationEnabled,notification:notificationEnabled,audit:auditEnabled,chat:chatEnabled,storage:storageEnabled,payment:paymentEnabled,backup:backupEnabled,monitoring:monitoringPersistenceOn,secrets:resolvedOptions.secrets?.enabled===!0,domains:resolvedOptions.domains?.enabled===!0,"multi-tenant":isMultiTenant};for(let sysTable of SYSTEM_TABLES)if(sysTable.feature_set.some((f)=>{if(f==="authentication"||f==="authorization")return!1;if(!(f in featureEnabled))return logger2.warn(`[Schema] Consumer mode has no rule for feature "${f}" (table "${sysTable.table_name}") \u2014 `+"its table will NOT be synced. Add it to featureEnabled in ElysiaPlugin/index.ts."),!1;return featureEnabled[f]===!0})){let camelKey=sysTable.table_name.replace(/_([a-z])/g,(_,c)=>c.toUpperCase());consumerAllowedTableKeys.add(camelKey)}}if(db&&config.schema){let schemas=await import(__require("path").resolve(process.cwd(),config.schema)),auditLogsTable=schemaTables.auditLogs||schemas.auditLogs;if(audit?.enabled&&auditLogsTable)logger2.addAuditTransport(new DatabaseAuditTransport({db,table:auditLogsTable,enabled:!0,dedup:audit.dedup}));let{ensureSchemaExists:ensureSchemaExists2,applySchemaPush:applySchemaPush2}=await Promise.resolve().then(() => (init_schema(),exports_schema)),{reconcileMissingColumns:reconcileMissingColumns2}=await Promise.resolve().then(() => (init_schemaReconcile(),exports_schemaReconcile));try{logger2.info(`Syncing schema to database (target: ${targetSchemaName})...`),await ensureSchemaExists2(db,targetSchemaName);let filteredTables={};try{filteredTables=Object.fromEntries(Object.entries(schemaTables).filter(([key2,v])=>{if(v===void 0||v===null)return!1;if(consumerAllowedTableKeys&&!consumerAllowedTableKeys.has(key2))return!1;if(typeof v==="object"&&v!==null)return Object.getOwnPropertySymbols(v).length>0||v._!==void 0;return!1}));let tableNames=Object.keys(filteredTables);if(logger2.info("[Schema] Tables to sync:",{tables:tableNames,count:tableNames.length,mode:isConsumerModeOnStart?"consumer":"full"}),!isConsumerModeOnStart){let usersTableDef=filteredTables.users;if(usersTableDef){let columnSymbols=Object.getOwnPropertyNames(usersTableDef).filter((k)=>!k.startsWith("_"));logger2.info("[Schema] Users table columns:",{columns:columnSymbols})}}let realExit=process.exit,push;try{process.exit=(code)=>{throw Error(`drizzle-kit called process.exit(${code??0}) during pushSchema \u2014 `+"suppressed so the app can keep booting")};let timeoutMs=database?.schemaPushTimeoutMs??120000;push=await withDeadline(pushSchema({schema:targetSchema,...filteredTables},db,[targetSchemaName]),timeoutMs,`pushSchema did not finish within ${timeoutMs}ms. drizzle-kit most likely hit its `+"interactive rename prompt, which cannot be answered without a TTY \u2014 it appears "+"when a push adds a new table while another table exists in the database but not in the schema. Drop the stale table, or split the change across two deploys.")}finally{process.exit=realExit}if(await applySchemaPush2(push,{schemaName:targetSchemaName,allowDataLoss:database?.allowDataLoss===!0,logger:logger2,execute:(statement)=>db.execute(sql13.raw(statement))}))logger2.info("[Schema] pushSchema completed successfully")}catch(pushError){let msg=pushError instanceof Error?pushError.message:String(pushError),repair=await reconcileMissingColumns2({db,schema:targetSchemaName,tables:filteredTables,logger:logger2,schemaObject:targetSchema});if(!repair||repair.applied>0||repair.plan.createdTables.length>0||repair.plan.missingTables.length>0||repair.plan.unsafe.length>0)logger2.error(`[Schema] pushSchema applied NOTHING: ${msg}`);else logger2.info(`[Schema] pushSchema applied nothing, and nothing was needed \u2014 the database already matches the model. (${msg})`)}logger2.info("[Schema] Schema sync completed",{schema:targetSchemaName})}catch(error3){logger2.error("[Schema] Schema sync failed",error3,{schema:targetSchemaName})}if(secretsService)try{await secretsService.start(),logger2.info("[Secrets] Credential store ready",{storedCredentials:secretsService.size()})}catch(error3){logger2.error("[Secrets] Credential store failed to start \u2014 env and literal values still resolve",{error:error3 instanceof Error?error3.message:String(error3)})}if(logger2.info("[Database] Connection established"),await bootStep("multi-tenant schemas",async()=>{if(isMultiTenant&&db&&config.schema){let schemasForTenant={};try{let schemaPath=__require("path").resolve(process.cwd(),config.schema);logger2.info("[MultiTenant] Loading schema for tenant registry",{schemaPath}),schemasForTenant=await import(schemaPath),logger2.info("[MultiTenant] Schema loaded",{keys:Object.keys(schemasForTenant).slice(0,10),hasCreateAll:!!schemasForTenant.createAllTablesForSchema})}catch(err){let msg=err instanceof Error?err.message:String(err);logger2.error("[MultiTenant] Failed to load schema for tenant registry",{error:msg})}let createAllFn=schemasForTenant.createAllTablesForSchema;if(createAllFn){let idpUrl=isConsumerModeOnStart?authentication?.idpUrl?String(process.env[authentication.idpUrl]||authentication.idpUrl):void 0:void 0;if(tenantRegistry=new TenantRegistry({db,logger:logger2,mainSchemaName:targetSchemaName,mainSchemaTables:schemaTables,mainSchemaRelations:schemaRelations,createAllTablesForSchema:createAllFn,createAllRelationsForSchema:schemasForTenant.createAllRelationsForSchema,appId:resolvedOptions.appId,authMode:authentication?.mode,tenantResolution:database?.tenantResolution||"both",tenantHeader:database?.tenantHeader||"x-tenant-id",redisCacheTtlSeconds:300,defaultTrustedSources:database?.defaultTrustedSources,idpUrl,allowDataLoss:database?.allowDataLoss===!0,onTenantProvisioned:resolvedOptions.authorization?.enabled&&!isConsumerModeOnStart?async(context)=>{let authConfig={...DEFAULT_AUTHORIZATION_CONFIG,...resolvedOptions.authorization};if(authConfig.autoSeedClaims&&db){let claimEntities=mergeEntitiesByName([...extractSchemaTableEntities(context.schemaTables),...SYSTEM_TABLES.map((table)=>normalizeSystemTable(table)),...effectiveConfigEntities(resolvedOptions.entities||[]),...config.systemTables||[],...resolvedOptions.authorization?.externalEntities||[]]);await seedClaims(db,context.schemaTables,context.schemaRelations,claimEntities,authConfig,logger2)}let seedConfig=resolvedOptions.authorization?.seed;if(seedConfig&&db){let{runSeed:runSeed2}=await Promise.resolve().then(() => (init_SeedRunner(),exports_SeedRunner));await runSeed2(db,context.schemaTables,seedConfig,logger2)}logger2.info(`[Authorization] New tenant schema seeded: ${context.schemaName}`)}:void 0}),isConsumerModeOnStart&&idpUrl){await tenantRegistry.initializeFromIdp(),logger2.info("[MultiTenant] Consumer mode: tenants fetched from IDP");let tenantSyncTimer=setInterval(()=>{tenantRegistry?.syncFromIdp().then((result)=>{if(result.added.length>0||result.removed.length>0)logger2.info(`[MultiTenant] Tenant sync: +${result.added.length} / -${result.removed.length} (total ${result.total})`)}).catch((err)=>{let msg=err instanceof Error?err.message:String(err);logger2.warn(`[MultiTenant] Tenant sync failed: ${msg}`)})},60000);trackInterval(tenantSyncTimer)}else await tenantRegistry.initialize();for(let schemaName of tenantRegistry.getAllSchemaNames()){if(schemaName===targetSchemaName)continue;let ctx=tenantRegistry.getSchemaContext(schemaName);if(ctx){await ensureSchemaExists2(db,schemaName);try{let tenantFilteredTables=Object.fromEntries(Object.entries(ctx.schemaTables).filter(([key2,v])=>{if(v===void 0||v===null)return!1;if(consumerAllowedTableKeys&&!consumerAllowedTableKeys.has(key2))return!1;if(typeof v==="object"&&v!==null)return Object.getOwnPropertySymbols(v).length>0||v._!==void 0;return!1})),tenantSchema=pgSchema2(schemaName),tenantPush=await pushSchema({schema:tenantSchema,...tenantFilteredTables},db,[schemaName]);if(await applySchemaPush2(tenantPush,{schemaName,allowDataLoss:database?.allowDataLoss===!0,logger:logger2,execute:(statement)=>db.execute(sql13.raw(statement))}))logger2.info(`[Schema] Tenant schema synced: ${schemaName}`)}catch(tenantPushError){let msg=tenantPushError instanceof Error?tenantPushError.message:String(tenantPushError);logger2.warn(`[Schema] Tenant schema sync warning for ${schemaName}: ${msg}`)}}}logger2.info(`[MultiTenant] Registry initialized with ${tenantRegistry.getAllSchemaNames().length} schemas`),logger2.info("[MultiTenant] Tenant registry ready, routes were pre-registered")}}}),resolvedOptions.authorization?.enabled&&!isConsumerModeOnStart){let authConfig={...DEFAULT_AUTHORIZATION_CONFIG,...resolvedOptions.authorization,godminEmail:resolveConfigCredential(resolvedOptions.authorization?.godminEmail),godminPassword:resolveConfigCredential(resolvedOptions.authorization?.godminPassword)};if(authConfig.autoSeedClaims){let schemaEntities=extractSchemaTableEntities(schemaTables),systemEntities=SYSTEM_TABLES.map((table)=>normalizeSystemTable(table)),configEntities=effectiveConfigEntities(resolvedOptions.entities||[]),externalEntities=resolvedOptions.authorization?.externalEntities||[],claimEntities=mergeEntitiesByName([...schemaEntities,...configEntities,...systemEntities,...config.systemTables||[],...externalEntities]);logger2.info("[Authorization] Seeding claims...",{schemaEntities:schemaEntities.length,systemEntities:systemEntities.length,configEntities:configEntities.length,externalEntities:externalEntities.length,totalEntities:claimEntities.length}),await seedClaims(db,schemaTables,schemaRelations,claimEntities,authConfig,logger2)}let discoveryConfig=resolvedOptions.authorization?.endpointDiscovery;if(discoveryConfig?.enabled&&(discoveryConfig.runOnBoot??!0)&&db)try{let{runEndpointDiscovery:runEndpointDiscovery2}=await Promise.resolve().then(() => (init_seed(),exports_seed)),discoveryResult=await runEndpointDiscovery2(db,schemaTables,discoveryConfig,logger2);logger2.info("[Authorization] Endpoint discovery completed",{services:discoveryResult.services})}catch(discoveryErr){logger2.error("[Authorization] Endpoint discovery failed",{error:discoveryErr instanceof Error?discoveryErr.message:String(discoveryErr)})}if(authConfig.godminEmail&&authConfig.godminPassword)logger2.info("[Authorization] Setting up godmin..."),await setupGodmin(db,schemaTables,authConfig,logger2);let seedConfig=resolvedOptions.authorization?.seed;if(seedConfig){let{runSeed:runSeed2}=await Promise.resolve().then(() => (init_SeedRunner(),exports_SeedRunner));logger2.info("[Authorization] Running custom seed...");let seedResult=await bootStep("authorization.seed",()=>runSeed2(db,schemaTables,seedConfig,logger2));if(seedResult)logger2.info("[Authorization] Custom seed completed",{rolesCreated:seedResult.rolesCreated,rolesExisting:seedResult.rolesExisting,claimsCreated:seedResult.claimsCreated,claimsExisting:seedResult.claimsExisting,assignmentsCreated:seedResult.assignmentsCreated,assignmentsExisting:seedResult.assignmentsExisting,assignmentsUpdated:seedResult.assignmentsUpdated})}let claimGuardsCfg=resolvedOptions.authorization?.claimGuards;if(claimGuardsCfg?.length){let{seedClaimGuards:seedClaimGuards2}=await Promise.resolve().then(() => (init_ClaimGuard(),exports_ClaimGuard));await bootStep("authorization.claimGuards",()=>seedClaimGuards2(db,schemaTables,claimGuardsCfg,logger2))}let jwtClaimsMode=resolvedOptions.authorization?.jwtClaimsMode||"embed",claimsCacheRedis=getRedisManager();if(jwtClaimsMode==="resolve"&&db&&claimsCacheRedis){let{ClaimsCache:ClaimsCache3}=await Promise.resolve().then(() => (init_ClaimsCache(),exports_ClaimsCache));claimsCache=new ClaimsCache3({prefix:resolvedOptions.authorization?.claimsCachePrefix||"nucleus:claims",redis:{get:async(key2)=>{let r2=await claimsCacheRedis.read(key2);return r2.success?r2.data:null},set:async(key2,value2)=>{await claimsCacheRedis.create(key2,value2)},delete:async(key2)=>{await claimsCacheRedis.remove(key2)}},db,schemaTables,logger:logger2});let cacheInstance=claimsCache,cacheResult=await bootStep("authorization.claimsCache",()=>cacheInstance.buildCache());if(cacheResult)logger2.info("[Authorization] Claims cache built (resolve mode)",{version:cacheResult.version,roleCount:cacheResult.roleCount,totalMappings:cacheResult.totalMappings})}else if(jwtClaimsMode==="resolve"&&!claimsCacheRedis)logger2.warn("[Authorization] jwtClaimsMode=resolve requires Redis. Falling back to embed mode.");if(logger2.info("[Authorization] Enabled"),isMultiTenant&&tenantRegistry){let tenantSchemas=tenantRegistry.getAllSchemaNames().filter((name2)=>name2!==targetSchemaName);for(let tenantSchemaName of tenantSchemas){let tenantCtx=tenantRegistry.getSchemaContext(tenantSchemaName);if(!tenantCtx)continue;try{if(authConfig.autoSeedClaims){let tenantSchemaEntities=extractSchemaTableEntities(tenantCtx.schemaTables),tenantClaimEntities=mergeEntitiesByName([...tenantSchemaEntities,...SYSTEM_TABLES.map((table)=>normalizeSystemTable(table)),...effectiveConfigEntities(resolvedOptions.entities||[]),...config.systemTables||[],...resolvedOptions.authorization?.externalEntities||[]]);await seedClaims(db,tenantCtx.schemaTables,tenantCtx.schemaRelations,tenantClaimEntities,authConfig,logger2)}if(tenantCtx.tenant?.godAdminEmail&&authConfig.godminPassword)await setupGodmin(db,tenantCtx.schemaTables,{...authConfig,godminEmail:tenantCtx.tenant.godAdminEmail},logger2);if(seedConfig){let{runSeed:runSeed2}=await Promise.resolve().then(() => (init_SeedRunner(),exports_SeedRunner));await runSeed2(db,tenantCtx.schemaTables,seedConfig,logger2)}logger2.info(`[Authorization] Tenant schema seeded: ${tenantSchemaName}`)}catch(err){let msg=err instanceof Error?err.message:String(err);logger2.warn(`[Authorization] Failed to seed tenant ${tenantSchemaName}: ${msg}`)}}logger2.info(`[Authorization] Multi-tenant seeding complete for ${tenantSchemas.length} schemas`)}}let sessionsTableRef=schemaTables.userSessions;if(!isConsumerModeOnStart&&sessionsTableRef&&resolvedOptions.authentication?.sessions?.enabled){let{lt:lt4}=await import("drizzle-orm"),expiredCount=await bootStep("auth.expiredSessionCleanup",()=>db.update(sessionsTableRef).set({isActive:!1,revokedAt:new Date,revokedReason:"expired"}).where(and23(eq63(sessionsTableRef.isActive,!0),lt4(sessionsTableRef.expiresAt,new Date))));if(expiredCount!==void 0)logger2.info("[AUTH] Expired sessions cleanup completed",{expiredCount});let sessionCleanupInterval=setInterval(async()=>{try{await db.update(sessionsTableRef).set({isActive:!1,revokedAt:new Date,revokedReason:"expired"}).where(and23(eq63(sessionsTableRef.isActive,!0),lt4(sessionsTableRef.expiresAt,new Date)));let approvalTtlMs=86400000,approvalCutoff=new Date(Date.now()-approvalTtlMs);await db.update(sessionsTableRef).set({isActive:!1,revokedAt:new Date,revokedReason:"approval_token_expired",approvalStatus:"rejected",approvalToken:null}).where(and23(eq63(sessionsTableRef.approvalStatus,"pending"),lt4(sessionsTableRef.approvalRequestedAt,approvalCutoff)))}catch(err){logger2.warn("[AUTH] Session cleanup failed",{error:err})}},3600000);trackInterval(sessionCleanupInterval)}if(isMultiTenant&&tenantRegistry&&resolvedOptions.authentication?.sessions?.enabled){let{lt:lt4}=await import("drizzle-orm"),tenantSchemaNames=tenantRegistry.getAllSchemaNames().filter((name2)=>name2!==targetSchemaName);for(let tenantSchemaName of tenantSchemaNames){let tenantCtx=tenantRegistry.getSchemaContext(tenantSchemaName);if(!tenantCtx)continue;let tenantSessionsTable=tenantCtx.schemaTables.userSessions||tenantCtx.schemaTables.user_sessions||tenantCtx.schemaTables.sessions;if(!tenantSessionsTable)continue;try{await db.update(tenantSessionsTable).set({isActive:!1,revokedAt:new Date,revokedReason:"expired"}).where(and23(eq63(tenantSessionsTable.isActive,!0),lt4(tenantSessionsTable.expiresAt,new Date))),logger2.info(`[AUTH] Tenant session cleanup completed: ${tenantSchemaName}`)}catch(err){let msg=err instanceof Error?err.message:String(err);logger2.warn(`[AUTH] Tenant session cleanup failed for ${tenantSchemaName}: ${msg}`)}}}}}).onRequest(async({request,set:set2,server})=>{if(request.headers.delete("x-user-id"),request.headers.delete("x-request-id"),request.headers.delete("x-auth-type"),request.headers.delete("x-api-key-id"),request.headers.delete("x-api-key-owner-type"),request.headers.delete("x-user-roles"),request.headers.delete("x-user-claims"),request.headers.delete("x-user-claim-scopes"),request.headers.delete("x-session-id"),request.headers.delete("x-access-token"),request.headers.delete("x-refresh-token"),request.headers.delete("x-tenant-schema"),exceedsBodyLimit(request.headers.get("content-length"),resolvedOptions.security?.maxRequestBodyBytes))return set2.status=413,Response.json({isSuccess:!1,message:"Request body too large",status:413,errors:[{message:"Request body too large"}],data:null});let requestStartTime=Date.now(),requestSchemaTables=schemaTables;if(tenantRegistry){let tenantVettedClientIp=resolveClientIp(server?.requestIP(request)?.address??null,request.headers.get("x-forwarded-for")??request.headers.get("x-real-ip"),resolvedOptions.rateLimit?.trustedProxies??[]),tenantResult=tenantRegistry.resolveFromRequest(request,tenantVettedClientIp);if(tenantResult.resolved)requestSchemaTables=tenantResult.context.schemaTables,request.headers.set("x-tenant-schema",tenantResult.context.schemaName);else if(new URL(request.url).pathname!=="/health")return set2.status=tenantResult.statusCode,Response.json({isSuccess:!1,message:tenantResult.error,status:tenantResult.statusCode,errors:[{message:tenantResult.error}],data:null})}request.headers.set("x-request-start-time",String(requestStartTime));let requestId=randomUUID9();if(request.headers.set("x-request-id",requestId),set2.headers["x-request-id"]=requestId,resolvedOptions.security?.disableDefaultHeaders!==!0){set2.headers["X-Content-Type-Options"]="nosniff",set2.headers["X-Frame-Options"]="SAMEORIGIN",set2.headers["Referrer-Policy"]="strict-origin-when-cross-origin";let hstsMaxAge=resolvedOptions.security?.hstsMaxAge??15552000;if(hstsMaxAge>0)set2.headers["Strict-Transport-Security"]=`max-age=${hstsMaxAge}; includeSubDomains`}let url=new URL(request.url),pathname=url.pathname,method=request.method,query=url.search;if(csrfConfig.enabled){let csrfSecure=request.headers.get("x-forwarded-proto")==="https"||url.protocol==="https:"?"; Secure":"",issueCsrfCookie=()=>`${csrfConfig.cookieName}=${randomUUID9()}; Path=/; SameSite=Lax${csrfSecure}`,csrfCookies=parseCookies(request.headers.get("cookie"));if(requiresCsrf({method,cookies:csrfCookies,hasAuthorizationHeader:!!request.headers.get("authorization"),authCookieNames:csrfAuthCookieNames})&&!csrfTokenMatches(csrfCookies[csrfConfig.cookieName],request.headers.get(csrfConfig.headerName)))return set2.headers["Set-Cookie"]=issueCsrfCookie(),set2.status=403,Response.json({isSuccess:!1,message:"CSRF token missing or invalid",status:403,errors:[{message:"CSRF token missing or invalid"}],data:null});else if(!isStateChanging(method)&&!csrfCookies[csrfConfig.cookieName])set2.headers["Set-Cookie"]=issueCsrfCookie()}let socketIp=server?.requestIP(request)?.address??null,clientIp=resolveClientIp(socketIp,request.headers.get("x-forwarded-for")??request.headers.get("x-real-ip"),resolvedOptions.rateLimit?.trustedProxies??[]);request.headers.set("x-client-ip",clientIp);let userAgent=request.headers.get("user-agent")||"unknown";if(requestLogConfig.enabled&&requestLogConfig.logArrival&&!isRequestLogExcluded(pathname))logger2.log("debug",`\u2192 ${method} ${pathname}`,{requestId,method,path:pathname,query:requestLogConfig.includeQuery&&query?query:void 0,ip:clientIp,tenant:request.headers.get("x-tenant-schema")||void 0},void 0,void 0,"middleware.request");let tokens,parsedBody={};if(request.method!=="GET"&&request.method!=="HEAD")try{let text2=await request.clone().text();parsedBody=text2?JSON.parse(text2):{}}catch{parsedBody={}}let auditPayload=audit?.enabled?{id:randomUUID9(),user_id:"unknown",entity_name:pathname.split("/").filter(Boolean)[0]||"root",entity_id:null,operation_type:method,summary:"",old_values:{},new_values:parsedBody,ip_address:clientIp,user_agent:userAgent,timestamp:new Date().toISOString(),path:pathname,query}:null,isPublic=isPublicRoute(publicRoutes,pathname,method);if(rateLimiter){let routeCategory=isPublic?"public":"private",authType=resolveAuthType(pathname,resolvedOptions.authentication),category=authType?"auth":routeCategory,rateLimitResult=await rateLimiter.check({ip:clientIp,endpoint:pathname,category,authType}),headers=rateLimiter.getHeaders(rateLimitResult);for(let[key2,value2]of Object.entries(headers))set2.headers[key2]=value2;if(!rateLimitResult.allowed){if(set2.status=429,rateLimitResult.retryAfter)set2.headers["Retry-After"]=String(rateLimitResult.retryAfter);if(logger2.warn(`[RateLimit] Blocked request from ${clientIp} to ${pathname}`),monitoringService)monitoringService.recordRateLimitBlock();return new Response(JSON.stringify({error:"Too Many Requests",retryAfter:rateLimitResult.retryAfter}),{status:429,headers:{"Content-Type":"application/json"}})}}if(pathname==="/health")return;if(authentication?.enabled&&!isPublic){let apiKeyRaw=extractApiKeyFromHeader(request.headers),apiKeysTableRef=requestSchemaTables.apiKeys;if(apiKeyRaw&&authentication.apiKeys?.enabled&&apiKeysTableRef&&db){let keyHash=hashApiKey(apiKeyRaw),apiKeyRecord=(await db.select().from(apiKeysTableRef).where(eq63(apiKeysTableRef.keyHash,keyHash)).limit(1))[0];if(!apiKeyRecord)return set2.status=401,logger2.traceSync({message:"Invalid API key",level:"warn",context:{path:pathname,method},audit:toAudit(auditPayload,"Invalid API key")}),Error("Invalid API key");let validation=validateApiKeyRecord(apiKeyRecord);if(!validation.valid)return set2.status=401,logger2.traceSync({message:`API key rejected: ${validation.reason}`,level:"warn",context:{path:pathname,method,keyId:apiKeyRecord.id},audit:toAudit(auditPayload,`API key rejected: ${validation.reason}`)}),Error(validation.reason);let apiKeyUserId=apiKeyRecord.userId,apiKeyUserData;{let ksTable=requestSchemaTables.users;if(ksTable&&db){apiKeyUserData=(await db.select().from(ksTable).where(eq63(ksTable.id,apiKeyUserId)).limit(1))[0];let{evaluateAccountState:evaluateAccountState2}=await Promise.resolve().then(() => exports_accountState),ksState=apiKeyUserData?evaluateAccountState2(apiKeyUserData):{allowed:!1,reason:"inactive",message:"Account is not active"};if(!ksState.allowed)return set2.status=401,logger2.traceSync({message:`API key rejected: account ${ksState.reason}`,level:"warn",context:{path:pathname,method,keyId:apiKeyRecord.id},audit:toAudit(auditPayload,`API key rejected: account ${ksState.reason}`,{userId:apiKeyUserId})}),Error(ksState.message)}}let keyAllowedRoles=apiKeyRecord.allowedRoles||[],keyAllowedClaims=apiKeyRecord.allowedClaims||[],effectiveRoles=keyAllowedRoles,effectiveClaims=keyAllowedClaims,apiKeyClaimScopes={},userRolesTable=requestSchemaTables.userRoles,rolesTable=requestSchemaTables.roles,roleClaimsTable=requestSchemaTables.roleClaims,claimsTable=requestSchemaTables.claims;if(userRolesTable&&rolesTable){let currentUserRoles=(await db.select({name:rolesTable.name}).from(userRolesTable).innerJoin(rolesTable,eq63(rolesTable.id,userRolesTable.roleId)).where(eq63(userRolesTable.userId,apiKeyUserId))).map((r2)=>r2.name).filter((n2)=>n2!==void 0);effectiveRoles=intersectPermissions(currentUserRoles,keyAllowedRoles)}if(userRolesTable&&roleClaimsTable&&claimsTable){let userClaimRows=await db.select({action:claimsTable.action,scope:roleClaimsTable.scope}).from(userRolesTable).innerJoin(roleClaimsTable,eq63(roleClaimsTable.roleId,userRolesTable.roleId)).innerJoin(claimsTable,eq63(claimsTable.id,roleClaimsTable.claimId)).where(eq63(userRolesTable.userId,apiKeyUserId)),currentUserClaims=[...new Set(userClaimRows.map((r2)=>r2.action).filter((a12)=>a12!==void 0))];effectiveClaims=intersectPermissions(currentUserClaims,keyAllowedClaims);let effectiveClaimSet=new Set(effectiveClaims),apiScopedRows=userClaimRows.filter((r2)=>typeof r2.action==="string"&&effectiveClaimSet.has(r2.action)).map((r2)=>({action:r2.action,scope:r2.scope??null}));if(apiScopedRows.some((r2)=>!!r2.scope)){let{claimScopes,dropped}=resolveClaimScopes(apiScopedRows,apiKeyUserData,logger2);if(apiKeyClaimScopes=claimScopes,dropped.length>0){let droppedSet=new Set(dropped);effectiveClaims=effectiveClaims.filter((a12)=>!droppedSet.has(a12))}}}if(db.update(apiKeysTableRef).set({lastUsedAt:new Date,lastUsedIp:clientIp,usageCount:apiKeyRecord.usageCount+1}).where(eq63(apiKeysTableRef.id,apiKeyRecord.id)).catch(()=>{}),effectiveRoles=effectiveRoles.filter((r2)=>r2!==GODMIN_ROLE_NAME),request.headers.set("x-user-id",apiKeyUserId),request.headers.set("x-auth-type","api_key"),request.headers.set("x-api-key-id",apiKeyRecord.id),request.headers.set("x-api-key-owner-type",apiKeyRecord.ownerType||"personal"),effectiveRoles.length>0)request.headers.set("x-user-roles",encodeHeaderList(effectiveRoles));if(effectiveClaims.length>0)request.headers.set("x-user-claims",encodeHeaderList(effectiveClaims));{let apiEncodedScopes=encodeClaimScopesHeader(apiKeyClaimScopes);if(apiEncodedScopes)request.headers.set("x-user-claim-scopes",apiEncodedScopes)}logger2.info("[AUTH] API key authenticated",{userId:apiKeyUserId,keyId:apiKeyRecord.id,ownerType:apiKeyRecord.ownerType,path:pathname,method,effectiveRoles:effectiveRoles.length,effectiveClaims:effectiveClaims.length});return}if(!authentication.accessToken?.secret)return set2.status=500,logger2.traceSync({message:"Authentication secrets not defined",level:"error",context:{path:pathname,method},audit:toAudit(auditPayload,"Authentication secrets not defined")}),Error("One or more authentication secrets are not defined");if(authentication.mode==="consumer"){tokens=parseTokenValuesFromHeaders(request.headers,tokenNames);let jwtResult=verifyJWT(tokens.access_token||"",envResolved.accessTokenSecret||"",{issuer:authentication.accessToken?.issuer,audience:authentication.accessToken?.audience});if(!jwtResult.valid)return set2.status=401,logger2.traceSync({message:"Invalid or missing access token",level:"warn",context:{path:pathname,method},audit:toAudit(auditPayload,"Invalid or missing access token",{userId:decodeUnverifiedSubject(tokens.access_token)})}),Error("Unauthenticated");let consumerBinding=verifyTenantBinding(jwtResult.payload[TENANT_CLAIM],request.headers.get("x-tenant-schema"),resolvedOptions.authentication?.tenantBinding??"lenient");if(!consumerBinding.ok)return set2.status=401,logger2.traceSync({message:"Access token tenant binding failed",level:"warn",context:{path:pathname,method,reason:consumerBinding.reason},audit:toAudit(auditPayload,"Access token tenant binding failed",{userId:decodeUnverifiedSubject(tokens.access_token)})}),Error("Unauthenticated");let userId=jwtResult.payload.sub,roles=jwtResult.payload.roles,claimsFromToken=jwtResult.payload.claims;if(request.headers.set("x-access-token",tokens.access_token||""),request.headers.set("x-user-id",userId||""),roles&&roles.length>0)request.headers.set("x-user-roles",encodeHeaderList(roles));if(claimsFromToken&&claimsFromToken.length>0)request.headers.set("x-user-claims",encodeHeaderList(claimsFromToken));{let encodedScopes=encodeClaimScopesHeader(jwtResult.payload.claimScopes);if(encodedScopes)request.headers.set("x-user-claim-scopes",encodedScopes)}}else{if(!authentication.refreshToken?.secret||!authentication.sessionToken?.secret)return set2.status=500,logger2.traceSync({message:"Authentication secrets not defined",level:"error",context:{path:pathname,method},audit:toAudit(auditPayload,"Authentication secrets not defined")}),Error("One or more authentication secrets are not defined");if(tokens=parseTokenValuesFromHeaders(request.headers,tokenNames),!tokens.session_token)return set2.status=401,logger2.traceSync({message:"No session token",level:"debug",context:{path:pathname,method},audit:toAudit(auditPayload,"No session token")}),Error("Unauthenticated");let sessionData=await readSession({sessionId:tokens.session_token});if(!sessionData)return set2.status=401,logger2.traceSync({message:"Invalid session",level:"debug",context:{path:pathname,method,sessionId:tokens.session_token},audit:toAudit(auditPayload,"Invalid session")}),Error("Unauthenticated");let sessionsTableCheck=requestSchemaTables.userSessions;if(sessionsTableCheck&&db){let session=(await db.select().from(sessionsTableCheck).where(eq63(sessionsTableCheck.id,tokens.session_token)).limit(1))[0],revokedAtVal=session?.revokedAt,isRevoked=revokedAtVal!=null&&!(typeof revokedAtVal==="object"&&!(revokedAtVal instanceof Date)&&Object.keys(revokedAtVal).length===0);if(!session||session.isActive===!1||isRevoked)return set2.status=401,logger2.traceSync({message:"Session revoked or inactive",level:"warn",context:{path:pathname,method,sessionId:tokens.session_token,isActive:session?.isActive,revokedAt:session?.revokedAt},audit:toAudit(auditPayload,"Session revoked",{userId:sessionData.userId??null})}),Error("Session has been revoked");if(session.expiresAt&&new Date(session.expiresAt)<new Date)return set2.status=401,logger2.traceSync({message:"Session expired",level:"debug",context:{path:pathname,method,sessionId:tokens.session_token,expiresAt:session.expiresAt},audit:toAudit(auditPayload,"Session expired",{userId:sessionData.userId??null})}),Error("Session has expired")}if(isIdleExpired({lastActiveAt:sessionData.lastActiveAt,inactivityTimeout:authentication.sessions?.inactivityTimeout}))return set2.status=401,logger2.traceSync({message:"Session inactive timeout",level:"debug",context:{path:pathname,method,sessionId:tokens.session_token,lastActiveAt:sessionData.lastActiveAt},audit:toAudit(auditPayload,"Session inactive timeout",{userId:sessionData.userId??null})}),Error("Session expired due to inactivity");updateLastActiveAt(tokens.session_token).catch(()=>{});let sessionsTableRef=requestSchemaTables.userSessions;if(sessionsTableRef&&db)db.update(sessionsTableRef).set({lastActivityAt:new Date}).where(eq63(sessionsTableRef.id,tokens.session_token)).catch(()=>{});let jwtResult=verifyJWT(tokens.access_token||"",envResolved.accessTokenSecret||"",{issuer:authentication.accessToken?.issuer,audience:authentication.accessToken?.audience}),isAccessTokenValid=tokens.access_token?jwtResult.valid:!1,isRefreshTokenValid=tokens.refresh_token?verifyJWT(tokens.refresh_token,envResolved.refreshTokenSecret||"",{issuer:authentication.refreshToken?.issuer,audience:authentication.refreshToken?.audience}).valid:!1;if(!isAccessTokenValid&&isRefreshTokenValid&&tokens.refresh_token&&sessionData.rememberMe===!0){let killSwitchUsersTable=requestSchemaTables.users;if(db&&killSwitchUsersTable){let ksUser=(await db.select().from(killSwitchUsersTable).where(eq63(killSwitchUsersTable.id,sessionData.userId)).limit(1))[0],{evaluateAccountState:evaluateAccountState2}=await Promise.resolve().then(() => exports_accountState),ksState=ksUser?evaluateAccountState2(ksUser):{allowed:!1,reason:"inactive",message:"Account is not active"};if(!ksState.allowed)return set2.status=401,logger2.traceSync({message:`Silent refresh blocked - account ${ksState.reason}`,level:"warn",context:{path:pathname,method},audit:toAudit(auditPayload,`Silent refresh blocked - account ${ksState.reason}`,{userId:sessionData.userId??null})}),Error(ksState.message)}let refreshRoles=[],refreshClaims=[],refreshClaimScopes={},refreshUserRolesTable=requestSchemaTables.userRoles,refreshRolesTable=requestSchemaTables.roles,refreshRoleClaimsTable=requestSchemaTables.roleClaims,refreshClaimsTable=requestSchemaTables.claims;if(db&&refreshUserRolesTable&&refreshRolesTable)try{let{fetchUserRolesAndClaims:fetchUserRolesAndClaims2}=await Promise.resolve().then(() => (init_fetchUserRolesAndClaims(),exports_fetchUserRolesAndClaims)),rc=await fetchUserRolesAndClaims2(db,sessionData.userId,{usersTable:killSwitchUsersTable??null,sessionsTable:null,userRolesTable:refreshUserRolesTable,rolesTable:refreshRolesTable,roleClaimsTable:refreshRoleClaimsTable,claimsTable:refreshClaimsTable,oauthAccountsTable:void 0,apiKeysTable:void 0,schemaTables:requestSchemaTables});refreshRoles=rc.roles,refreshClaims=rc.claims,refreshClaimScopes=rc.claimScopes}catch{}let refreshResult=await refreshAccessTokenWithLock(sessionData.userId,sessionData.id,()=>signNewAccessToken({refreshTokenId:tokens.refresh_token,options:resolvedOptions,sessionData,roles:refreshRoles.length>0?refreshRoles:void 0,claims:refreshClaims.length>0?refreshClaims:void 0,claimScopes:refreshClaimScopes,tenant:request.headers.get("x-tenant-schema")??void 0,resolveMode:resolvedOptions.authorization?.jwtClaimsMode==="resolve"&&!!claimsCache}));if(refreshResult.success&&refreshResult.accessToken){tokens.access_token=refreshResult.accessToken;let rawDomain=authentication.cookieDomain,resolvedDomainRaw=rawDomain?process.env[rawDomain]??rawDomain:void 0,resolvedDomain=resolvedDomainRaw==="localhost"||resolvedDomainRaw===".localhost"?void 0:resolvedDomainRaw,domainPart=resolvedDomain?`; Domain=${resolvedDomain}`:"",bufferSeconds=authentication.cookieMaxAgeBufferSeconds??0,maxAge=Math.max(0,parseTimeToSeconds2(authentication.accessToken.expiresIn??"15m")-bufferSeconds),securePart=!resolvedDomain?"":"; Secure",cookieValue=`${tokenNames.access_token}=${refreshResult.accessToken}; Path=/; HttpOnly; SameSite=Lax${securePart}; Max-Age=${maxAge}${domainPart}`;set2.headers["Set-Cookie"]=cookieValue}}if(jwtResult.valid){let fullBinding=verifyTenantBinding(jwtResult.payload[TENANT_CLAIM],request.headers.get("x-tenant-schema"),resolvedOptions.authentication?.tenantBinding??"lenient");if(!fullBinding.ok)return set2.status=401,logger2.traceSync({message:"Access token tenant binding failed",level:"warn",context:{path:pathname,method,reason:fullBinding.reason},audit:toAudit(auditPayload,"Access token tenant binding failed",{userId:jwtResult.payload.sub??null})}),Error("Unauthenticated")}if(jwtResult.valid&&jwtResult.payload.sub&&String(jwtResult.payload.sub)!==String(sessionData.userId))return set2.status=401,logger2.traceSync({message:"Access token subject does not match session",level:"warn",context:{path:pathname,method,sessionUserId:sessionData.userId,tokenSub:jwtResult.payload.sub},audit:toAudit(auditPayload,"Access token/session subject mismatch",{userId:sessionData.userId??null})}),Error("Unauthenticated");let userId=jwtResult.valid?jwtResult.payload.sub:sessionData.userId,roles=jwtResult.valid?jwtResult.payload.roles:void 0,claimsFromToken=jwtResult.valid?jwtResult.payload.claims:void 0;if(!claimsFromToken?.length&&claimsCache&&roles&&roles.length>0)try{let resolvedClaims=await claimsCache.resolveClaimsForRoles(roles);if(resolvedClaims.length>0)claimsFromToken=resolvedClaims}catch{}if(userId&&db&&authentication.cohorts?.enabled){let mwUsersTable=requestSchemaTables.users;if(mwUsersTable)try{let mwCohortId=(await db.select().from(mwUsersTable).where(eq63(mwUsersTable.id,userId)).limit(1))[0]?.cohortId;if(mwCohortId){let mwCohortsTable=requestSchemaTables.userCohorts??requestSchemaTables.user_cohorts;if(mwCohortsTable){let mwExpiresAt=(await db.select().from(mwCohortsTable).where(eq63(mwCohortsTable.id,mwCohortId)).limit(1))[0]?.expiresAt;if(mwExpiresAt&&new Date(mwExpiresAt)<new Date)return set2.status=403,logger2.traceSync({message:"Cohort expired - access denied",level:"warn",context:{path:pathname,method,userId,cohortId:mwCohortId},audit:toAudit(auditPayload,"Cohort expired",{userId:userId??null})}),Error("Your access has expired. Please contact your administrator.")}}}catch{}}if(request.headers.set("x-access-token",tokens.access_token||""),request.headers.set("x-refresh-token",tokens.refresh_token||""),request.headers.set("x-session-id",tokens.session_token||""),request.headers.set("x-user-id",userId||""),roles&&roles.length>0)request.headers.set("x-user-roles",encodeHeaderList(roles));if(claimsFromToken&&claimsFromToken.length>0)request.headers.set("x-user-claims",encodeHeaderList(claimsFromToken));{let encodedScopes=encodeClaimScopesHeader(jwtResult.valid?jwtResult.payload.claimScopes:void 0);if(encodedScopes)request.headers.set("x-user-claim-scopes",encodedScopes)}}}}).onAfterHandle(({request,set:set2})=>{let afterUrl=new URL(request.url),afterStatus=typeof set2.status==="number"?set2.status:200,afterStartStr=request.headers.get("x-request-start-time"),afterDuration=afterStartStr?Date.now()-parseInt(afterStartStr,10):0;if(requestLogConfig.enabled&&!isRequestLogExcluded(afterUrl.pathname)){let isSlow=afterDuration>=requestLogConfig.slowThresholdMs,level=afterStatus>=500?"error":afterStatus>=400||isSlow?"warn":"info";logger2.log(level,`\u2190 ${request.method} ${afterUrl.pathname} ${afterStatus} (${afterDuration}ms)`,{requestId:request.headers.get("x-request-id")||void 0,method:request.method,path:afterUrl.pathname,query:requestLogConfig.includeQuery&&afterUrl.search?afterUrl.search:void 0,statusCode:afterStatus,durationMs:afterDuration,slow:isSlow||void 0,userId:request.headers.get("x-user-id")||void 0,authType:request.headers.get("x-auth-type")||void 0,tenant:request.headers.get("x-tenant-schema")||void 0,ip:request.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||request.headers.get("x-real-ip")||void 0},void 0,void 0,"middleware.request")}if(monitoringService){let startTimeStr=request.headers.get("x-request-start-time"),startTime=startTimeStr?parseInt(startTimeStr,10):Date.now(),responseTimeMs=Date.now()-startTime,url=new URL(request.url),status=typeof set2.status==="number"?set2.status:200;monitoringService.recordRequest({endpoint:url.pathname,method:request.method,status,responseTimeMs,isError:status>=500,errorType:status>=500?"server_error":status>=400?"client_error":void 0})}if(liveMonitoringService){let url=new URL(request.url),headersObj=redactSensitiveHeaders(request.headers);liveMonitoringService.recordRequest({path:url.pathname,method:request.method,timestamp:Date.now(),headers:headersObj})}}).onError((ctx)=>{let{set:set2,code,error:error3,request}=ctx,status=statusOfError(code,error3),message="Internal Server Error",pgCode,clientSafe=!1;if(error3 instanceof Error){let cause=error3.cause;if(pgCode=cause?.code,pgCode==="23505")message="A record with this value already exists",clientSafe=!0;else if(pgCode==="23503")message="Referenced record does not exist",clientSafe=!0;else if(pgCode==="23502")message=`Missing required field: ${cause?.column||"a required field is empty"}`,clientSafe=!0;else if(pgCode==="22P02")message=cause?.routine==="string_to_uuid"?"Invalid ID format":"Invalid data format",clientSafe=!0;else if(pgCode)message=`Database error (${pgCode}): ${cause?.detail||cause?.message||error3.message}`;else if(code==="VALIDATION")message=describeValidationError(error3)??error3.message,clientSafe=!0;else message=error3.message,clientSafe=status<500}try{let errUrl=new URL(request.url),errStartStr=request.headers.get("x-request-start-time");logger2.log(status>=500?"error":"warn",`\u2716 ${request.method} ${errUrl.pathname} ${status}: ${message}`,{requestId:request.headers.get("x-request-id")||void 0,method:request.method,path:errUrl.pathname,statusCode:status,elysiaCode:typeof code==="string"?code:void 0,pgCode,durationMs:errStartStr?Date.now()-parseInt(errStartStr,10):void 0,userId:request.headers.get("x-user-id")||void 0,tenant:request.headers.get("x-tenant-schema")||void 0},status>=500?error3:void 0)}catch(logErr){logger2.error("Failed to log request error",logErr)}set2.status=status;let clientMessage=clientSafe?message:"Internal Server Error";return Response.json({isSuccess:!1,message:clientMessage,status,errors:[{message:clientMessage}],data:null})});let featureAdminRoles={};for(let[feature,section]of Object.entries(resolvedOptions)){if(!section||typeof section!=="object")continue;let roles=section.adminRoles;if(!Array.isArray(roles))continue;let named=roles.filter((role)=>typeof role==="string"&&role.length>0);if(named.length>0)featureAdminRoles[feature]=named}logger2.info("Creating routes for entities"),createEntityRoutes(plugin,{db,schemaTables,schemaRelations,entities,logger:logger2,databaseUrl:envResolved.databaseUrl,dbPool,storage:resolvedOptions.storage,cdnMedia:{transform:mergeTransformConfig(resolvedOptions.storage?.cdn?.transform),video:mergeVideoConfig(resolvedOptions.storage?.cdn?.video),pdf:mergePdfConfig(resolvedOptions.storage?.cdn?.pdf)},authorization:resolvedOptions.authorization,featureAdminRoles,accountLinks:authentication?.accountLinks,authMode:authentication?.mode,idpUrl:authentication?.idpUrl?process.env[authentication.idpUrl]||authentication.idpUrl:void 0,isEmailServiceAvailable:()=>!!getEmailService()?.isAvailable(),onRoleChanged:({userId:subjectId,roleName,assigned})=>{if(!db)return;let service=new NotificationService({db,schemaTables,config:resolvedOptions.notification??{},logger:logger2,getEmailService}),title=assigned?`Yeni yetki: ${roleName}`:`Yetki kald\u0131r\u0131ld\u0131: ${roleName}`,body=assigned?`Portalda "${roleName}" yetkisi hesab\u0131n\u0131za tan\u0131mland\u0131. Yeni b\xF6l\xFCmler men\xFCn\xFCzde g\xF6r\xFCnecek.`:`Portalda "${roleName}" yetkiniz kald\u0131r\u0131ld\u0131. Bu yetkiye ba\u011Fl\u0131 b\xF6l\xFCmler art\u0131k g\xF6r\xFCnmeyecek.`;service.send({user_id:subjectId,title,body,type:"system",source:"authorization",channels:["portal","email"]}).catch(()=>{})},tenantRegistry,getTenantRegistry:()=>tenantRegistry,claimsCache});let isConsumerMode=authentication?.mode==="consumer";if(isMultiTenant&&!isConsumerMode)createTenantRoutes(plugin,{getDb:()=>db,logger:logger2,getTenantRegistry:()=>tenantRegistry,schemaName:targetSchemaName}),logger2.info("[MultiTenant] Tenant routes pre-registered (handlers check runtime readiness)");else if(isMultiTenant&&isConsumerMode)plugin.post("/tenants/refresh",async(ctx)=>{if(!tenantRegistry||!tenantRegistry.isConsumerMode())return ctx.set.status=503,{success:!1,message:"Tenant registry not ready"};try{return{success:!0,data:await tenantRegistry.syncFromIdp()}}catch(err){let msg=err instanceof Error?err.message:String(err);return ctx.set.status=500,{success:!1,message:`Tenant sync failed: ${msg}`}}}),logger2.info("[MultiTenant] Consumer tenant refresh route registered (/tenants/refresh)");let domainServices=null;if(resolvedOptions.domains?.enabled){if(domainServices=createDomainServices({options:resolvedOptions,logger:logger2,getDb:()=>db,getTenantRegistry:()=>tenantRegistry}),domainServices)createDomainRoutes(plugin,{getDomainService:()=>domainServices?.domainService??null,getRegistrationService:()=>domainServices?.registrationService??null,logger:logger2,basePath:resolvedOptions.domains.basePath||"/domains",resolveTenantIdForSchema:(schema3)=>schema3&&tenantRegistry?tenantRegistry.getTenantBySchemaName(schema3)?.id??null:null}),logger2.info("[Domains] Custom domain routes registered",{provider:domainServices.domainService.config.provider,basePath:resolvedOptions.domains.basePath||"/domains"})}if(authentication?.enabled&&!isConsumerMode&&db){let resolveTableForTenant=(tableName,reqSchemaName)=>{if(reqSchemaName&&tenantRegistry){let ctx=tenantRegistry.getSchemaContext(reqSchemaName);if(ctx?.schemaTables[tableName])return ctx.schemaTables[tableName]}return schemaTables[tableName]},usersTable=schemaTables.users,sessionsTable=schemaTables.userSessions||schemaTables.user_sessions||schemaTables.sessions;if(!sessionsTable&&authentication.sessions?.enabled)logger2.warn("[AUTH] sessions is enabled but user_sessions table not found in schema. Disabling sessions.");if(usersTable){await initiateRedisManager(resolvedOptions);let{createAuthRoutes:createAuthRoutes2}=(init_auth(),__toCommonJS(exports_auth)),{signJWT:signJWT2,verifyJWT:verifyJWT3}=(init_JWT(),__toCommonJS(exports_JWT)),{generateSession:generateSession2,deleteSession:deleteSession2}=(init_SessionStore(),__toCommonJS(exports_SessionStore));createAuthRoutes2(plugin,{authConfig:{db,logger:logger2,usersTable,sessionsTable,userRolesTable:schemaTables.userRoles,rolesTable:schemaTables.roles,roleClaimsTable:schemaTables.roleClaims,claimsTable:schemaTables.claims,authentication:{enabled:authentication.enabled,get defaultRole(){return resolvedOptions.authentication?.defaultRole||process.env.AUTH_DEFAULT_ROLE},get defaultRoles(){return resolvedOptions.authentication?.defaultRoles},cookieDomain:resolvedOptions.authentication?.cookieDomain,get trustedAppOrigins(){return trustedAppOrigins()},emailExemptDomains:authentication?.emailExemptDomains,accessToken:authentication.accessToken,refreshToken:authentication.refreshToken,sessionToken:authentication.sessionToken,deviceTrust:authentication.sessions?.deviceTrust}},features:{login:authentication.login,register:authentication.register,logout:authentication.logout,refresh:authentication.refresh,passwordReset:withResolvedRedirects(authentication.passwordReset,["redirectUrl"]),passwordChange:authentication.passwordChange,passwordSet:authentication.passwordSet,sessions:withResolvedRedirects(authentication.sessions,["approvalRedirectUrl"]),magicLink:withResolvedRedirects(authentication.magicLink,["redirectUrl"]),me:authentication.me||{enabled:!0,route:"/auth/me"},invite:withResolvedRedirects(authentication.invite,["redirectUrl"]),captcha:authentication.captcha,oauth:authentication.oauth?.enabled&&envResolved.oauthProviders?{...withResolvedRedirects(authentication.oauth,["successRedirectUrl","errorRedirectUrl"]),providers:liveOAuthProviders(envResolved.oauthProviders)}:void 0,apiKeys:authentication.apiKeys?.enabled?{enabled:!0,route:authentication.apiKeys.route,keyPrefix:authentication.apiKeys.keyPrefix,maxKeysPerUser:authentication.apiKeys.maxKeysPerUser,defaultExpiresIn:authentication.apiKeys.defaultExpiresIn,allowApplicationKeys:authentication.apiKeys.allowApplicationKeys,preventApiKeyManagement:authentication.apiKeys.preventApiKeyManagement}:void 0,webauthn:authentication.webauthn},sessionsTable,oauthAccountsTable:schemaTables.oauthAccounts,oauthStateStore:(()=>{let oauthRedis=getRedisManager();if(!oauthRedis)return;let{createRedisOAuthStateStore:createRedisOAuthStateStore2}=__toCommonJS(exports_stateStore);return createRedisOAuthStateStore2(oauthRedis)})(),apiKeysTable:schemaTables.apiKeys,schemaTables,schemaRelations,tenantRegistry,getTenantRegistry:()=>tenantRegistry,databaseUrl:envResolved.databaseUrl,dbPool,admin:(()=>{let adminCfg=resolvedOptions.authentication?.admin;return{impersonate:{enabled:!0},changeUserId:{enabled:!0},createUser:adminCfg?.createUser??{enabled:!0},passwordTools:adminCfg?.passwordTools??{enabled:!1}}})(),schemaName:targetSchemaName,getEmailService,appName:resolvedOptions.appId,webauthnService:(()=>{if(!authentication.webauthn?.enabled||!db)return null;let{WebAuthnService:WebAuthnService2}=(init_WebAuthn(),__toCommonJS(exports_WebAuthn)),{createDbWebAuthnStorage:createDbWebAuthnStorage2}=(init_dbStorage(),__toCommonJS(exports_dbStorage)),rpName=authentication.webauthn.rpName||resolvedOptions.appId||"Nucleus",rpID=authentication.webauthn.rpID||"localhost",expectedOrigins=authentication.webauthn.expectedOrigins||[`http://${rpID}`,`https://${rpID}`],challengeTtlMs=authentication.webauthn.challengeTtl?parseTimeToSeconds2(authentication.webauthn.challengeTtl)*1000:300000,storage=createDbWebAuthnStorage2({db,resolveTable:resolveTableForTenant});return new WebAuthnService2({rp:{rpName,rpID,expectedOrigins},challengeTtlMs,storage,userVerification:authentication.webauthn?.userVerification})})(),captchaService:(()=>{let redisManager=getRedisManager();if(!authentication.captcha?.enabled||!redisManager)return null;return new CaptchaService({redis:{get:async(key2)=>{let result=await redisManager.read(key2);return result.success?result.data:null},set:async(key2,value2,options)=>{await redisManager.create(key2,value2,options?.ex)},del:async(key2)=>{await redisManager.remove(key2)},incrementCounter:(key2,delta,ttlSeconds)=>redisManager.incrementCounter(key2,delta,ttlSeconds)},logger:logger2,config:{enabled:!0,type:authentication.captcha.type||"math",difficulty:authentication.captcha.difficulty||"medium",expiresIn:authentication.captcha.expiresIn||"5m",maxAttempts:authentication.captcha.maxAttempts||3,caseSensitive:authentication.captcha.caseSensitive??!1}})})(),tokenResponseConfig:{accessToken:{setHeadersEnabled:authentication.accessToken?.setHeadersEnabled??!0,returnJson:authentication.accessToken?.returnJson??!0},refreshToken:{setHeadersEnabled:authentication.refreshToken?.setHeadersEnabled??!0,returnJson:authentication.refreshToken?.returnJson??!0},sessionToken:{setHeadersEnabled:authentication.sessionToken?.setHeadersEnabled??!0,returnJson:authentication.sessionToken?.returnJson??!0}},helpers:{signAccessToken:(userId,roles,claims,tenant,claimScopes)=>{let resolveMode=resolvedOptions.authorization?.jwtClaimsMode==="resolve"&&claimsCache,hasClaimScopes=!resolveMode&&!!claimScopes&&Object.keys(claimScopes).length>0,token=signJWT2({subject:userId,expiresInSeconds:parseTimeToSeconds2(authentication.accessToken?.expiresIn||"15m"),issuer:authentication.accessToken?.issuer,audience:authentication.accessToken?.audience,customClaims:{...roles&&roles.length>0?{roles}:{},...!resolveMode&&claims&&claims.length>0?{claims}:{},...hasClaimScopes?{claimScopes}:{},...tenant?{tenant}:{}}},envResolved.accessTokenSecret||"",authentication.accessToken?.algorithm||"HS256");return warnIfAccessTokenTooLargeForCookie(token,resolveMode?"resolve":resolvedOptions.authorization?.jwtClaimsMode),token},signRefreshToken:(userId,rememberMe)=>signJWT2({subject:userId,expiresInSeconds:longerLifetime(rememberMe?authentication.rememberMe?.expiresIn:void 0,authentication.refreshToken?.expiresIn,604800),issuer:authentication.refreshToken?.issuer,audience:authentication.refreshToken?.audience},envResolved.refreshTokenSecret||"",authentication.refreshToken?.algorithm||"HS256"),verifyRefreshToken:(token)=>verifyJWT3(token,envResolved.refreshTokenSecret||"",{issuer:authentication.refreshToken?.issuer,audience:authentication.refreshToken?.audience}),createSession:async(params)=>{let sessionTtlSeconds=longerLifetime(params.rememberMe?authentication.rememberMe?.expiresIn:void 0,authentication.sessionToken?.expiresIn,2592000),result=await generateSession2({userId:params.userId,deviceInfo:params.deviceInfo,rememberMe:params.rememberMe,loginMethod:params.loginMethod,expiresInSeconds:sessionTtlSeconds});if(!result.success)throw logger2.error("[createSession] failed to create session",{userId:params.userId,error:result.error}),Error(`Session storage unavailable: ${result.error||"unknown error"}`);return result.session.id},destroySession:async(sessionId)=>deleteSession2({sessionId}),saveSessionToDb:async(sessionId,params,reqSchemaName)=>{let resolvedSessionsTable=resolveTableForTenant("userSessions",reqSchemaName)||resolveTableForTenant("user_sessions",reqSchemaName)||resolveTableForTenant("sessions",reqSchemaName)||sessionsTable;if(!resolvedSessionsTable||!db)return;let sessionsConfig=authentication.sessions,deviceInfo=ensureDeviceInfo(params.deviceInfo||{ipAddress:""}),resolvedUsersTableForExempt=resolveTableForTenant("users",reqSchemaName),sessionUserEmail=null;if(resolvedUsersTableForExempt)sessionUserEmail=(await db.select().from(resolvedUsersTableForExempt).where(eq63(resolvedUsersTableForExempt.id,params.userId)).limit(1))[0]?.email??null;let userIsEmailExempt=sessionUserEmail?isEmailExempt(sessionUserEmail,authentication?.emailExemptDomains):!1,deviceFingerprint=deviceInfo.deviceHint?`${deviceInfo.browserName||""}-${deviceInfo.osName||""}-${deviceInfo.deviceType||""}-${deviceInfo.deviceHint}`:`${deviceInfo.browserName||""}-${deviceInfo.osName||""}-${deviceInfo.deviceType||""}`,existingSessions=await db.select().from(resolvedSessionsTable).where(and23(eq63(resolvedSessionsTable.userId,params.userId),eq63(resolvedSessionsTable.isActive,!0))),hasValidFingerprint=deviceFingerprint&&!deviceFingerprint.includes("--unknown")&&!deviceFingerprint.includes("Bot/Crawler")&&!deviceFingerprint.includes("Headless")&&deviceFingerprint!=="--"&&deviceFingerprint!=="--unknown",allUserSessions=await db.select().from(resolvedSessionsTable).where(eq63(resolvedSessionsTable.userId,params.userId)),isNewDevice=hasValidFingerprint?!existingSessions.some((s)=>s.deviceFingerprint===deviceFingerprint):!1,wasPreviouslyApproved=hasValidFingerprint?allUserSessions.some((s)=>{let sess=s;return sess.deviceFingerprint===deviceFingerprint&&sess.approvalStatus==="approved"}):!1,hasAnyApprovedSession=existingSessions.some((s)=>s.approvalStatus==="approved"),isImpersonationLogin=params.loginMethod==="impersonation"||params.loginMethod==="impersonation_stop",isOAuthLogin=params.loginMethod?.startsWith("oauth:"),requiresApproval=!isImpersonationLogin&&!userIsEmailExempt&&sessionsConfig?.trustNewDevices===!1&&isNewDevice&&!wasPreviouslyApproved&&hasValidFingerprint&&hasAnyApprovedSession,deviceTrustCfg=sessionsConfig?.deviceTrust,dtTable=deviceTrustCfg?.enabled?resolveTableForTenant("trustedDevices",reqSchemaName)||resolveTableForTenant("trusted_devices",reqSchemaName):void 0,deviceTrustMint=null,deviceTokenToSet=null;if(deviceTrustCfg?.enabled&&dtTable){let DT=await Promise.resolve().then(() => (init_DeviceTrust(),exports_DeviceTrust)),DTStore=await Promise.resolve().then(() => (init_store2(),exports_store)),dtNow=new Date,dtRows=params.deviceToken?await DTStore.findDeviceRowsByRawToken(db,dtTable,params.deviceToken):[],knownRow=DT.selectUsableDeviceRow(dtRows,params.userId,dtNow),pendingRow=dtRows.find((r2)=>(r2.userId??r2.user_id)===params.userId&&r2.status==="pending"),isFirstEver=allUserSessions.length===0&&await DTStore.userHasNoTrustedDevices(db,dtTable,params.userId),decision=DT.decideDeviceApproval({knownDevice:!!knownRow,trustNewDevices:sessionsConfig?.trustNewDevices??!0,hasValidFingerprint:!!hasValidFingerprint,isFirstEverDevice:isFirstEver,loginMethod:params.loginMethod,approvalMethods:deviceTrustCfg.approvalMethods??["password","magic_link","sso","webauthn","oauth:*","register"],onUnidentifiable:deviceTrustCfg.onUnidentifiable??"require_approval",isImpersonation:isImpersonationLogin,isEmailExempt:userIsEmailExempt});if(knownRow)await DTStore.touchDevice(db,dtTable,knownRow.id,deviceInfo.ipAddress).catch(()=>{});if(decision.deny)return logger2.warn("[AUTH] Device-trust denied unidentifiable device",{userId:params.userId}),{requiresApproval:!1,denied:!0};let reuseSessionId=pendingRow?.originSessionId??pendingRow?.origin_session_id;if(decision.requiresApproval&&reuseSessionId)return{requiresApproval:!0,sessionId:reuseSessionId};requiresApproval=decision.requiresApproval,deviceTrustMint=decision.mintToken?decision.trustImmediately?"trusted":"pending":null}logger2.info("[AUTH] Device fingerprint analysis",{userId:params.userId,deviceFingerprint,hasValidFingerprint,isNewDevice,wasPreviouslyApproved,loginMethod:params.loginMethod,isImpersonationLogin,isOAuthLogin,existingSessionCount:existingSessions.length,hasAnyApprovedSession,requiresApproval});let approvalToken=null,approvalStatus="approved";if(requiresApproval){let existingPending=deviceTrustCfg?.enabled?void 0:allUserSessions.find((s)=>{let sess=s;return sess.deviceFingerprint===deviceFingerprint&&(sess.approvalStatus==="pending"||sess.approval_status==="pending")&&sess.approvalToken});if(existingPending){let pendingSess=existingPending,pendingRequestedAt=pendingSess.approvalRequestedAt||pendingSess.approval_requested_at;if(pendingRequestedAt?Date.now()-new Date(pendingRequestedAt).getTime()<86400000:!0)return logger2.info("[AUTH] Reusing existing pending session for same device",{userId:params.userId,deviceFingerprint,existingSessionId:pendingSess.id}),{requiresApproval:!0,sessionId:pendingSess.id}}let{randomBytes:randomBytes8}=await import("crypto");approvalToken=randomBytes8(32).toString("hex"),approvalStatus="pending",logger2.info("[AUTH] New device requires approval",{userId:params.userId,deviceFingerprint,ipAddress:deviceInfo.ipAddress})}let staleBotSessions=existingSessions.filter((s)=>{let sess=s,fp=(sess.deviceFingerprint||"").toLowerCase(),ip=sess.ipAddress||"",ua=(sess.userAgent||"").toLowerCase(),isBotFingerprint=!fp||fp==="--"||fp==="--unknown"||fp.includes("bot/crawler")||fp.includes("headless")||fp.includes("unknown-unknown"),isServerAction=ua.includes("nucleusserveraction")||ua.includes("serveraction")||ua.includes("node-fetch")||ua.includes("undici");return isBotFingerprint&&(ip==="127.0.0.1"||ip==="::1"||ip==="localhost"||!ip)||isServerAction});if(staleBotSessions.length>0){for(let botSession of staleBotSessions)await db.update(resolvedSessionsTable).set({isActive:!1,revokedAt:new Date,revokedReason:"bot_session_cleanup"}).where(eq63(resolvedSessionsTable.id,botSession.id));logger2.info("[AUTH] Cleaned up stale bot/crawler sessions",{userId:params.userId,cleanedCount:staleBotSessions.length})}if(hasValidFingerprint&&!requiresApproval){let sameDeviceOldSessions=existingSessions.filter((s)=>s.deviceFingerprint===deviceFingerprint);for(let oldSession of sameDeviceOldSessions)await db.update(resolvedSessionsTable).set({isActive:!1,revokedAt:new Date,revokedReason:"same_device_relogin"}).where(eq63(resolvedSessionsTable.id,oldSession.id));if(sameDeviceOldSessions.length>0)logger2.info("[AUTH] Revoked old same-device sessions",{userId:params.userId,deviceFingerprint,revokedCount:sameDeviceOldSessions.length})}if(!sessionsConfig?.allowMultipleDevices&&existingSessions.length>0){if((hasValidFingerprint?existingSessions.filter((s)=>s.deviceFingerprint===deviceFingerprint):[]).length===0)for(let oldSession of existingSessions)await db.update(resolvedSessionsTable).set({isActive:!1,revokedAt:new Date,revokedReason:"new_device_login"}).where(eq63(resolvedSessionsTable.id,oldSession.id))}if(sessionsConfig?.maxActiveSessions){let{count:count3}=await import("drizzle-orm"),currentCount=(await db.select({count:count3()}).from(resolvedSessionsTable).where(and23(eq63(resolvedSessionsTable.userId,params.userId),eq63(resolvedSessionsTable.isActive,!0))))[0]?.count||0;if(currentCount>=sessionsConfig.maxActiveSessions){let{asc:asc2}=await import("drizzle-orm"),oldestSessions=await db.select().from(resolvedSessionsTable).where(and23(eq63(resolvedSessionsTable.userId,params.userId),eq63(resolvedSessionsTable.isActive,!0))).orderBy(asc2(resolvedSessionsTable.createdAt)).limit(currentCount-sessionsConfig.maxActiveSessions+1);for(let oldSession of oldestSessions)await db.update(resolvedSessionsTable).set({isActive:!1,revokedAt:new Date,revokedReason:"max_sessions_exceeded"}).where(eq63(resolvedSessionsTable.id,oldSession.id))}}let trustScore=100;if(deviceInfo.isHeadless)trustScore-=50;if(deviceInfo.isBot)trustScore-=40;if(deviceInfo.isSuspicious)logger2.warn("[AUTH] Suspicious login detected",{userId:params.userId,suspiciousPatterns:deviceInfo.suspiciousPatterns,userAgent:deviceInfo.userAgent,ipAddress:deviceInfo.ipAddress});if(isNewDevice)trustScore-=25;if(!deviceInfo.ipAddress||deviceInfo.ipAddress==="unknown")trustScore-=20;if(!deviceInfo.browserName)trustScore-=15;if(!deviceInfo.osName)trustScore-=15;if(!deviceInfo.deviceType||deviceInfo.deviceType==="unknown")trustScore-=10;if(!deviceInfo.deviceName||deviceInfo.deviceName==="Unknown Device")trustScore-=5;let validFingerprint=deviceFingerprint&&!deviceFingerprint.includes("--unknown")&&deviceFingerprint!=="--",validIp=deviceInfo.ipAddress&&deviceInfo.ipAddress!=="unknown";if(validFingerprint){if(existingSessions.filter((s)=>s.deviceFingerprint===deviceFingerprint).length>0)trustScore+=20}if(validIp){if(existingSessions.filter((s)=>s.ipAddress===deviceInfo.ipAddress).length>0)trustScore+=15}trustScore=Math.max(0,Math.min(100,trustScore));let LOW_TRUST_THRESHOLD=50;if(await db.insert(resolvedSessionsTable).values({id:sessionId,userId:params.userId,tokenHash:sessionId,deviceFingerprint,deviceName:deviceInfo.deviceName,deviceType:deviceInfo.deviceType,browserName:deviceInfo.browserName,browserVersion:deviceInfo.browserVersion,osName:deviceInfo.osName,osVersion:deviceInfo.osVersion,ipAddress:deviceInfo.ipAddress,locationCountry:deviceInfo.locationCountry,locationCity:deviceInfo.locationCity,loginMethod:params.loginMethod||"password",rememberMe:params.rememberMe??!1,trustScore,lastActivityAt:new Date,createdAt:new Date,expiresAt:(()=>{let ttl=lifetimeSeconds(authentication.sessionToken?.expiresIn,2592000);return ttl===null?null:new Date(Date.now()+ttl*1000)})(),isActive:approvalStatus==="approved",approvalStatus,approvalToken,approvalRequestedAt:requiresApproval?new Date:null}),shouldNotifyDevice({emailAvailable:Boolean(getEmailService()?.isAvailable()),isImpersonationLogin:Boolean(isImpersonationLogin),notifyOnNewDevice:Boolean(sessionsConfig?.notifyOnNewDevice),isNewDevice,trustScore,lowTrustThreshold:LOW_TRUST_THRESHOLD,requiresApproval:Boolean(requiresApproval)})){let resolvedUsersTable=resolveTableForTenant("users",reqSchemaName);if(resolvedUsersTable){let user=(await db.select().from(resolvedUsersTable).where(eq63(resolvedUsersTable.id,params.userId)).limit(1))[0];if(user?.email&&!isEmailExempt(user.email,authentication?.emailExemptDomains)){let isLowTrust=trustScore<LOW_TRUST_THRESHOLD,sessionsRoute=authentication.sessions?.route||"/auth/sessions",configuredUrl=authentication.sessions?.approvalRedirectUrl||"",isLegacyFrontendUrl=!configuredUrl||configuredUrl.endsWith("/devices"),approvalBase;if(!isLegacyFrontendUrl)approvalBase=configuredUrl;else{let origin=pickTrustedOrigin(params.requestOrigin,configuredUrl,trustedAppOrigins());if(params.requestOrigin&&origin!==params.requestOrigin)logger2.warn("[AUTH] Device-approval link origin refused \u2014 not in trustedAppOrigins",{requested:params.requestOrigin,used:origin||"(none)"});approvalBase=`${origin||"http://localhost:9000"}${sessionsRoute}`}let approveUrl=approvalToken?`${approvalBase}/approve-page?token=${approvalToken}`:"",rejectUrl=approvalToken?`${approvalBase}/reject-page?token=${approvalToken}`:"",subject,emailHtml,brandName=resolvedOptions.appId||"Nucleus",loginTime=new Date().toLocaleString("en-US",{dateStyle:"medium",timeStyle:"short"}),deviceSummary=`${deviceInfo.browserName||"Unknown"} ${deviceInfo.browserVersion||""} on ${deviceInfo.osName||"Unknown"} ${deviceInfo.osVersion||""}`,emailWrapper=(content)=>`
|
|
1989
|
+
${detail}`)}let sensitiveNames=resolvedForBoot.flatMap((e)=>e.columns??[]).filter((c)=>c.sensitive===!0).map((c)=>c.name);{registerSensitiveColumns(sensitiveNames);let redactUnion=[...loggingConfig?.redactKeys||[],...sensitiveColumnNames()];if(logger2.configure({redactKeys:redactUnion}),Logger.getInstance().configure({redactKeys:redactUnion}),sensitiveNames.length>0)logger2.info("[Schema] Sensitive columns registered",{columns:sensitiveNames})}}let requestLogConfig={enabled:loggingConfig?.requests?.enabled!==!1,logArrival:loggingConfig?.requests?.logArrival===!0,includeQuery:loggingConfig?.requests?.includeQuery!==!1,slowThresholdMs:loggingConfig?.requests?.slowThresholdMs??3000,excludePaths:loggingConfig?.requests?.excludePaths??["/health"]},isRequestLogExcluded=(pathname)=>requestLogConfig.excludePaths.some((p)=>p.endsWith("*")?pathname.startsWith(p.slice(0,-1)):pathname===p),envValidation=validateEnvVariables(resolvedOptions);if(!envValidation.valid){for(let error3 of envValidation.errors)logger2.error(`[CONFIG] ${error3.message}`,{field:error3.field,envName:error3.envName});throw Error("Nucleus configuration error: Missing required environment variables. Check logs for details.")}let{resolved:envResolved}=envValidation;{let secretEntries=[["accessToken",envResolved.accessTokenSecret],["refreshToken",envResolved.refreshTokenSecret],["sessionToken",envResolved.sessionTokenSecret]];for(let[name2,value2]of secretEntries)if(value2&&value2.length<32)logger2.warn(`[Security] authentication.${name2}.secret is only ${value2.length} chars \u2014 use at least ${"32"} random bytes.`);let present=secretEntries.map(([,v])=>v).filter((v)=>!!v);if(present.length>1&&new Set(present).size<present.length)logger2.warn("[Security] Two or more of the access/refresh/session token secrets are identical \u2014 use a distinct secret for each.")}let tokenNames={access_token:authentication?.accessToken?.name||"access_token",refresh_token:authentication?.refreshToken?.name||"refresh_token",session_token:authentication?.sessionToken?.name||"session_token"},csrfConfig=resolveCsrfConfig(authentication?.csrf),csrfAuthCookieNames=[tokenNames.session_token,tokenNames.access_token],targetSchemaName=database?.sharedSchema||database?.schemas?.[0]||"main",targetSchema=pgSchema2(targetSchemaName);if(envResolved.databaseUrl)await ensureDatabaseExists(envResolved.databaseUrl,logger2,envResolved.databaseAuthMode);let db=null,dbPool=null,dbAuthMode=envResolved.databaseAuthMode||"password",backgroundIntervals=[],trackInterval=(timer)=>{timer.unref?.(),backgroundIntervals.push(timer)};if(envResolved.databaseUrl){let{Pool:Pool2}=await import("pg"),poolOptions=resolveDbPoolConfig(database?.pool);if(dbAuthMode==="password")dbPool=new Pool2({connectionString:envResolved.databaseUrl,...poolOptions});else{let{getPostgresToken:getPostgresToken2}=await Promise.resolve().then(() => (init_Azure(),exports_Azure));await getPostgresToken2(),dbPool=new Pool2({connectionString:envResolved.databaseUrl,password:getPostgresToken2,ssl:{rejectUnauthorized:!0},...poolOptions}),logger2.info(`[Database] Using Entra ID auth mode: ${dbAuthMode}`)}db=drizzle2(dbPool),dbPool.on("error",(err)=>{logger2.warn("[Database] idle pool client error",{error:err instanceof Error?err.message:String(err)})})}let isMultiTenant=database?.isMultiTenant===!0,tenantRegistry=null,schemaTables={},schemaRelations={},claimsCache=null;if(config.schema){let schemasPath=__require("path").resolve(process.cwd(),config.schema),schemas=__require(schemasPath);schemaTables=schemas.createAllTablesForSchema?schemas.createAllTablesForSchema(targetSchema):{}}if(config.relations){let relationsPath=__require("path").resolve(process.cwd(),config.relations);schemaRelations=__require(relationsPath)}let secretsService=null;if(resolvedOptions.secrets?.enabled){let masterKey=resolveMasterKey(resolvedOptions.secrets.encryptionKey);if(!db)logger2.warn("[Secrets] secrets.enabled=true but no database is configured \u2014 disabled");else if(!masterKey)logger2.error("[Secrets] secrets.enabled=true but no encryption key resolved \u2014 set secrets.encryptionKey or NUCLEUS_SECRETS_KEY. Credential storage is disabled; env and literal values still work.");else if(!schemaTables[SECRETS_TABLE])logger2.error(`[Secrets] secrets.enabled=true but the "${SECRETS_TABLE}" table is missing from the generated schema \u2014 re-run schema generation. Credential storage is disabled.`);else{secretsService=new SecretsService({store:new SecretsStore({db,resolveTable:(tableName)=>schemaTables[tableName],masterKey}),logger:logger2,refreshIntervalMs:resolvedOptions.secrets.refreshIntervalMs,getRedis:()=>getRedisManager()}),logger2.info("[Secrets] Credential store enabled");try{if(await secretsService.refresh(),secretsService.isReady())logger2.info("[Secrets] Credentials preloaded for boot-time resolution",{storedCredentials:secretsService.size()})}catch(error3){logger2.warn("[Secrets] Preload failed \u2014 env and literal values still resolve",{error:error3 instanceof Error?error3.message:String(error3)})}}}let resolveCredential=(scope,key2,configValue)=>{if(secretsService)return secretsService.value(scope,key2,configValue);if(!configValue)return;let fromEnv=process.env[configValue];if(fromEnv)return fromEnv;return/^[A-Z][A-Z0-9_]{2,}$/.test(configValue)?void 0:configValue},resolveRedirectUrl=(value2)=>{if(!value2)return;let fromEnv=process.env[value2];if(fromEnv)return fromEnv;return/^[A-Z][A-Z0-9_]{2,}$/.test(value2)?void 0:value2},withResolvedRedirects=(node,keys)=>{if(!node)return node;let resolved={...node};for(let key2 of keys)if(typeof node[key2]==="string")resolved[key2]=resolveRedirectUrl(node[key2]);return resolved},trustedAppOrigins=()=>{let configured=normalizeTrustedOrigins(resolvedOptions.authentication?.trustedAppOrigins);if(!secretsService)return configured;let resolved=secretsService.listValue("authentication","trustedAppOrigins",configured);return resolved.length>0?resolved:configured},liveOAuthProviders=(resolvedProviders)=>{if(!secretsService)return resolvedProviders;let declared=resolvedOptions.authentication?.oauth?.providers??{},live={};for(let[providerName,providerConfig]of Object.entries(resolvedProviders)){let declaredConfig=declared[providerName]??{},entry={...providerConfig};for(let key2 of["clientId","clientSecret","tenantId","redirectUri"]){let declaredValue=declaredConfig[key2],bootValue=providerConfig[key2];Object.defineProperty(entry,key2,{get:()=>{let resolved=secretsService?.value(`authentication.oauth.providers.${providerName}`,key2,typeof declaredValue==="string"?declaredValue:void 0);if(resolved!==void 0)return resolved;return looksLikeEnvName(typeof bootValue==="string"?bootValue:void 0)?void 0:bootValue},enumerable:!0,configurable:!0})}live[providerName]=entry}return live},storageProvider=null;if(resolvedOptions.storage?.enabled){let storageBase=resolvedOptions.storage.basePath||"./uploads";storageProvider=createStorageProvider({provider:resolvedOptions.storage.provider,basePath:storageBase,smb:resolvedOptions.storage.smb,resolveCredential},{logger:logger2}),setStorageProvider(storageProvider)}let buildStorageProvider=(kind)=>{if(!resolvedOptions.storage?.enabled)return null;return createStorageProvider({provider:kind,basePath:resolvedOptions.storage.basePath||"./uploads",smb:resolvedOptions.storage.smb,resolveCredential:(scope,key2,configValue)=>scope==="storage"&&key2==="provider"?kind:resolveCredential(scope,key2,configValue)},{logger:logger2})},swaggerPlugin=createSwaggerPlugin(config.swagger);if(swaggerPlugin)plugin.use(swaggerPlugin);let systemTables2=config.systemTables||[];publicRoutes=buildPublicRoutes(resolvedOptions,systemTables2,"",targetSchemaName),logger2.info(`[AUTH] Built ${publicRoutes.length} public routes`);let rateLimiter=null,monitoringService=null,liveMonitoringService=null,activeEmailProvider=()=>{let declared=resolveCredential("email","provider",resolvedOptions.email?.provider);if(declared==="azure"||declared==="gmail"||declared==="smtp")return emailProviderOn(declared)||resolvedOptions.email?.provider===declared?declared:null;if(emailProviderOn("azure"))return"azure";if(emailProviderOn("gmail"))return"gmail";if(emailProviderOn("smtp"))return"smtp";return null},emailProviderOn=(provider)=>{let configured=resolvedOptions.email?.[provider]?.enabled===!0;return secretsService?secretsService.flag(`email.${provider}`,"enabled",configured):configured},azureEmailCredentials=()=>{let azureConfig=resolvedOptions.email?.azure;return{enabled:!0,connectionString:resolveCredential("email.azure","connection_string",azureConfig?.connection_string)??"",senderAddress:resolveCredential("email.azure","sender_address",azureConfig?.sender_address)??"",fromName:resolveCredential("email.azure","from_name",azureConfig?.from_name)}},gmailCredentials=()=>{let gmailConfig=resolvedOptions.email?.gmail;return{enabled:!0,jsonFilePath:gmailConfig?.json_file_path,serviceAccountJson:resolveCredential("email.gmail","service_account_json",gmailConfig?.service_account_json),fromEmail:resolveCredential("email.gmail","from_email",gmailConfig?.from_email)??"",fromName:resolveCredential("email.gmail","from_name",gmailConfig?.from_name)}},smtpCredentials=()=>{let smtpConfig=resolvedOptions.email?.smtp,port=resolveCredential("email.smtp","port",smtpConfig?.port===void 0?void 0:String(smtpConfig.port)),secure=resolveCredential("email.smtp","secure",smtpConfig?.secure===void 0?void 0:String(smtpConfig.secure));return{enabled:!0,host:resolveCredential("email.smtp","host",smtpConfig?.host)??"",port:port?Number(port):void 0,secure:secure===void 0?void 0:String(secure)==="true",user:resolveCredential("email.smtp","user",smtpConfig?.user)??"",password:resolveCredential("email.smtp","password",smtpConfig?.password)??"",senderAddress:resolveCredential("email.smtp","sender_address",smtpConfig?.sender_address)??"",fromName:resolveCredential("email.smtp","from_name",smtpConfig?.from_name)}},azureService=null,gmailService=null,smtpService=null,getEmailService=()=>{let provider=activeEmailProvider();if(!provider)return null;if(provider==="azure"){if(!azureService)azureService=new AzureEmailService(azureEmailCredentials(),logger2),logger2.info("[AzureEmailService] Initialized",{available:azureService.isAvailable()});else azureService.reconfigure(azureEmailCredentials());return azureService}if(provider==="smtp"){if(!smtpService)smtpService=new SmtpEmailService(smtpCredentials(),logger2),logger2.info("[SmtpEmailService] Initialized",{available:smtpService.isAvailable()});else smtpService.applyConfig(smtpCredentials());return smtpService}if(!gmailService)gmailService=new GmailService(gmailCredentials(),logger2),logger2.info("[GmailService] Initialized",{available:gmailService.isAvailable()});else gmailService.reconfigure(gmailCredentials());return gmailService};if(plugin.decorate("nucleus",createNucleusRuntime({getEmailService,activeEmailProvider})),resolvedOptions.liveMonitoring?.enabled){let liveBasePath=resolvedOptions.liveMonitoring.basePath||"/monitoring",liveStreamInterval=resolvedOptions.liveMonitoring.streamInterval||150;plugin.use(createLiveMonitoringRoutes({getService:()=>liveMonitoringService,logger:logger2,basePath:liveBasePath,streamInterval:liveStreamInterval,db,schemaTables}))}if(resolvedOptions.monitoring?.enabled&&resolvedOptions.monitoring.endpoints?.enabled){let monitoringEndpoints=resolvedOptions.monitoring.endpoints;plugin.use(createMonitoringRoutes({getService:()=>monitoringService,logger:logger2,endpoints:{enabled:!0,basePath:monitoringEndpoints.basePath||"/monitoring",allowRoles:monitoringEndpoints.allowRoles,stream:{enabled:monitoringEndpoints.stream?.enabled!==!1,path:monitoringEndpoints.stream?.path||"/stream",interval:monitoringEndpoints.stream?.interval||"5s"},snapshot:{enabled:monitoringEndpoints.snapshot?.enabled!==!1,path:monitoringEndpoints.snapshot?.path||"/snapshot"},history:{enabled:monitoringEndpoints.history?.enabled!==!1,path:monitoringEndpoints.history?.path||"/history",maxMinutes:monitoringEndpoints.history?.maxMinutes||60},alerts:{enabled:monitoringEndpoints.alerts?.enabled!==!1,path:monitoringEndpoints.alerts?.path||"/alerts"}},db,schemaTables}))}if(serverLogBuffer)plugin.use(createServerLogRoutes({buffer:serverLogBuffer,logger:logger2,basePath:serverLogsConfig?.basePath||resolvedOptions.monitoring?.endpoints?.basePath||"/monitoring",path:serverLogsConfig?.path||"/server-logs",allowRoles:serverLogsConfig?.allowRoles,streamEnabled:serverLogsConfig?.stream!==!1,clearEnabled:serverLogsConfig?.allowClear!==!1,db,schemaTables}));let bootStep=async(name2,run)=>{try{return await run()}catch(error3){logger2.error(`[Boot] Step "${name2}" failed \u2014 continuing in a degraded state rather than crashing`,{error:error3 instanceof Error?error3.message:String(error3)});return}};plugin.onStart(async()=>{await bootStep("redis",()=>initiateRedisManager(resolvedOptions));let redis=getRedisManager();if(redis&&resolvedOptions.configManagement?.enabled)try{let{loadOverridesFromRedis:loadOverridesFromRedis2}=await Promise.resolve().then(() => (init_helpers3(),exports_helpers)),applied=await loadOverridesFromRedis2({read:async(key2)=>{let r2=await redis.read(key2);return{success:r2.success,data:r2.success?r2.data:null}}},resolvedOptions.appId||"nucleus",resolvedOptions);if(applied.length>0)logger2.info(`[ConfigManagement] Loaded ${applied.length} override(s) from Redis`,{sections:applied})}catch(err){logger2.warn("[ConfigManagement] Failed to load overrides from Redis",{error:err instanceof Error?err.message:String(err)})}if(redis&&resolvedOptions.rateLimit?.enabled!==!1)rateLimiter=new RateLimiter({redis,logger:logger2,config:resolvedOptions.rateLimit||{}}),logger2.info(`[RateLimit] Enabled with strategy: ${resolvedOptions.rateLimit?.strategy||"sliding-window"}`);{let channels=resolvedOptions.notification?.channels;if(channels?.telegram?.enabled&&(!channels.telegram.botToken||!channels.telegram.chatId))logger2.warn("[Notification] telegram channel is enabled but botToken/chatId is missing \u2014 telegram deliveries will be skipped");if(channels?.webhook?.enabled&&!channels.webhook.url)logger2.warn("[Notification] webhook channel is enabled but url is missing \u2014 webhook deliveries will be skipped")}if(redis&&resolvedOptions.monitoring?.enabled){let monitoringDb=db,monitoringMetricsTable=schemaTables.monitoringMetrics,monitoringPersistenceEnabled=resolvedOptions.monitoring.persistence?.enabled!==!1,monitoringRetentionDays=resolvedOptions.monitoring.persistence?.retentionDays??30,lastMetricsCleanupAt=0,monitoringDbQuery=monitoringDb?async(sqlText)=>{return(await monitoringDb.execute(sql13.raw(sqlText))).rows}:void 0,monitoringLoadPeaks=monitoringDb&&monitoringPersistenceEnabled&&monitoringMetricsTable?async()=>{let t43=monitoringMetricsTable;return(await monitoringDb.select({metricName:t43.metricName,value:t43.value,recordedAt:t43.recordedAt,tags:t43.tags}).from(t43).where(eq63(t43.metricType,"peak")).orderBy(desc7(t43.value))).map((r2)=>({metricName:String(r2.metricName),value:Number(r2.value??0),at:r2.recordedAt?new Date(r2.recordedAt).getTime():0,context:r2.tags??void 0}))}:void 0;if(monitoringPersistenceEnabled&&monitoringDb&&!monitoringMetricsTable)logger2.warn("[Monitoring] monitoring.persistence is enabled but the monitoring_metrics table is missing from the generated schema \u2014 re-run nucleus-generate to add it");let monitoringFlushToDb=monitoringDb&&monitoringPersistenceEnabled&&monitoringMetricsTable?async(metrics)=>{if(metrics.length===0)return;let metricsTable=monitoringMetricsTable;await monitoringDb.insert(metricsTable).values(metrics.map((m2)=>({metricType:m2.metricType,metricName:m2.metricName,value:m2.value,tags:m2.tags??null,recordedAt:new Date(m2.timestamp)})));let nowMs=Date.now();if(nowMs-lastMetricsCleanupAt>86400000){lastMetricsCleanupAt=nowMs;let cutoff=new Date(nowMs-monitoringRetentionDays*24*60*60*1000);await monitoringDb.delete(metricsTable).where(and23(lt3(metricsTable.recordedAt,cutoff),ne3(metricsTable.metricType,"peak")))}}:void 0;monitoringService=new MonitoringService({redis,logger:logger2,getEmailService,config:resolvedOptions.monitoring,appId:resolvedOptions.appId,dbQuery:monitoringDbQuery,flushToDb:monitoringFlushToDb,loadPeaks:monitoringLoadPeaks}),monitoringService.start(),logger2.info("[Monitoring] Service started")}if(resolvedOptions.liveMonitoring?.enabled)liveMonitoringService=new LiveMonitoringService(resolvedOptions.liveMonitoring),liveMonitoringService.start(),logger2.info("[LiveMonitoring] Service started");let isConsumerModeOnStart=authentication?.mode==="consumer",consumerAllowedTableKeys=isConsumerModeOnStart&&entities?new Set(entities.map((e)=>e.table_name.replace(/_([a-z])/g,(_,c)=>c.toUpperCase()))):null;if(consumerAllowedTableKeys){let opts=resolvedOptions,verificationEnabled=opts.verification?.enabled===!0,notificationEnabled=opts.notification?.enabled===!0,auditEnabled=opts.audit?.enabled===!0,chatEnabled=opts.chat?.enabled===!0,storageEnabled=opts.storage?.enabled===!0,paymentEnabled=opts.payment?.enabled===!0,backupEnabled=opts.backup?.enabled===!0,monitoringPersistenceOn=resolvedOptions.monitoring?.enabled===!0&&resolvedOptions.monitoring?.persistence?.enabled!==!1,featureEnabled={verification:verificationEnabled,notification:notificationEnabled,audit:auditEnabled,chat:chatEnabled,storage:storageEnabled,payment:paymentEnabled,backup:backupEnabled,monitoring:monitoringPersistenceOn,secrets:resolvedOptions.secrets?.enabled===!0,domains:resolvedOptions.domains?.enabled===!0,"multi-tenant":isMultiTenant};for(let sysTable of SYSTEM_TABLES)if(sysTable.feature_set.some((f)=>{if(f==="authentication"||f==="authorization")return!1;if(!(f in featureEnabled))return logger2.warn(`[Schema] Consumer mode has no rule for feature "${f}" (table "${sysTable.table_name}") \u2014 `+"its table will NOT be synced. Add it to featureEnabled in ElysiaPlugin/index.ts."),!1;return featureEnabled[f]===!0})){let camelKey=sysTable.table_name.replace(/_([a-z])/g,(_,c)=>c.toUpperCase());consumerAllowedTableKeys.add(camelKey)}}if(db&&config.schema){let schemas=await import(__require("path").resolve(process.cwd(),config.schema)),auditLogsTable=schemaTables.auditLogs||schemas.auditLogs;if(audit?.enabled&&auditLogsTable)logger2.addAuditTransport(new DatabaseAuditTransport({db,table:auditLogsTable,enabled:!0,dedup:audit.dedup}));let{ensureSchemaExists:ensureSchemaExists2,applySchemaPush:applySchemaPush2}=await Promise.resolve().then(() => (init_schema(),exports_schema)),{reconcileMissingColumns:reconcileMissingColumns2}=await Promise.resolve().then(() => (init_schemaReconcile(),exports_schemaReconcile));try{logger2.info(`Syncing schema to database (target: ${targetSchemaName})...`),await ensureSchemaExists2(db,targetSchemaName);let filteredTables={};try{filteredTables=Object.fromEntries(Object.entries(schemaTables).filter(([key2,v])=>{if(v===void 0||v===null)return!1;if(consumerAllowedTableKeys&&!consumerAllowedTableKeys.has(key2))return!1;if(typeof v==="object"&&v!==null)return Object.getOwnPropertySymbols(v).length>0||v._!==void 0;return!1}));let tableNames=Object.keys(filteredTables);if(logger2.info("[Schema] Tables to sync:",{tables:tableNames,count:tableNames.length,mode:isConsumerModeOnStart?"consumer":"full"}),!isConsumerModeOnStart){let usersTableDef=filteredTables.users;if(usersTableDef){let columnSymbols=Object.getOwnPropertyNames(usersTableDef).filter((k)=>!k.startsWith("_"));logger2.info("[Schema] Users table columns:",{columns:columnSymbols})}}let realExit=process.exit,push;try{process.exit=(code)=>{throw Error(`drizzle-kit called process.exit(${code??0}) during pushSchema \u2014 `+"suppressed so the app can keep booting")};let timeoutMs=database?.schemaPushTimeoutMs??120000;push=await withDeadline(pushSchema({schema:targetSchema,...filteredTables},db,[targetSchemaName]),timeoutMs,`pushSchema did not finish within ${timeoutMs}ms. drizzle-kit most likely hit its `+"interactive rename prompt, which cannot be answered without a TTY \u2014 it appears "+"when a push adds a new table while another table exists in the database but not in the schema. Drop the stale table, or split the change across two deploys.")}finally{process.exit=realExit}if(await applySchemaPush2(push,{schemaName:targetSchemaName,allowDataLoss:database?.allowDataLoss===!0,logger:logger2,execute:(statement)=>db.execute(sql13.raw(statement))}))logger2.info("[Schema] pushSchema completed successfully")}catch(pushError){let msg=pushError instanceof Error?pushError.message:String(pushError),repair=await reconcileMissingColumns2({db,schema:targetSchemaName,tables:filteredTables,logger:logger2,schemaObject:targetSchema});if(!repair||repair.applied>0||repair.plan.createdTables.length>0||repair.plan.missingTables.length>0||repair.plan.unsafe.length>0)logger2.error(`[Schema] pushSchema applied NOTHING: ${msg}`);else logger2.info(`[Schema] pushSchema applied nothing, and nothing was needed \u2014 the database already matches the model. (${msg})`)}logger2.info("[Schema] Schema sync completed",{schema:targetSchemaName})}catch(error3){logger2.error("[Schema] Schema sync failed",error3,{schema:targetSchemaName})}try{let{relaxSessionExpiryIfNever:relaxSessionExpiryIfNever2}=await Promise.resolve().then(() => (init_relaxSessionExpiry(),exports_relaxSessionExpiry)),{sql:sql14}=await import("drizzle-orm");await relaxSessionExpiryIfNever2({db,sql:sql14,schemaName:targetSchemaName,lifetimeSeconds:lifetimeSeconds(authentication?.sessionToken?.expiresIn,2592000),logger:logger2})}catch(error3){logger2.warn("[Schema] Session expiry relaxation skipped",{error:String(error3)})}if(secretsService)try{await secretsService.start(),logger2.info("[Secrets] Credential store ready",{storedCredentials:secretsService.size()})}catch(error3){logger2.error("[Secrets] Credential store failed to start \u2014 env and literal values still resolve",{error:error3 instanceof Error?error3.message:String(error3)})}if(logger2.info("[Database] Connection established"),await bootStep("multi-tenant schemas",async()=>{if(isMultiTenant&&db&&config.schema){let schemasForTenant={};try{let schemaPath=__require("path").resolve(process.cwd(),config.schema);logger2.info("[MultiTenant] Loading schema for tenant registry",{schemaPath}),schemasForTenant=await import(schemaPath),logger2.info("[MultiTenant] Schema loaded",{keys:Object.keys(schemasForTenant).slice(0,10),hasCreateAll:!!schemasForTenant.createAllTablesForSchema})}catch(err){let msg=err instanceof Error?err.message:String(err);logger2.error("[MultiTenant] Failed to load schema for tenant registry",{error:msg})}let createAllFn=schemasForTenant.createAllTablesForSchema;if(createAllFn){let idpUrl=isConsumerModeOnStart?authentication?.idpUrl?String(process.env[authentication.idpUrl]||authentication.idpUrl):void 0:void 0;if(tenantRegistry=new TenantRegistry({db,logger:logger2,mainSchemaName:targetSchemaName,mainSchemaTables:schemaTables,mainSchemaRelations:schemaRelations,createAllTablesForSchema:createAllFn,createAllRelationsForSchema:schemasForTenant.createAllRelationsForSchema,appId:resolvedOptions.appId,authMode:authentication?.mode,tenantResolution:database?.tenantResolution||"both",tenantHeader:database?.tenantHeader||"x-tenant-id",redisCacheTtlSeconds:300,defaultTrustedSources:database?.defaultTrustedSources,idpUrl,allowDataLoss:database?.allowDataLoss===!0,onTenantProvisioned:resolvedOptions.authorization?.enabled&&!isConsumerModeOnStart?async(context)=>{let authConfig={...DEFAULT_AUTHORIZATION_CONFIG,...resolvedOptions.authorization};if(authConfig.autoSeedClaims&&db){let claimEntities=mergeEntitiesByName([...extractSchemaTableEntities(context.schemaTables),...SYSTEM_TABLES.map((table)=>normalizeSystemTable(table)),...effectiveConfigEntities(resolvedOptions.entities||[]),...config.systemTables||[],...resolvedOptions.authorization?.externalEntities||[]]);await seedClaims(db,context.schemaTables,context.schemaRelations,claimEntities,authConfig,logger2)}let seedConfig=resolvedOptions.authorization?.seed;if(seedConfig&&db){let{runSeed:runSeed2}=await Promise.resolve().then(() => (init_SeedRunner(),exports_SeedRunner));await runSeed2(db,context.schemaTables,seedConfig,logger2)}logger2.info(`[Authorization] New tenant schema seeded: ${context.schemaName}`)}:void 0}),isConsumerModeOnStart&&idpUrl){await tenantRegistry.initializeFromIdp(),logger2.info("[MultiTenant] Consumer mode: tenants fetched from IDP");let tenantSyncTimer=setInterval(()=>{tenantRegistry?.syncFromIdp().then((result)=>{if(result.added.length>0||result.removed.length>0)logger2.info(`[MultiTenant] Tenant sync: +${result.added.length} / -${result.removed.length} (total ${result.total})`)}).catch((err)=>{let msg=err instanceof Error?err.message:String(err);logger2.warn(`[MultiTenant] Tenant sync failed: ${msg}`)})},60000);trackInterval(tenantSyncTimer)}else await tenantRegistry.initialize();for(let schemaName of tenantRegistry.getAllSchemaNames()){if(schemaName===targetSchemaName)continue;let ctx=tenantRegistry.getSchemaContext(schemaName);if(ctx){await ensureSchemaExists2(db,schemaName);try{let tenantFilteredTables=Object.fromEntries(Object.entries(ctx.schemaTables).filter(([key2,v])=>{if(v===void 0||v===null)return!1;if(consumerAllowedTableKeys&&!consumerAllowedTableKeys.has(key2))return!1;if(typeof v==="object"&&v!==null)return Object.getOwnPropertySymbols(v).length>0||v._!==void 0;return!1})),tenantSchema=pgSchema2(schemaName),tenantPush=await pushSchema({schema:tenantSchema,...tenantFilteredTables},db,[schemaName]);if(await applySchemaPush2(tenantPush,{schemaName,allowDataLoss:database?.allowDataLoss===!0,logger:logger2,execute:(statement)=>db.execute(sql13.raw(statement))}))logger2.info(`[Schema] Tenant schema synced: ${schemaName}`)}catch(tenantPushError){let msg=tenantPushError instanceof Error?tenantPushError.message:String(tenantPushError);logger2.warn(`[Schema] Tenant schema sync warning for ${schemaName}: ${msg}`)}}}logger2.info(`[MultiTenant] Registry initialized with ${tenantRegistry.getAllSchemaNames().length} schemas`),logger2.info("[MultiTenant] Tenant registry ready, routes were pre-registered")}}}),resolvedOptions.authorization?.enabled&&!isConsumerModeOnStart){let authConfig={...DEFAULT_AUTHORIZATION_CONFIG,...resolvedOptions.authorization,godminEmail:resolveConfigCredential(resolvedOptions.authorization?.godminEmail),godminPassword:resolveConfigCredential(resolvedOptions.authorization?.godminPassword)};if(authConfig.autoSeedClaims){let schemaEntities=extractSchemaTableEntities(schemaTables),systemEntities=SYSTEM_TABLES.map((table)=>normalizeSystemTable(table)),configEntities=effectiveConfigEntities(resolvedOptions.entities||[]),externalEntities=resolvedOptions.authorization?.externalEntities||[],claimEntities=mergeEntitiesByName([...schemaEntities,...configEntities,...systemEntities,...config.systemTables||[],...externalEntities]);logger2.info("[Authorization] Seeding claims...",{schemaEntities:schemaEntities.length,systemEntities:systemEntities.length,configEntities:configEntities.length,externalEntities:externalEntities.length,totalEntities:claimEntities.length}),await seedClaims(db,schemaTables,schemaRelations,claimEntities,authConfig,logger2)}let discoveryConfig=resolvedOptions.authorization?.endpointDiscovery;if(discoveryConfig?.enabled&&(discoveryConfig.runOnBoot??!0)&&db)try{let{runEndpointDiscovery:runEndpointDiscovery2}=await Promise.resolve().then(() => (init_seed(),exports_seed)),discoveryResult=await runEndpointDiscovery2(db,schemaTables,discoveryConfig,logger2);logger2.info("[Authorization] Endpoint discovery completed",{services:discoveryResult.services})}catch(discoveryErr){logger2.error("[Authorization] Endpoint discovery failed",{error:discoveryErr instanceof Error?discoveryErr.message:String(discoveryErr)})}if(authConfig.godminEmail&&authConfig.godminPassword)logger2.info("[Authorization] Setting up godmin..."),await setupGodmin(db,schemaTables,authConfig,logger2);let seedConfig=resolvedOptions.authorization?.seed;if(seedConfig){let{runSeed:runSeed2}=await Promise.resolve().then(() => (init_SeedRunner(),exports_SeedRunner));logger2.info("[Authorization] Running custom seed...");let seedResult=await bootStep("authorization.seed",()=>runSeed2(db,schemaTables,seedConfig,logger2));if(seedResult)logger2.info("[Authorization] Custom seed completed",{rolesCreated:seedResult.rolesCreated,rolesExisting:seedResult.rolesExisting,claimsCreated:seedResult.claimsCreated,claimsExisting:seedResult.claimsExisting,assignmentsCreated:seedResult.assignmentsCreated,assignmentsExisting:seedResult.assignmentsExisting,assignmentsUpdated:seedResult.assignmentsUpdated})}let claimGuardsCfg=resolvedOptions.authorization?.claimGuards;if(claimGuardsCfg?.length){let{seedClaimGuards:seedClaimGuards2}=await Promise.resolve().then(() => (init_ClaimGuard(),exports_ClaimGuard));await bootStep("authorization.claimGuards",()=>seedClaimGuards2(db,schemaTables,claimGuardsCfg,logger2))}let jwtClaimsMode=resolvedOptions.authorization?.jwtClaimsMode||"embed",claimsCacheRedis=getRedisManager();if(jwtClaimsMode==="resolve"&&db&&claimsCacheRedis){let{ClaimsCache:ClaimsCache3}=await Promise.resolve().then(() => (init_ClaimsCache(),exports_ClaimsCache));claimsCache=new ClaimsCache3({prefix:resolvedOptions.authorization?.claimsCachePrefix||"nucleus:claims",redis:{get:async(key2)=>{let r2=await claimsCacheRedis.read(key2);return r2.success?r2.data:null},set:async(key2,value2)=>{await claimsCacheRedis.create(key2,value2)},delete:async(key2)=>{await claimsCacheRedis.remove(key2)}},db,schemaTables,logger:logger2});let cacheInstance=claimsCache,cacheResult=await bootStep("authorization.claimsCache",()=>cacheInstance.buildCache());if(cacheResult)logger2.info("[Authorization] Claims cache built (resolve mode)",{version:cacheResult.version,roleCount:cacheResult.roleCount,totalMappings:cacheResult.totalMappings})}else if(jwtClaimsMode==="resolve"&&!claimsCacheRedis)logger2.warn("[Authorization] jwtClaimsMode=resolve requires Redis. Falling back to embed mode.");if(logger2.info("[Authorization] Enabled"),isMultiTenant&&tenantRegistry){let tenantSchemas=tenantRegistry.getAllSchemaNames().filter((name2)=>name2!==targetSchemaName);for(let tenantSchemaName of tenantSchemas){let tenantCtx=tenantRegistry.getSchemaContext(tenantSchemaName);if(!tenantCtx)continue;try{if(authConfig.autoSeedClaims){let tenantSchemaEntities=extractSchemaTableEntities(tenantCtx.schemaTables),tenantClaimEntities=mergeEntitiesByName([...tenantSchemaEntities,...SYSTEM_TABLES.map((table)=>normalizeSystemTable(table)),...effectiveConfigEntities(resolvedOptions.entities||[]),...config.systemTables||[],...resolvedOptions.authorization?.externalEntities||[]]);await seedClaims(db,tenantCtx.schemaTables,tenantCtx.schemaRelations,tenantClaimEntities,authConfig,logger2)}if(tenantCtx.tenant?.godAdminEmail&&authConfig.godminPassword)await setupGodmin(db,tenantCtx.schemaTables,{...authConfig,godminEmail:tenantCtx.tenant.godAdminEmail},logger2);if(seedConfig){let{runSeed:runSeed2}=await Promise.resolve().then(() => (init_SeedRunner(),exports_SeedRunner));await runSeed2(db,tenantCtx.schemaTables,seedConfig,logger2)}logger2.info(`[Authorization] Tenant schema seeded: ${tenantSchemaName}`)}catch(err){let msg=err instanceof Error?err.message:String(err);logger2.warn(`[Authorization] Failed to seed tenant ${tenantSchemaName}: ${msg}`)}}logger2.info(`[Authorization] Multi-tenant seeding complete for ${tenantSchemas.length} schemas`)}}let sessionsTableRef=schemaTables.userSessions;if(!isConsumerModeOnStart&&sessionsTableRef&&resolvedOptions.authentication?.sessions?.enabled){let{lt:lt4}=await import("drizzle-orm"),expiredCount=await bootStep("auth.expiredSessionCleanup",()=>db.update(sessionsTableRef).set({isActive:!1,revokedAt:new Date,revokedReason:"expired"}).where(and23(eq63(sessionsTableRef.isActive,!0),lt4(sessionsTableRef.expiresAt,new Date))));if(expiredCount!==void 0)logger2.info("[AUTH] Expired sessions cleanup completed",{expiredCount});let sessionCleanupInterval=setInterval(async()=>{try{await db.update(sessionsTableRef).set({isActive:!1,revokedAt:new Date,revokedReason:"expired"}).where(and23(eq63(sessionsTableRef.isActive,!0),lt4(sessionsTableRef.expiresAt,new Date)));let approvalTtlMs=86400000,approvalCutoff=new Date(Date.now()-approvalTtlMs);await db.update(sessionsTableRef).set({isActive:!1,revokedAt:new Date,revokedReason:"approval_token_expired",approvalStatus:"rejected",approvalToken:null}).where(and23(eq63(sessionsTableRef.approvalStatus,"pending"),lt4(sessionsTableRef.approvalRequestedAt,approvalCutoff)))}catch(err){logger2.warn("[AUTH] Session cleanup failed",{error:err})}},3600000);trackInterval(sessionCleanupInterval)}if(isMultiTenant&&tenantRegistry&&resolvedOptions.authentication?.sessions?.enabled){let{lt:lt4}=await import("drizzle-orm"),tenantSchemaNames=tenantRegistry.getAllSchemaNames().filter((name2)=>name2!==targetSchemaName);for(let tenantSchemaName of tenantSchemaNames){let tenantCtx=tenantRegistry.getSchemaContext(tenantSchemaName);if(!tenantCtx)continue;let tenantSessionsTable=tenantCtx.schemaTables.userSessions||tenantCtx.schemaTables.user_sessions||tenantCtx.schemaTables.sessions;if(!tenantSessionsTable)continue;try{await db.update(tenantSessionsTable).set({isActive:!1,revokedAt:new Date,revokedReason:"expired"}).where(and23(eq63(tenantSessionsTable.isActive,!0),lt4(tenantSessionsTable.expiresAt,new Date))),logger2.info(`[AUTH] Tenant session cleanup completed: ${tenantSchemaName}`)}catch(err){let msg=err instanceof Error?err.message:String(err);logger2.warn(`[AUTH] Tenant session cleanup failed for ${tenantSchemaName}: ${msg}`)}}}}}).onRequest(async({request,set:set2,server})=>{if(request.headers.delete("x-user-id"),request.headers.delete("x-request-id"),request.headers.delete("x-auth-type"),request.headers.delete("x-api-key-id"),request.headers.delete("x-api-key-owner-type"),request.headers.delete("x-user-roles"),request.headers.delete("x-user-claims"),request.headers.delete("x-user-claim-scopes"),request.headers.delete("x-session-id"),request.headers.delete("x-access-token"),request.headers.delete("x-refresh-token"),request.headers.delete("x-tenant-schema"),exceedsBodyLimit(request.headers.get("content-length"),resolvedOptions.security?.maxRequestBodyBytes))return set2.status=413,Response.json({isSuccess:!1,message:"Request body too large",status:413,errors:[{message:"Request body too large"}],data:null});let requestStartTime=Date.now(),requestSchemaTables=schemaTables;if(tenantRegistry){let tenantVettedClientIp=resolveClientIp(server?.requestIP(request)?.address??null,request.headers.get("x-forwarded-for")??request.headers.get("x-real-ip"),resolvedOptions.rateLimit?.trustedProxies??[]),tenantResult=tenantRegistry.resolveFromRequest(request,tenantVettedClientIp);if(tenantResult.resolved)requestSchemaTables=tenantResult.context.schemaTables,request.headers.set("x-tenant-schema",tenantResult.context.schemaName);else if(new URL(request.url).pathname!=="/health")return set2.status=tenantResult.statusCode,Response.json({isSuccess:!1,message:tenantResult.error,status:tenantResult.statusCode,errors:[{message:tenantResult.error}],data:null})}request.headers.set("x-request-start-time",String(requestStartTime));let requestId=randomUUID9();if(request.headers.set("x-request-id",requestId),set2.headers["x-request-id"]=requestId,resolvedOptions.security?.disableDefaultHeaders!==!0){set2.headers["X-Content-Type-Options"]="nosniff",set2.headers["X-Frame-Options"]="SAMEORIGIN",set2.headers["Referrer-Policy"]="strict-origin-when-cross-origin";let hstsMaxAge=resolvedOptions.security?.hstsMaxAge??15552000;if(hstsMaxAge>0)set2.headers["Strict-Transport-Security"]=`max-age=${hstsMaxAge}; includeSubDomains`}let url=new URL(request.url),pathname=url.pathname,method=request.method,query=url.search;if(csrfConfig.enabled){let csrfSecure=request.headers.get("x-forwarded-proto")==="https"||url.protocol==="https:"?"; Secure":"",issueCsrfCookie=()=>`${csrfConfig.cookieName}=${randomUUID9()}; Path=/; SameSite=Lax${csrfSecure}`,csrfCookies=parseCookies(request.headers.get("cookie"));if(requiresCsrf({method,cookies:csrfCookies,hasAuthorizationHeader:!!request.headers.get("authorization"),authCookieNames:csrfAuthCookieNames})&&!csrfTokenMatches(csrfCookies[csrfConfig.cookieName],request.headers.get(csrfConfig.headerName)))return set2.headers["Set-Cookie"]=issueCsrfCookie(),set2.status=403,Response.json({isSuccess:!1,message:"CSRF token missing or invalid",status:403,errors:[{message:"CSRF token missing or invalid"}],data:null});else if(!isStateChanging(method)&&!csrfCookies[csrfConfig.cookieName])set2.headers["Set-Cookie"]=issueCsrfCookie()}let socketIp=server?.requestIP(request)?.address??null,clientIp=resolveClientIp(socketIp,request.headers.get("x-forwarded-for")??request.headers.get("x-real-ip"),resolvedOptions.rateLimit?.trustedProxies??[]);request.headers.set("x-client-ip",clientIp);let userAgent=request.headers.get("user-agent")||"unknown";if(requestLogConfig.enabled&&requestLogConfig.logArrival&&!isRequestLogExcluded(pathname))logger2.log("debug",`\u2192 ${method} ${pathname}`,{requestId,method,path:pathname,query:requestLogConfig.includeQuery&&query?query:void 0,ip:clientIp,tenant:request.headers.get("x-tenant-schema")||void 0},void 0,void 0,"middleware.request");let tokens,parsedBody={};if(request.method!=="GET"&&request.method!=="HEAD")try{let text2=await request.clone().text();parsedBody=text2?JSON.parse(text2):{}}catch{parsedBody={}}let auditPayload=audit?.enabled?{id:randomUUID9(),user_id:"unknown",entity_name:pathname.split("/").filter(Boolean)[0]||"root",entity_id:null,operation_type:method,summary:"",old_values:{},new_values:parsedBody,ip_address:clientIp,user_agent:userAgent,timestamp:new Date().toISOString(),path:pathname,query}:null,isPublic=isPublicRoute(publicRoutes,pathname,method);if(rateLimiter){let routeCategory=isPublic?"public":"private",authType=resolveAuthType(pathname,resolvedOptions.authentication),category=authType?"auth":routeCategory,rateLimitResult=await rateLimiter.check({ip:clientIp,endpoint:pathname,category,authType}),headers=rateLimiter.getHeaders(rateLimitResult);for(let[key2,value2]of Object.entries(headers))set2.headers[key2]=value2;if(!rateLimitResult.allowed){if(set2.status=429,rateLimitResult.retryAfter)set2.headers["Retry-After"]=String(rateLimitResult.retryAfter);if(logger2.warn(`[RateLimit] Blocked request from ${clientIp} to ${pathname}`),monitoringService)monitoringService.recordRateLimitBlock();return new Response(JSON.stringify({error:"Too Many Requests",retryAfter:rateLimitResult.retryAfter}),{status:429,headers:{"Content-Type":"application/json"}})}}if(pathname==="/health")return;if(authentication?.enabled&&!isPublic){let apiKeyRaw=extractApiKeyFromHeader(request.headers),apiKeysTableRef=requestSchemaTables.apiKeys;if(apiKeyRaw&&authentication.apiKeys?.enabled&&apiKeysTableRef&&db){let keyHash=hashApiKey(apiKeyRaw),apiKeyRecord=(await db.select().from(apiKeysTableRef).where(eq63(apiKeysTableRef.keyHash,keyHash)).limit(1))[0];if(!apiKeyRecord)return set2.status=401,logger2.traceSync({message:"Invalid API key",level:"warn",context:{path:pathname,method},audit:toAudit(auditPayload,"Invalid API key")}),Error("Invalid API key");let validation=validateApiKeyRecord(apiKeyRecord);if(!validation.valid)return set2.status=401,logger2.traceSync({message:`API key rejected: ${validation.reason}`,level:"warn",context:{path:pathname,method,keyId:apiKeyRecord.id},audit:toAudit(auditPayload,`API key rejected: ${validation.reason}`)}),Error(validation.reason);let apiKeyUserId=apiKeyRecord.userId,apiKeyUserData;{let ksTable=requestSchemaTables.users;if(ksTable&&db){apiKeyUserData=(await db.select().from(ksTable).where(eq63(ksTable.id,apiKeyUserId)).limit(1))[0];let{evaluateAccountState:evaluateAccountState2}=await Promise.resolve().then(() => exports_accountState),ksState=apiKeyUserData?evaluateAccountState2(apiKeyUserData):{allowed:!1,reason:"inactive",message:"Account is not active"};if(!ksState.allowed)return set2.status=401,logger2.traceSync({message:`API key rejected: account ${ksState.reason}`,level:"warn",context:{path:pathname,method,keyId:apiKeyRecord.id},audit:toAudit(auditPayload,`API key rejected: account ${ksState.reason}`,{userId:apiKeyUserId})}),Error(ksState.message)}}let keyAllowedRoles=apiKeyRecord.allowedRoles||[],keyAllowedClaims=apiKeyRecord.allowedClaims||[],effectiveRoles=keyAllowedRoles,effectiveClaims=keyAllowedClaims,apiKeyClaimScopes={},userRolesTable=requestSchemaTables.userRoles,rolesTable=requestSchemaTables.roles,roleClaimsTable=requestSchemaTables.roleClaims,claimsTable=requestSchemaTables.claims;if(userRolesTable&&rolesTable){let currentUserRoles=(await db.select({name:rolesTable.name}).from(userRolesTable).innerJoin(rolesTable,eq63(rolesTable.id,userRolesTable.roleId)).where(eq63(userRolesTable.userId,apiKeyUserId))).map((r2)=>r2.name).filter((n2)=>n2!==void 0);effectiveRoles=intersectPermissions(currentUserRoles,keyAllowedRoles)}if(userRolesTable&&roleClaimsTable&&claimsTable){let userClaimRows=await db.select({action:claimsTable.action,scope:roleClaimsTable.scope}).from(userRolesTable).innerJoin(roleClaimsTable,eq63(roleClaimsTable.roleId,userRolesTable.roleId)).innerJoin(claimsTable,eq63(claimsTable.id,roleClaimsTable.claimId)).where(eq63(userRolesTable.userId,apiKeyUserId)),currentUserClaims=[...new Set(userClaimRows.map((r2)=>r2.action).filter((a12)=>a12!==void 0))];effectiveClaims=intersectPermissions(currentUserClaims,keyAllowedClaims);let effectiveClaimSet=new Set(effectiveClaims),apiScopedRows=userClaimRows.filter((r2)=>typeof r2.action==="string"&&effectiveClaimSet.has(r2.action)).map((r2)=>({action:r2.action,scope:r2.scope??null}));if(apiScopedRows.some((r2)=>!!r2.scope)){let{claimScopes,dropped}=resolveClaimScopes(apiScopedRows,apiKeyUserData,logger2);if(apiKeyClaimScopes=claimScopes,dropped.length>0){let droppedSet=new Set(dropped);effectiveClaims=effectiveClaims.filter((a12)=>!droppedSet.has(a12))}}}if(db.update(apiKeysTableRef).set({lastUsedAt:new Date,lastUsedIp:clientIp,usageCount:apiKeyRecord.usageCount+1}).where(eq63(apiKeysTableRef.id,apiKeyRecord.id)).catch(()=>{}),effectiveRoles=effectiveRoles.filter((r2)=>r2!==GODMIN_ROLE_NAME),request.headers.set("x-user-id",apiKeyUserId),request.headers.set("x-auth-type","api_key"),request.headers.set("x-api-key-id",apiKeyRecord.id),request.headers.set("x-api-key-owner-type",apiKeyRecord.ownerType||"personal"),effectiveRoles.length>0)request.headers.set("x-user-roles",encodeHeaderList(effectiveRoles));if(effectiveClaims.length>0)request.headers.set("x-user-claims",encodeHeaderList(effectiveClaims));{let apiEncodedScopes=encodeClaimScopesHeader(apiKeyClaimScopes);if(apiEncodedScopes)request.headers.set("x-user-claim-scopes",apiEncodedScopes)}logger2.info("[AUTH] API key authenticated",{userId:apiKeyUserId,keyId:apiKeyRecord.id,ownerType:apiKeyRecord.ownerType,path:pathname,method,effectiveRoles:effectiveRoles.length,effectiveClaims:effectiveClaims.length});return}if(!authentication.accessToken?.secret)return set2.status=500,logger2.traceSync({message:"Authentication secrets not defined",level:"error",context:{path:pathname,method},audit:toAudit(auditPayload,"Authentication secrets not defined")}),Error("One or more authentication secrets are not defined");if(authentication.mode==="consumer"){tokens=parseTokenValuesFromHeaders(request.headers,tokenNames);let jwtResult=verifyJWT(tokens.access_token||"",envResolved.accessTokenSecret||"",{issuer:authentication.accessToken?.issuer,audience:authentication.accessToken?.audience});if(!jwtResult.valid)return set2.status=401,logger2.traceSync({message:"Invalid or missing access token",level:"warn",context:{path:pathname,method},audit:toAudit(auditPayload,"Invalid or missing access token",{userId:decodeUnverifiedSubject(tokens.access_token)})}),Error("Unauthenticated");let consumerBinding=verifyTenantBinding(jwtResult.payload[TENANT_CLAIM],request.headers.get("x-tenant-schema"),resolvedOptions.authentication?.tenantBinding??"lenient");if(!consumerBinding.ok)return set2.status=401,logger2.traceSync({message:"Access token tenant binding failed",level:"warn",context:{path:pathname,method,reason:consumerBinding.reason},audit:toAudit(auditPayload,"Access token tenant binding failed",{userId:decodeUnverifiedSubject(tokens.access_token)})}),Error("Unauthenticated");let userId=jwtResult.payload.sub,roles=jwtResult.payload.roles,claimsFromToken=jwtResult.payload.claims;if(request.headers.set("x-access-token",tokens.access_token||""),request.headers.set("x-user-id",userId||""),roles&&roles.length>0)request.headers.set("x-user-roles",encodeHeaderList(roles));if(claimsFromToken&&claimsFromToken.length>0)request.headers.set("x-user-claims",encodeHeaderList(claimsFromToken));{let encodedScopes=encodeClaimScopesHeader(jwtResult.payload.claimScopes);if(encodedScopes)request.headers.set("x-user-claim-scopes",encodedScopes)}}else{if(!authentication.refreshToken?.secret||!authentication.sessionToken?.secret)return set2.status=500,logger2.traceSync({message:"Authentication secrets not defined",level:"error",context:{path:pathname,method},audit:toAudit(auditPayload,"Authentication secrets not defined")}),Error("One or more authentication secrets are not defined");if(tokens=parseTokenValuesFromHeaders(request.headers,tokenNames),!tokens.session_token)return set2.status=401,logger2.traceSync({message:"No session token",level:"debug",context:{path:pathname,method},audit:toAudit(auditPayload,"No session token")}),Error("Unauthenticated");let sessionData=await readSession({sessionId:tokens.session_token});if(!sessionData)return set2.status=401,logger2.traceSync({message:"Invalid session",level:"debug",context:{path:pathname,method,sessionId:tokens.session_token},audit:toAudit(auditPayload,"Invalid session")}),Error("Unauthenticated");let sessionsTableCheck=requestSchemaTables.userSessions;if(sessionsTableCheck&&db){let session=(await db.select().from(sessionsTableCheck).where(eq63(sessionsTableCheck.id,tokens.session_token)).limit(1))[0],revokedAtVal=session?.revokedAt,isRevoked=revokedAtVal!=null&&!(typeof revokedAtVal==="object"&&!(revokedAtVal instanceof Date)&&Object.keys(revokedAtVal).length===0);if(!session||session.isActive===!1||isRevoked)return set2.status=401,logger2.traceSync({message:"Session revoked or inactive",level:"warn",context:{path:pathname,method,sessionId:tokens.session_token,isActive:session?.isActive,revokedAt:session?.revokedAt},audit:toAudit(auditPayload,"Session revoked",{userId:sessionData.userId??null})}),Error("Session has been revoked");if(session.expiresAt&&new Date(session.expiresAt)<new Date)return set2.status=401,logger2.traceSync({message:"Session expired",level:"debug",context:{path:pathname,method,sessionId:tokens.session_token,expiresAt:session.expiresAt},audit:toAudit(auditPayload,"Session expired",{userId:sessionData.userId??null})}),Error("Session has expired")}if(isIdleExpired({lastActiveAt:sessionData.lastActiveAt,inactivityTimeout:authentication.sessions?.inactivityTimeout}))return set2.status=401,logger2.traceSync({message:"Session inactive timeout",level:"debug",context:{path:pathname,method,sessionId:tokens.session_token,lastActiveAt:sessionData.lastActiveAt},audit:toAudit(auditPayload,"Session inactive timeout",{userId:sessionData.userId??null})}),Error("Session expired due to inactivity");updateLastActiveAt(tokens.session_token).catch(()=>{});let sessionsTableRef=requestSchemaTables.userSessions;if(sessionsTableRef&&db)db.update(sessionsTableRef).set({lastActivityAt:new Date}).where(eq63(sessionsTableRef.id,tokens.session_token)).catch(()=>{});let jwtResult=verifyJWT(tokens.access_token||"",envResolved.accessTokenSecret||"",{issuer:authentication.accessToken?.issuer,audience:authentication.accessToken?.audience}),isAccessTokenValid=tokens.access_token?jwtResult.valid:!1,isRefreshTokenValid=tokens.refresh_token?verifyJWT(tokens.refresh_token,envResolved.refreshTokenSecret||"",{issuer:authentication.refreshToken?.issuer,audience:authentication.refreshToken?.audience}).valid:!1;if(!isAccessTokenValid&&isRefreshTokenValid&&tokens.refresh_token&&sessionData.rememberMe===!0){let killSwitchUsersTable=requestSchemaTables.users;if(db&&killSwitchUsersTable){let ksUser=(await db.select().from(killSwitchUsersTable).where(eq63(killSwitchUsersTable.id,sessionData.userId)).limit(1))[0],{evaluateAccountState:evaluateAccountState2}=await Promise.resolve().then(() => exports_accountState),ksState=ksUser?evaluateAccountState2(ksUser):{allowed:!1,reason:"inactive",message:"Account is not active"};if(!ksState.allowed)return set2.status=401,logger2.traceSync({message:`Silent refresh blocked - account ${ksState.reason}`,level:"warn",context:{path:pathname,method},audit:toAudit(auditPayload,`Silent refresh blocked - account ${ksState.reason}`,{userId:sessionData.userId??null})}),Error(ksState.message)}let refreshRoles=[],refreshClaims=[],refreshClaimScopes={},refreshUserRolesTable=requestSchemaTables.userRoles,refreshRolesTable=requestSchemaTables.roles,refreshRoleClaimsTable=requestSchemaTables.roleClaims,refreshClaimsTable=requestSchemaTables.claims;if(db&&refreshUserRolesTable&&refreshRolesTable)try{let{fetchUserRolesAndClaims:fetchUserRolesAndClaims2}=await Promise.resolve().then(() => (init_fetchUserRolesAndClaims(),exports_fetchUserRolesAndClaims)),rc=await fetchUserRolesAndClaims2(db,sessionData.userId,{usersTable:killSwitchUsersTable??null,sessionsTable:null,userRolesTable:refreshUserRolesTable,rolesTable:refreshRolesTable,roleClaimsTable:refreshRoleClaimsTable,claimsTable:refreshClaimsTable,oauthAccountsTable:void 0,apiKeysTable:void 0,schemaTables:requestSchemaTables});refreshRoles=rc.roles,refreshClaims=rc.claims,refreshClaimScopes=rc.claimScopes}catch{}let refreshResult=await refreshAccessTokenWithLock(sessionData.userId,sessionData.id,()=>signNewAccessToken({refreshTokenId:tokens.refresh_token,options:resolvedOptions,sessionData,roles:refreshRoles.length>0?refreshRoles:void 0,claims:refreshClaims.length>0?refreshClaims:void 0,claimScopes:refreshClaimScopes,tenant:request.headers.get("x-tenant-schema")??void 0,resolveMode:resolvedOptions.authorization?.jwtClaimsMode==="resolve"&&!!claimsCache}));if(refreshResult.success&&refreshResult.accessToken){tokens.access_token=refreshResult.accessToken;let rawDomain=authentication.cookieDomain,resolvedDomainRaw=rawDomain?process.env[rawDomain]??rawDomain:void 0,resolvedDomain=resolvedDomainRaw==="localhost"||resolvedDomainRaw===".localhost"?void 0:resolvedDomainRaw,domainPart=resolvedDomain?`; Domain=${resolvedDomain}`:"",bufferSeconds=authentication.cookieMaxAgeBufferSeconds??0,maxAge=Math.max(0,parseTimeToSeconds2(authentication.accessToken.expiresIn??"15m")-bufferSeconds),securePart=!resolvedDomain?"":"; Secure",cookieValue=`${tokenNames.access_token}=${refreshResult.accessToken}; Path=/; HttpOnly; SameSite=Lax${securePart}; Max-Age=${maxAge}${domainPart}`;set2.headers["Set-Cookie"]=cookieValue}}if(jwtResult.valid){let fullBinding=verifyTenantBinding(jwtResult.payload[TENANT_CLAIM],request.headers.get("x-tenant-schema"),resolvedOptions.authentication?.tenantBinding??"lenient");if(!fullBinding.ok)return set2.status=401,logger2.traceSync({message:"Access token tenant binding failed",level:"warn",context:{path:pathname,method,reason:fullBinding.reason},audit:toAudit(auditPayload,"Access token tenant binding failed",{userId:jwtResult.payload.sub??null})}),Error("Unauthenticated")}if(jwtResult.valid&&jwtResult.payload.sub&&String(jwtResult.payload.sub)!==String(sessionData.userId))return set2.status=401,logger2.traceSync({message:"Access token subject does not match session",level:"warn",context:{path:pathname,method,sessionUserId:sessionData.userId,tokenSub:jwtResult.payload.sub},audit:toAudit(auditPayload,"Access token/session subject mismatch",{userId:sessionData.userId??null})}),Error("Unauthenticated");let userId=jwtResult.valid?jwtResult.payload.sub:sessionData.userId,roles=jwtResult.valid?jwtResult.payload.roles:void 0,claimsFromToken=jwtResult.valid?jwtResult.payload.claims:void 0;if(!claimsFromToken?.length&&claimsCache&&roles&&roles.length>0)try{let resolvedClaims=await claimsCache.resolveClaimsForRoles(roles);if(resolvedClaims.length>0)claimsFromToken=resolvedClaims}catch{}if(userId&&db&&authentication.cohorts?.enabled){let mwUsersTable=requestSchemaTables.users;if(mwUsersTable)try{let mwCohortId=(await db.select().from(mwUsersTable).where(eq63(mwUsersTable.id,userId)).limit(1))[0]?.cohortId;if(mwCohortId){let mwCohortsTable=requestSchemaTables.userCohorts??requestSchemaTables.user_cohorts;if(mwCohortsTable){let mwExpiresAt=(await db.select().from(mwCohortsTable).where(eq63(mwCohortsTable.id,mwCohortId)).limit(1))[0]?.expiresAt;if(mwExpiresAt&&new Date(mwExpiresAt)<new Date)return set2.status=403,logger2.traceSync({message:"Cohort expired - access denied",level:"warn",context:{path:pathname,method,userId,cohortId:mwCohortId},audit:toAudit(auditPayload,"Cohort expired",{userId:userId??null})}),Error("Your access has expired. Please contact your administrator.")}}}catch{}}if(request.headers.set("x-access-token",tokens.access_token||""),request.headers.set("x-refresh-token",tokens.refresh_token||""),request.headers.set("x-session-id",tokens.session_token||""),request.headers.set("x-user-id",userId||""),roles&&roles.length>0)request.headers.set("x-user-roles",encodeHeaderList(roles));if(claimsFromToken&&claimsFromToken.length>0)request.headers.set("x-user-claims",encodeHeaderList(claimsFromToken));{let encodedScopes=encodeClaimScopesHeader(jwtResult.valid?jwtResult.payload.claimScopes:void 0);if(encodedScopes)request.headers.set("x-user-claim-scopes",encodedScopes)}}}}).onAfterHandle(({request,set:set2})=>{let afterUrl=new URL(request.url),afterStatus=typeof set2.status==="number"?set2.status:200,afterStartStr=request.headers.get("x-request-start-time"),afterDuration=afterStartStr?Date.now()-parseInt(afterStartStr,10):0;if(requestLogConfig.enabled&&!isRequestLogExcluded(afterUrl.pathname)){let isSlow=afterDuration>=requestLogConfig.slowThresholdMs,level=afterStatus>=500?"error":afterStatus>=400||isSlow?"warn":"info";logger2.log(level,`\u2190 ${request.method} ${afterUrl.pathname} ${afterStatus} (${afterDuration}ms)`,{requestId:request.headers.get("x-request-id")||void 0,method:request.method,path:afterUrl.pathname,query:requestLogConfig.includeQuery&&afterUrl.search?afterUrl.search:void 0,statusCode:afterStatus,durationMs:afterDuration,slow:isSlow||void 0,userId:request.headers.get("x-user-id")||void 0,authType:request.headers.get("x-auth-type")||void 0,tenant:request.headers.get("x-tenant-schema")||void 0,ip:request.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||request.headers.get("x-real-ip")||void 0},void 0,void 0,"middleware.request")}if(monitoringService){let startTimeStr=request.headers.get("x-request-start-time"),startTime=startTimeStr?parseInt(startTimeStr,10):Date.now(),responseTimeMs=Date.now()-startTime,url=new URL(request.url),status=typeof set2.status==="number"?set2.status:200;monitoringService.recordRequest({endpoint:url.pathname,method:request.method,status,responseTimeMs,isError:status>=500,errorType:status>=500?"server_error":status>=400?"client_error":void 0})}if(liveMonitoringService){let url=new URL(request.url),headersObj=redactSensitiveHeaders(request.headers);liveMonitoringService.recordRequest({path:url.pathname,method:request.method,timestamp:Date.now(),headers:headersObj})}}).onError((ctx)=>{let{set:set2,code,error:error3,request}=ctx,status=statusOfError(code,error3),message="Internal Server Error",pgCode,clientSafe=!1;if(error3 instanceof Error){let cause=error3.cause;if(pgCode=cause?.code,pgCode==="23505")message="A record with this value already exists",clientSafe=!0;else if(pgCode==="23503")message="Referenced record does not exist",clientSafe=!0;else if(pgCode==="23502")message=`Missing required field: ${cause?.column||"a required field is empty"}`,clientSafe=!0;else if(pgCode==="22P02")message=cause?.routine==="string_to_uuid"?"Invalid ID format":"Invalid data format",clientSafe=!0;else if(pgCode)message=`Database error (${pgCode}): ${cause?.detail||cause?.message||error3.message}`;else if(code==="VALIDATION")message=describeValidationError(error3)??error3.message,clientSafe=!0;else message=error3.message,clientSafe=status<500}try{let errUrl=new URL(request.url),errStartStr=request.headers.get("x-request-start-time");logger2.log(status>=500?"error":"warn",`\u2716 ${request.method} ${errUrl.pathname} ${status}: ${message}`,{requestId:request.headers.get("x-request-id")||void 0,method:request.method,path:errUrl.pathname,statusCode:status,elysiaCode:typeof code==="string"?code:void 0,pgCode,durationMs:errStartStr?Date.now()-parseInt(errStartStr,10):void 0,userId:request.headers.get("x-user-id")||void 0,tenant:request.headers.get("x-tenant-schema")||void 0},status>=500?error3:void 0)}catch(logErr){logger2.error("Failed to log request error",logErr)}set2.status=status;let clientMessage=clientSafe?message:"Internal Server Error";return Response.json({isSuccess:!1,message:clientMessage,status,errors:[{message:clientMessage}],data:null})});let featureAdminRoles={};for(let[feature,section]of Object.entries(resolvedOptions)){if(!section||typeof section!=="object")continue;let roles=section.adminRoles;if(!Array.isArray(roles))continue;let named=roles.filter((role)=>typeof role==="string"&&role.length>0);if(named.length>0)featureAdminRoles[feature]=named}logger2.info("Creating routes for entities"),createEntityRoutes(plugin,{db,schemaTables,schemaRelations,entities,logger:logger2,databaseUrl:envResolved.databaseUrl,dbPool,storage:resolvedOptions.storage,cdnMedia:{transform:mergeTransformConfig(resolvedOptions.storage?.cdn?.transform),video:mergeVideoConfig(resolvedOptions.storage?.cdn?.video),pdf:mergePdfConfig(resolvedOptions.storage?.cdn?.pdf)},authorization:resolvedOptions.authorization,featureAdminRoles,accountLinks:authentication?.accountLinks,authMode:authentication?.mode,idpUrl:authentication?.idpUrl?process.env[authentication.idpUrl]||authentication.idpUrl:void 0,isEmailServiceAvailable:()=>!!getEmailService()?.isAvailable(),onRoleChanged:({userId:subjectId,roleName,assigned})=>{if(!db)return;let service=new NotificationService({db,schemaTables,config:resolvedOptions.notification??{},logger:logger2,getEmailService}),title=assigned?`Yeni yetki: ${roleName}`:`Yetki kald\u0131r\u0131ld\u0131: ${roleName}`,body=assigned?`Portalda "${roleName}" yetkisi hesab\u0131n\u0131za tan\u0131mland\u0131. Yeni b\xF6l\xFCmler men\xFCn\xFCzde g\xF6r\xFCnecek.`:`Portalda "${roleName}" yetkiniz kald\u0131r\u0131ld\u0131. Bu yetkiye ba\u011Fl\u0131 b\xF6l\xFCmler art\u0131k g\xF6r\xFCnmeyecek.`;service.send({user_id:subjectId,title,body,type:"system",source:"authorization",channels:["portal","email"]}).catch(()=>{})},tenantRegistry,getTenantRegistry:()=>tenantRegistry,claimsCache});let isConsumerMode=authentication?.mode==="consumer";if(isMultiTenant&&!isConsumerMode)createTenantRoutes(plugin,{getDb:()=>db,logger:logger2,getTenantRegistry:()=>tenantRegistry,schemaName:targetSchemaName}),logger2.info("[MultiTenant] Tenant routes pre-registered (handlers check runtime readiness)");else if(isMultiTenant&&isConsumerMode)plugin.post("/tenants/refresh",async(ctx)=>{if(!tenantRegistry||!tenantRegistry.isConsumerMode())return ctx.set.status=503,{success:!1,message:"Tenant registry not ready"};try{return{success:!0,data:await tenantRegistry.syncFromIdp()}}catch(err){let msg=err instanceof Error?err.message:String(err);return ctx.set.status=500,{success:!1,message:`Tenant sync failed: ${msg}`}}}),logger2.info("[MultiTenant] Consumer tenant refresh route registered (/tenants/refresh)");let domainServices=null;if(resolvedOptions.domains?.enabled){if(domainServices=createDomainServices({options:resolvedOptions,logger:logger2,getDb:()=>db,getTenantRegistry:()=>tenantRegistry}),domainServices)createDomainRoutes(plugin,{getDomainService:()=>domainServices?.domainService??null,getRegistrationService:()=>domainServices?.registrationService??null,logger:logger2,basePath:resolvedOptions.domains.basePath||"/domains",resolveTenantIdForSchema:(schema3)=>schema3&&tenantRegistry?tenantRegistry.getTenantBySchemaName(schema3)?.id??null:null}),logger2.info("[Domains] Custom domain routes registered",{provider:domainServices.domainService.config.provider,basePath:resolvedOptions.domains.basePath||"/domains"})}if(authentication?.enabled&&!isConsumerMode&&db){let resolveTableForTenant=(tableName,reqSchemaName)=>{if(reqSchemaName&&tenantRegistry){let ctx=tenantRegistry.getSchemaContext(reqSchemaName);if(ctx?.schemaTables[tableName])return ctx.schemaTables[tableName]}return schemaTables[tableName]},usersTable=schemaTables.users,sessionsTable=schemaTables.userSessions||schemaTables.user_sessions||schemaTables.sessions;if(!sessionsTable&&authentication.sessions?.enabled)logger2.warn("[AUTH] sessions is enabled but user_sessions table not found in schema. Disabling sessions.");if(usersTable){await initiateRedisManager(resolvedOptions);let{createAuthRoutes:createAuthRoutes2}=(init_auth(),__toCommonJS(exports_auth)),{signJWT:signJWT2,verifyJWT:verifyJWT3}=(init_JWT(),__toCommonJS(exports_JWT)),{generateSession:generateSession2,deleteSession:deleteSession2}=(init_SessionStore(),__toCommonJS(exports_SessionStore));createAuthRoutes2(plugin,{authConfig:{db,logger:logger2,usersTable,sessionsTable,userRolesTable:schemaTables.userRoles,rolesTable:schemaTables.roles,roleClaimsTable:schemaTables.roleClaims,claimsTable:schemaTables.claims,authentication:{enabled:authentication.enabled,get defaultRole(){return resolvedOptions.authentication?.defaultRole||process.env.AUTH_DEFAULT_ROLE},get defaultRoles(){return resolvedOptions.authentication?.defaultRoles},cookieDomain:resolvedOptions.authentication?.cookieDomain,get trustedAppOrigins(){return trustedAppOrigins()},emailExemptDomains:authentication?.emailExemptDomains,accessToken:authentication.accessToken,refreshToken:authentication.refreshToken,sessionToken:authentication.sessionToken,deviceTrust:authentication.sessions?.deviceTrust}},features:{login:authentication.login,register:authentication.register,logout:authentication.logout,refresh:authentication.refresh,passwordReset:withResolvedRedirects(authentication.passwordReset,["redirectUrl"]),passwordChange:authentication.passwordChange,passwordSet:authentication.passwordSet,sessions:withResolvedRedirects(authentication.sessions,["approvalRedirectUrl"]),magicLink:withResolvedRedirects(authentication.magicLink,["redirectUrl"]),me:authentication.me||{enabled:!0,route:"/auth/me"},invite:withResolvedRedirects(authentication.invite,["redirectUrl"]),captcha:authentication.captcha,oauth:authentication.oauth?.enabled&&envResolved.oauthProviders?{...withResolvedRedirects(authentication.oauth,["successRedirectUrl","errorRedirectUrl"]),providers:liveOAuthProviders(envResolved.oauthProviders)}:void 0,apiKeys:authentication.apiKeys?.enabled?{enabled:!0,route:authentication.apiKeys.route,keyPrefix:authentication.apiKeys.keyPrefix,maxKeysPerUser:authentication.apiKeys.maxKeysPerUser,defaultExpiresIn:authentication.apiKeys.defaultExpiresIn,allowApplicationKeys:authentication.apiKeys.allowApplicationKeys,preventApiKeyManagement:authentication.apiKeys.preventApiKeyManagement}:void 0,webauthn:authentication.webauthn},sessionsTable,oauthAccountsTable:schemaTables.oauthAccounts,oauthStateStore:(()=>{let oauthRedis=getRedisManager();if(!oauthRedis)return;let{createRedisOAuthStateStore:createRedisOAuthStateStore2}=__toCommonJS(exports_stateStore);return createRedisOAuthStateStore2(oauthRedis)})(),apiKeysTable:schemaTables.apiKeys,schemaTables,schemaRelations,tenantRegistry,getTenantRegistry:()=>tenantRegistry,databaseUrl:envResolved.databaseUrl,dbPool,admin:(()=>{let adminCfg=resolvedOptions.authentication?.admin;return{impersonate:{enabled:!0},changeUserId:{enabled:!0},createUser:adminCfg?.createUser??{enabled:!0},passwordTools:adminCfg?.passwordTools??{enabled:!1}}})(),schemaName:targetSchemaName,getEmailService,appName:resolvedOptions.appId,webauthnService:(()=>{if(!authentication.webauthn?.enabled||!db)return null;let{WebAuthnService:WebAuthnService2}=(init_WebAuthn(),__toCommonJS(exports_WebAuthn)),{createDbWebAuthnStorage:createDbWebAuthnStorage2}=(init_dbStorage(),__toCommonJS(exports_dbStorage)),rpName=authentication.webauthn.rpName||resolvedOptions.appId||"Nucleus",rpID=authentication.webauthn.rpID||"localhost",expectedOrigins=authentication.webauthn.expectedOrigins||[`http://${rpID}`,`https://${rpID}`],challengeTtlMs=authentication.webauthn.challengeTtl?parseTimeToSeconds2(authentication.webauthn.challengeTtl)*1000:300000,storage=createDbWebAuthnStorage2({db,resolveTable:resolveTableForTenant});return new WebAuthnService2({rp:{rpName,rpID,expectedOrigins},challengeTtlMs,storage,userVerification:authentication.webauthn?.userVerification})})(),captchaService:(()=>{let redisManager=getRedisManager();if(!authentication.captcha?.enabled||!redisManager)return null;return new CaptchaService({redis:{get:async(key2)=>{let result=await redisManager.read(key2);return result.success?result.data:null},set:async(key2,value2,options)=>{await redisManager.create(key2,value2,options?.ex)},del:async(key2)=>{await redisManager.remove(key2)},incrementCounter:(key2,delta,ttlSeconds)=>redisManager.incrementCounter(key2,delta,ttlSeconds)},logger:logger2,config:{enabled:!0,type:authentication.captcha.type||"math",difficulty:authentication.captcha.difficulty||"medium",expiresIn:authentication.captcha.expiresIn||"5m",maxAttempts:authentication.captcha.maxAttempts||3,caseSensitive:authentication.captcha.caseSensitive??!1}})})(),tokenResponseConfig:{accessToken:{setHeadersEnabled:authentication.accessToken?.setHeadersEnabled??!0,returnJson:authentication.accessToken?.returnJson??!0},refreshToken:{setHeadersEnabled:authentication.refreshToken?.setHeadersEnabled??!0,returnJson:authentication.refreshToken?.returnJson??!0},sessionToken:{setHeadersEnabled:authentication.sessionToken?.setHeadersEnabled??!0,returnJson:authentication.sessionToken?.returnJson??!0}},helpers:{signAccessToken:(userId,roles,claims,tenant,claimScopes)=>{let resolveMode=resolvedOptions.authorization?.jwtClaimsMode==="resolve"&&claimsCache,hasClaimScopes=!resolveMode&&!!claimScopes&&Object.keys(claimScopes).length>0,token=signJWT2({subject:userId,expiresInSeconds:parseTimeToSeconds2(authentication.accessToken?.expiresIn||"15m"),issuer:authentication.accessToken?.issuer,audience:authentication.accessToken?.audience,customClaims:{...roles&&roles.length>0?{roles}:{},...!resolveMode&&claims&&claims.length>0?{claims}:{},...hasClaimScopes?{claimScopes}:{},...tenant?{tenant}:{}}},envResolved.accessTokenSecret||"",authentication.accessToken?.algorithm||"HS256");return warnIfAccessTokenTooLargeForCookie(token,resolveMode?"resolve":resolvedOptions.authorization?.jwtClaimsMode),token},signRefreshToken:(userId,rememberMe)=>signJWT2({subject:userId,expiresInSeconds:longerLifetime(rememberMe?authentication.rememberMe?.expiresIn:void 0,authentication.refreshToken?.expiresIn,604800),issuer:authentication.refreshToken?.issuer,audience:authentication.refreshToken?.audience},envResolved.refreshTokenSecret||"",authentication.refreshToken?.algorithm||"HS256"),verifyRefreshToken:(token)=>verifyJWT3(token,envResolved.refreshTokenSecret||"",{issuer:authentication.refreshToken?.issuer,audience:authentication.refreshToken?.audience}),createSession:async(params)=>{let sessionTtlSeconds=longerLifetime(params.rememberMe?authentication.rememberMe?.expiresIn:void 0,authentication.sessionToken?.expiresIn,2592000),result=await generateSession2({userId:params.userId,deviceInfo:params.deviceInfo,rememberMe:params.rememberMe,loginMethod:params.loginMethod,expiresInSeconds:sessionTtlSeconds});if(!result.success)throw logger2.error("[createSession] failed to create session",{userId:params.userId,error:result.error}),Error(`Session storage unavailable: ${result.error||"unknown error"}`);return result.session.id},destroySession:async(sessionId)=>deleteSession2({sessionId}),saveSessionToDb:async(sessionId,params,reqSchemaName)=>{let resolvedSessionsTable=resolveTableForTenant("userSessions",reqSchemaName)||resolveTableForTenant("user_sessions",reqSchemaName)||resolveTableForTenant("sessions",reqSchemaName)||sessionsTable;if(!resolvedSessionsTable||!db)return;let sessionsConfig=authentication.sessions,deviceInfo=ensureDeviceInfo(params.deviceInfo||{ipAddress:""}),resolvedUsersTableForExempt=resolveTableForTenant("users",reqSchemaName),sessionUserEmail=null;if(resolvedUsersTableForExempt)sessionUserEmail=(await db.select().from(resolvedUsersTableForExempt).where(eq63(resolvedUsersTableForExempt.id,params.userId)).limit(1))[0]?.email??null;let userIsEmailExempt=sessionUserEmail?isEmailExempt(sessionUserEmail,authentication?.emailExemptDomains):!1,deviceFingerprint=deviceInfo.deviceHint?`${deviceInfo.browserName||""}-${deviceInfo.osName||""}-${deviceInfo.deviceType||""}-${deviceInfo.deviceHint}`:`${deviceInfo.browserName||""}-${deviceInfo.osName||""}-${deviceInfo.deviceType||""}`,existingSessions=await db.select().from(resolvedSessionsTable).where(and23(eq63(resolvedSessionsTable.userId,params.userId),eq63(resolvedSessionsTable.isActive,!0))),hasValidFingerprint=deviceFingerprint&&!deviceFingerprint.includes("--unknown")&&!deviceFingerprint.includes("Bot/Crawler")&&!deviceFingerprint.includes("Headless")&&deviceFingerprint!=="--"&&deviceFingerprint!=="--unknown",allUserSessions=await db.select().from(resolvedSessionsTable).where(eq63(resolvedSessionsTable.userId,params.userId)),isNewDevice=hasValidFingerprint?!existingSessions.some((s)=>s.deviceFingerprint===deviceFingerprint):!1,wasPreviouslyApproved=hasValidFingerprint?allUserSessions.some((s)=>{let sess=s;return sess.deviceFingerprint===deviceFingerprint&&sess.approvalStatus==="approved"}):!1,hasAnyApprovedSession=existingSessions.some((s)=>s.approvalStatus==="approved"),isImpersonationLogin=params.loginMethod==="impersonation"||params.loginMethod==="impersonation_stop",isOAuthLogin=params.loginMethod?.startsWith("oauth:"),requiresApproval=!isImpersonationLogin&&!userIsEmailExempt&&sessionsConfig?.trustNewDevices===!1&&isNewDevice&&!wasPreviouslyApproved&&hasValidFingerprint&&hasAnyApprovedSession,deviceTrustCfg=sessionsConfig?.deviceTrust,dtTable=deviceTrustCfg?.enabled?resolveTableForTenant("trustedDevices",reqSchemaName)||resolveTableForTenant("trusted_devices",reqSchemaName):void 0,deviceTrustMint=null,deviceTokenToSet=null;if(deviceTrustCfg?.enabled&&dtTable){let DT=await Promise.resolve().then(() => (init_DeviceTrust(),exports_DeviceTrust)),DTStore=await Promise.resolve().then(() => (init_store2(),exports_store)),dtNow=new Date,dtRows=params.deviceToken?await DTStore.findDeviceRowsByRawToken(db,dtTable,params.deviceToken):[],knownRow=DT.selectUsableDeviceRow(dtRows,params.userId,dtNow),pendingRow=dtRows.find((r2)=>(r2.userId??r2.user_id)===params.userId&&r2.status==="pending"),isFirstEver=allUserSessions.length===0&&await DTStore.userHasNoTrustedDevices(db,dtTable,params.userId),decision=DT.decideDeviceApproval({knownDevice:!!knownRow,trustNewDevices:sessionsConfig?.trustNewDevices??!0,hasValidFingerprint:!!hasValidFingerprint,isFirstEverDevice:isFirstEver,loginMethod:params.loginMethod,approvalMethods:deviceTrustCfg.approvalMethods??["password","magic_link","sso","webauthn","oauth:*","register"],onUnidentifiable:deviceTrustCfg.onUnidentifiable??"require_approval",isImpersonation:isImpersonationLogin,isEmailExempt:userIsEmailExempt});if(knownRow)await DTStore.touchDevice(db,dtTable,knownRow.id,deviceInfo.ipAddress).catch(()=>{});if(decision.deny)return logger2.warn("[AUTH] Device-trust denied unidentifiable device",{userId:params.userId}),{requiresApproval:!1,denied:!0};let reuseSessionId=pendingRow?.originSessionId??pendingRow?.origin_session_id;if(decision.requiresApproval&&reuseSessionId)return{requiresApproval:!0,sessionId:reuseSessionId};requiresApproval=decision.requiresApproval,deviceTrustMint=decision.mintToken?decision.trustImmediately?"trusted":"pending":null}logger2.info("[AUTH] Device fingerprint analysis",{userId:params.userId,deviceFingerprint,hasValidFingerprint,isNewDevice,wasPreviouslyApproved,loginMethod:params.loginMethod,isImpersonationLogin,isOAuthLogin,existingSessionCount:existingSessions.length,hasAnyApprovedSession,requiresApproval});let approvalToken=null,approvalStatus="approved";if(requiresApproval){let existingPending=deviceTrustCfg?.enabled?void 0:allUserSessions.find((s)=>{let sess=s;return sess.deviceFingerprint===deviceFingerprint&&(sess.approvalStatus==="pending"||sess.approval_status==="pending")&&sess.approvalToken});if(existingPending){let pendingSess=existingPending,pendingRequestedAt=pendingSess.approvalRequestedAt||pendingSess.approval_requested_at;if(pendingRequestedAt?Date.now()-new Date(pendingRequestedAt).getTime()<86400000:!0)return logger2.info("[AUTH] Reusing existing pending session for same device",{userId:params.userId,deviceFingerprint,existingSessionId:pendingSess.id}),{requiresApproval:!0,sessionId:pendingSess.id}}let{randomBytes:randomBytes8}=await import("crypto");approvalToken=randomBytes8(32).toString("hex"),approvalStatus="pending",logger2.info("[AUTH] New device requires approval",{userId:params.userId,deviceFingerprint,ipAddress:deviceInfo.ipAddress})}let staleBotSessions=existingSessions.filter((s)=>{let sess=s,fp=(sess.deviceFingerprint||"").toLowerCase(),ip=sess.ipAddress||"",ua=(sess.userAgent||"").toLowerCase(),isBotFingerprint=!fp||fp==="--"||fp==="--unknown"||fp.includes("bot/crawler")||fp.includes("headless")||fp.includes("unknown-unknown"),isServerAction=ua.includes("nucleusserveraction")||ua.includes("serveraction")||ua.includes("node-fetch")||ua.includes("undici");return isBotFingerprint&&(ip==="127.0.0.1"||ip==="::1"||ip==="localhost"||!ip)||isServerAction});if(staleBotSessions.length>0){for(let botSession of staleBotSessions)await db.update(resolvedSessionsTable).set({isActive:!1,revokedAt:new Date,revokedReason:"bot_session_cleanup"}).where(eq63(resolvedSessionsTable.id,botSession.id));logger2.info("[AUTH] Cleaned up stale bot/crawler sessions",{userId:params.userId,cleanedCount:staleBotSessions.length})}if(hasValidFingerprint&&!requiresApproval){let sameDeviceOldSessions=existingSessions.filter((s)=>s.deviceFingerprint===deviceFingerprint);for(let oldSession of sameDeviceOldSessions)await db.update(resolvedSessionsTable).set({isActive:!1,revokedAt:new Date,revokedReason:"same_device_relogin"}).where(eq63(resolvedSessionsTable.id,oldSession.id));if(sameDeviceOldSessions.length>0)logger2.info("[AUTH] Revoked old same-device sessions",{userId:params.userId,deviceFingerprint,revokedCount:sameDeviceOldSessions.length})}if(!sessionsConfig?.allowMultipleDevices&&existingSessions.length>0){if((hasValidFingerprint?existingSessions.filter((s)=>s.deviceFingerprint===deviceFingerprint):[]).length===0)for(let oldSession of existingSessions)await db.update(resolvedSessionsTable).set({isActive:!1,revokedAt:new Date,revokedReason:"new_device_login"}).where(eq63(resolvedSessionsTable.id,oldSession.id))}if(sessionsConfig?.maxActiveSessions){let{count:count3}=await import("drizzle-orm"),currentCount=(await db.select({count:count3()}).from(resolvedSessionsTable).where(and23(eq63(resolvedSessionsTable.userId,params.userId),eq63(resolvedSessionsTable.isActive,!0))))[0]?.count||0;if(currentCount>=sessionsConfig.maxActiveSessions){let{asc:asc2}=await import("drizzle-orm"),oldestSessions=await db.select().from(resolvedSessionsTable).where(and23(eq63(resolvedSessionsTable.userId,params.userId),eq63(resolvedSessionsTable.isActive,!0))).orderBy(asc2(resolvedSessionsTable.createdAt)).limit(currentCount-sessionsConfig.maxActiveSessions+1);for(let oldSession of oldestSessions)await db.update(resolvedSessionsTable).set({isActive:!1,revokedAt:new Date,revokedReason:"max_sessions_exceeded"}).where(eq63(resolvedSessionsTable.id,oldSession.id))}}let trustScore=100;if(deviceInfo.isHeadless)trustScore-=50;if(deviceInfo.isBot)trustScore-=40;if(deviceInfo.isSuspicious)logger2.warn("[AUTH] Suspicious login detected",{userId:params.userId,suspiciousPatterns:deviceInfo.suspiciousPatterns,userAgent:deviceInfo.userAgent,ipAddress:deviceInfo.ipAddress});if(isNewDevice)trustScore-=25;if(!deviceInfo.ipAddress||deviceInfo.ipAddress==="unknown")trustScore-=20;if(!deviceInfo.browserName)trustScore-=15;if(!deviceInfo.osName)trustScore-=15;if(!deviceInfo.deviceType||deviceInfo.deviceType==="unknown")trustScore-=10;if(!deviceInfo.deviceName||deviceInfo.deviceName==="Unknown Device")trustScore-=5;let validFingerprint=deviceFingerprint&&!deviceFingerprint.includes("--unknown")&&deviceFingerprint!=="--",validIp=deviceInfo.ipAddress&&deviceInfo.ipAddress!=="unknown";if(validFingerprint){if(existingSessions.filter((s)=>s.deviceFingerprint===deviceFingerprint).length>0)trustScore+=20}if(validIp){if(existingSessions.filter((s)=>s.ipAddress===deviceInfo.ipAddress).length>0)trustScore+=15}trustScore=Math.max(0,Math.min(100,trustScore));let LOW_TRUST_THRESHOLD=50;if(await db.insert(resolvedSessionsTable).values({id:sessionId,userId:params.userId,tokenHash:sessionId,deviceFingerprint,deviceName:deviceInfo.deviceName,deviceType:deviceInfo.deviceType,browserName:deviceInfo.browserName,browserVersion:deviceInfo.browserVersion,osName:deviceInfo.osName,osVersion:deviceInfo.osVersion,ipAddress:deviceInfo.ipAddress,locationCountry:deviceInfo.locationCountry,locationCity:deviceInfo.locationCity,loginMethod:params.loginMethod||"password",rememberMe:params.rememberMe??!1,trustScore,lastActivityAt:new Date,createdAt:new Date,expiresAt:(()=>{let ttl=lifetimeSeconds(authentication.sessionToken?.expiresIn,2592000);return ttl===null?null:new Date(Date.now()+ttl*1000)})(),isActive:approvalStatus==="approved",approvalStatus,approvalToken,approvalRequestedAt:requiresApproval?new Date:null}),shouldNotifyDevice({emailAvailable:Boolean(getEmailService()?.isAvailable()),isImpersonationLogin:Boolean(isImpersonationLogin),notifyOnNewDevice:Boolean(sessionsConfig?.notifyOnNewDevice),isNewDevice,trustScore,lowTrustThreshold:LOW_TRUST_THRESHOLD,requiresApproval:Boolean(requiresApproval)})){let resolvedUsersTable=resolveTableForTenant("users",reqSchemaName);if(resolvedUsersTable){let user=(await db.select().from(resolvedUsersTable).where(eq63(resolvedUsersTable.id,params.userId)).limit(1))[0];if(user?.email&&!isEmailExempt(user.email,authentication?.emailExemptDomains)){let isLowTrust=trustScore<LOW_TRUST_THRESHOLD,sessionsRoute=authentication.sessions?.route||"/auth/sessions",configuredUrl=authentication.sessions?.approvalRedirectUrl||"",isLegacyFrontendUrl=!configuredUrl||configuredUrl.endsWith("/devices"),approvalBase;if(!isLegacyFrontendUrl)approvalBase=configuredUrl;else{let origin=pickTrustedOrigin(params.requestOrigin,configuredUrl,trustedAppOrigins());if(params.requestOrigin&&origin!==params.requestOrigin)logger2.warn("[AUTH] Device-approval link origin refused \u2014 not in trustedAppOrigins",{requested:params.requestOrigin,used:origin||"(none)"});approvalBase=`${origin||"http://localhost:9000"}${sessionsRoute}`}let approveUrl=approvalToken?`${approvalBase}/approve-page?token=${approvalToken}`:"",rejectUrl=approvalToken?`${approvalBase}/reject-page?token=${approvalToken}`:"",subject,emailHtml,brandName=resolvedOptions.appId||"Nucleus",loginTime=new Date().toLocaleString("en-US",{dateStyle:"medium",timeStyle:"short"}),deviceSummary=`${deviceInfo.browserName||"Unknown"} ${deviceInfo.browserVersion||""} on ${deviceInfo.osName||"Unknown"} ${deviceInfo.osVersion||""}`,emailWrapper=(content)=>`
|
|
1985
1990
|
<!DOCTYPE html>
|
|
1986
1991
|
<html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1.0"></head>
|
|
1987
1992
|
<body style="margin:0;padding:0;background-color:#f4f4f5;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">
|