@open-mercato/onboarding 0.6.4-develop.4371.1.8f3030407e → 0.6.4

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.
@@ -0,0 +1,15 @@
1
+ import { getCachedRateLimiterService } from '@open-mercato/core/bootstrap'
2
+ import { getClientIp } from '@open-mercato/shared/lib/ratelimit/helpers'
3
+
4
+ /**
5
+ * Resolve the client IP to persist on a legal-consent record, honoring the
6
+ * deployment-wide reverse-proxy trust depth (`RATE_LIMIT_TRUST_PROXY_DEPTH`)
7
+ * exposed by the rate limiter service instead of a hardcoded depth. When the
8
+ * trust depth is unknown, return null so a spoofable `X-Forwarded-For` value is
9
+ * never signed into the consent integrity hash.
10
+ */
11
+ export function resolveConsentClientIp(req: Request): string | null {
12
+ const rateLimiterService = getCachedRateLimiterService()
13
+ if (!rateLimiterService) return null
14
+ return getClientIp(req, rateLimiterService.trustProxyDepth) ?? null
15
+ }
@@ -4,6 +4,7 @@ import { loadDictionary } from '@open-mercato/shared/lib/i18n/server'
4
4
  import { defaultLocale, locales, type Locale } from '@open-mercato/shared/lib/i18n/config'
5
5
  import { createFallbackTranslator } from '@open-mercato/shared/lib/i18n/translate'
6
6
  import { sendEmail } from '@open-mercato/shared/lib/email/send'
7
+ import { getSecurityEmailBaseUrl } from '@open-mercato/shared/lib/url'
7
8
  import { OnboardingService } from '@open-mercato/onboarding/modules/onboarding/lib/service'
8
9
  import WorkspaceReadyEmail from '@open-mercato/onboarding/modules/onboarding/emails/WorkspaceReadyEmail'
9
10
 
@@ -14,7 +15,6 @@ function resolveLocale(rawLocale: string | null | undefined): Locale {
14
15
 
15
16
  export async function sendWorkspaceReadyEmail(args: {
16
17
  requestId: string
17
- baseUrl: string
18
18
  tenantId: string
19
19
  }) {
20
20
  const container = await createRequestContainer()
@@ -25,7 +25,8 @@ export async function sendWorkspaceReadyEmail(args: {
25
25
  const locale = resolveLocale(request.locale)
26
26
  const dict = await loadDictionary(locale)
27
27
  const translate = createFallbackTranslator(dict)
28
- const loginUrl = `${args.baseUrl}/login?tenant=${encodeURIComponent(args.tenantId)}`
28
+ const baseUrl = getSecurityEmailBaseUrl()
29
+ const loginUrl = `${baseUrl}/login?tenant=${encodeURIComponent(args.tenantId)}`
29
30
  const firstName = request.firstName?.trim() || request.organizationName?.trim() || request.email
30
31
  const subject = translate('onboarding.readyEmail.subject', 'Your Open Mercato workspace is ready')
31
32
  const emailCopy = {
@@ -97,16 +97,28 @@ export class OnboardingService {
97
97
  )
98
98
  }
99
99
 
100
- async startProcessing(request: OnboardingRequest, startedAt: Date) {
100
+ async startProcessing(request: OnboardingRequest, startedAt: Date): Promise<boolean> {
101
+ const claimedRows = await this.em.nativeUpdate(
102
+ OnboardingRequest,
103
+ { id: request.id, status: 'pending' },
104
+ { status: 'processing', processingStartedAt: startedAt, updatedAt: new Date() },
105
+ )
106
+ if (claimedRows === 0) return false
101
107
  request.status = 'processing'
102
108
  request.processingStartedAt = startedAt
103
- await this.em.flush()
109
+ return true
104
110
  }
105
111
 
106
- async resetProcessing(request: OnboardingRequest) {
112
+ async resetProcessing(request: OnboardingRequest): Promise<boolean> {
113
+ const revertedRows = await this.em.nativeUpdate(
114
+ OnboardingRequest,
115
+ { id: request.id, status: 'processing' },
116
+ { status: 'pending', processingStartedAt: null, updatedAt: new Date() },
117
+ )
118
+ if (revertedRows === 0) return false
107
119
  request.status = 'pending'
108
120
  request.processingStartedAt = null
109
- await this.em.flush()
121
+ return true
110
122
  }
111
123
 
112
124
  async updateProvisioningIds(request: OnboardingRequest, data: { tenantId: string; organizationId: string; userId: string }) {