@open-mercato/core 0.6.7-develop.6788.1.c2a1520a30 → 0.6.7-develop.6795.1.8a3f27921c

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/generated/entities.ids.generated.js +1 -0
  3. package/dist/generated/entities.ids.generated.js.map +2 -2
  4. package/dist/modules/customers/cli.js +17 -7
  5. package/dist/modules/customers/cli.js.map +2 -2
  6. package/dist/modules/customers/search.js +50 -29
  7. package/dist/modules/customers/search.js.map +2 -2
  8. package/dist/modules/data_sync/api/mappings/[id]/route.js +22 -9
  9. package/dist/modules/data_sync/api/mappings/[id]/route.js.map +2 -2
  10. package/dist/modules/data_sync/api/mappings/route.js +13 -4
  11. package/dist/modules/data_sync/api/mappings/route.js.map +2 -2
  12. package/dist/modules/data_sync/api/options.js +7 -2
  13. package/dist/modules/data_sync/api/options.js.map +2 -2
  14. package/dist/modules/data_sync/api/run.js +7 -2
  15. package/dist/modules/data_sync/api/run.js.map +2 -2
  16. package/dist/modules/data_sync/api/runs/[id]/cancel.js +8 -3
  17. package/dist/modules/data_sync/api/runs/[id]/cancel.js.map +2 -2
  18. package/dist/modules/data_sync/api/runs/[id]/retry.js +7 -2
  19. package/dist/modules/data_sync/api/runs/[id]/retry.js.map +2 -2
  20. package/dist/modules/data_sync/api/runs/[id]/route.js +8 -3
  21. package/dist/modules/data_sync/api/runs/[id]/route.js.map +2 -2
  22. package/dist/modules/data_sync/api/runs.js +7 -2
  23. package/dist/modules/data_sync/api/runs.js.map +2 -2
  24. package/dist/modules/data_sync/api/schedules/[id]/route.js +19 -6
  25. package/dist/modules/data_sync/api/schedules/[id]/route.js.map +2 -2
  26. package/dist/modules/data_sync/api/schedules/route.js +13 -4
  27. package/dist/modules/data_sync/api/schedules/route.js.map +2 -2
  28. package/dist/modules/data_sync/api/validate.js +9 -4
  29. package/dist/modules/data_sync/api/validate.js.map +2 -2
  30. package/dist/modules/design_system/acl.js +9 -0
  31. package/dist/modules/design_system/acl.js.map +7 -0
  32. package/dist/modules/design_system/backend/design-system/page.js +11 -0
  33. package/dist/modules/design_system/backend/design-system/page.js.map +7 -0
  34. package/dist/modules/design_system/backend/design-system/page.meta.js +15 -0
  35. package/dist/modules/design_system/backend/design-system/page.meta.js.map +7 -0
  36. package/dist/modules/design_system/gallery/components/CodeSnippet.js +52 -0
  37. package/dist/modules/design_system/gallery/components/CodeSnippet.js.map +7 -0
  38. package/dist/modules/design_system/gallery/components/EntryCard.js +63 -0
  39. package/dist/modules/design_system/gallery/components/EntryCard.js.map +7 -0
  40. package/dist/modules/design_system/gallery/components/GalleryShell.js +163 -0
  41. package/dist/modules/design_system/gallery/components/GalleryShell.js.map +7 -0
  42. package/dist/modules/design_system/gallery/components/VariantPreview.js +9 -0
  43. package/dist/modules/design_system/gallery/components/VariantPreview.js.map +7 -0
  44. package/dist/modules/design_system/gallery/entries/banners.js +186 -0
  45. package/dist/modules/design_system/gallery/entries/banners.js.map +7 -0
  46. package/dist/modules/design_system/gallery/entries/buttons.js +361 -0
  47. package/dist/modules/design_system/gallery/entries/buttons.js.map +7 -0
  48. package/dist/modules/design_system/gallery/entries/charts.js +457 -0
  49. package/dist/modules/design_system/gallery/entries/charts.js.map +7 -0
  50. package/dist/modules/design_system/gallery/entries/dates.js +306 -0
  51. package/dist/modules/design_system/gallery/entries/dates.js.map +7 -0
  52. package/dist/modules/design_system/gallery/entries/detail.js +358 -0
  53. package/dist/modules/design_system/gallery/entries/detail.js.map +7 -0
  54. package/dist/modules/design_system/gallery/entries/display.js +785 -0
  55. package/dist/modules/design_system/gallery/entries/display.js.map +7 -0
  56. package/dist/modules/design_system/gallery/entries/feedback.js +658 -0
  57. package/dist/modules/design_system/gallery/entries/feedback.js.map +7 -0
  58. package/dist/modules/design_system/gallery/entries/filters.js +505 -0
  59. package/dist/modules/design_system/gallery/entries/filters.js.map +7 -0
  60. package/dist/modules/design_system/gallery/entries/foundations.js +453 -0
  61. package/dist/modules/design_system/gallery/entries/foundations.js.map +7 -0
  62. package/dist/modules/design_system/gallery/entries/icons.js +140 -0
  63. package/dist/modules/design_system/gallery/entries/icons.js.map +7 -0
  64. package/dist/modules/design_system/gallery/entries/inputs.js +1217 -0
  65. package/dist/modules/design_system/gallery/entries/inputs.js.map +7 -0
  66. package/dist/modules/design_system/gallery/entries/messages.js +334 -0
  67. package/dist/modules/design_system/gallery/entries/messages.js.map +7 -0
  68. package/dist/modules/design_system/gallery/entries/navigation.js +475 -0
  69. package/dist/modules/design_system/gallery/entries/navigation.js.map +7 -0
  70. package/dist/modules/design_system/gallery/entries/notifications.js +257 -0
  71. package/dist/modules/design_system/gallery/entries/notifications.js.map +7 -0
  72. package/dist/modules/design_system/gallery/entries/overlays.js +576 -0
  73. package/dist/modules/design_system/gallery/entries/overlays.js.map +7 -0
  74. package/dist/modules/design_system/gallery/entries/scaffolding.js +378 -0
  75. package/dist/modules/design_system/gallery/entries/scaffolding.js.map +7 -0
  76. package/dist/modules/design_system/gallery/entries/schedule.js +297 -0
  77. package/dist/modules/design_system/gallery/entries/schedule.js.map +7 -0
  78. package/dist/modules/design_system/gallery/registry.js +139 -0
  79. package/dist/modules/design_system/gallery/registry.js.map +7 -0
  80. package/dist/modules/design_system/gallery/types.js +1 -0
  81. package/dist/modules/design_system/gallery/types.js.map +7 -0
  82. package/dist/modules/design_system/index.js +9 -0
  83. package/dist/modules/design_system/index.js.map +7 -0
  84. package/dist/modules/design_system/setup.js +14 -0
  85. package/dist/modules/design_system/setup.js.map +7 -0
  86. package/dist/modules/inbox_ops/search.js +15 -4
  87. package/dist/modules/inbox_ops/search.js.map +2 -2
  88. package/dist/modules/integrations/api/[id]/credentials/route.js +11 -5
  89. package/dist/modules/integrations/api/[id]/credentials/route.js.map +2 -2
  90. package/dist/modules/integrations/api/[id]/health/route.js +6 -3
  91. package/dist/modules/integrations/api/[id]/health/route.js.map +2 -2
  92. package/dist/modules/integrations/api/[id]/route.js +6 -3
  93. package/dist/modules/integrations/api/[id]/route.js.map +2 -2
  94. package/dist/modules/integrations/api/[id]/state/route.js +6 -3
  95. package/dist/modules/integrations/api/[id]/state/route.js.map +2 -2
  96. package/dist/modules/integrations/api/[id]/version/route.js +6 -3
  97. package/dist/modules/integrations/api/[id]/version/route.js.map +2 -2
  98. package/dist/modules/integrations/api/logs/route.js +6 -3
  99. package/dist/modules/integrations/api/logs/route.js.map +2 -2
  100. package/dist/modules/integrations/api/route.js +6 -3
  101. package/dist/modules/integrations/api/route.js.map +2 -2
  102. package/dist/modules/integrations/api/umes-read.js +2 -2
  103. package/dist/modules/integrations/api/umes-read.js.map +2 -2
  104. package/dist/modules/integrations/lib/organization-scope.js +2 -9
  105. package/dist/modules/integrations/lib/organization-scope.js.map +2 -2
  106. package/dist/modules/messages/search.js +10 -5
  107. package/dist/modules/messages/search.js.map +2 -2
  108. package/dist/modules/query_index/data/entities.js +2 -1
  109. package/dist/modules/query_index/data/entities.js.map +2 -2
  110. package/dist/modules/query_index/lib/engine.js +32 -50
  111. package/dist/modules/query_index/lib/engine.js.map +2 -2
  112. package/dist/modules/query_index/migrations/Migration20260731105052_query_index.js +17 -0
  113. package/dist/modules/query_index/migrations/Migration20260731105052_query_index.js.map +7 -0
  114. package/generated/entities.ids.generated.ts +1 -0
  115. package/package.json +16 -16
  116. package/src/modules/customers/cli.ts +17 -7
  117. package/src/modules/customers/i18n/de.json +17 -0
  118. package/src/modules/customers/i18n/en.json +17 -0
  119. package/src/modules/customers/i18n/es.json +17 -0
  120. package/src/modules/customers/i18n/pl.json +17 -0
  121. package/src/modules/customers/search.ts +59 -27
  122. package/src/modules/data_sync/AGENTS.md +1 -0
  123. package/src/modules/data_sync/api/mappings/[id]/route.ts +22 -9
  124. package/src/modules/data_sync/api/mappings/route.ts +13 -4
  125. package/src/modules/data_sync/api/options.ts +7 -2
  126. package/src/modules/data_sync/api/run.ts +7 -2
  127. package/src/modules/data_sync/api/runs/[id]/cancel.ts +8 -3
  128. package/src/modules/data_sync/api/runs/[id]/retry.ts +7 -2
  129. package/src/modules/data_sync/api/runs/[id]/route.ts +8 -3
  130. package/src/modules/data_sync/api/runs.ts +7 -2
  131. package/src/modules/data_sync/api/schedules/[id]/route.ts +19 -6
  132. package/src/modules/data_sync/api/schedules/route.ts +13 -4
  133. package/src/modules/data_sync/api/validate.ts +9 -4
  134. package/src/modules/design_system/AGENTS.md +34 -0
  135. package/src/modules/design_system/acl.ts +5 -0
  136. package/src/modules/design_system/backend/design-system/page.meta.ts +11 -0
  137. package/src/modules/design_system/backend/design-system/page.tsx +14 -0
  138. package/src/modules/design_system/gallery/components/CodeSnippet.tsx +55 -0
  139. package/src/modules/design_system/gallery/components/EntryCard.tsx +95 -0
  140. package/src/modules/design_system/gallery/components/GalleryShell.tsx +206 -0
  141. package/src/modules/design_system/gallery/components/VariantPreview.tsx +15 -0
  142. package/src/modules/design_system/gallery/entries/banners.tsx +226 -0
  143. package/src/modules/design_system/gallery/entries/buttons.tsx +422 -0
  144. package/src/modules/design_system/gallery/entries/charts.tsx +518 -0
  145. package/src/modules/design_system/gallery/entries/dates.tsx +325 -0
  146. package/src/modules/design_system/gallery/entries/detail.tsx +403 -0
  147. package/src/modules/design_system/gallery/entries/display.tsx +893 -0
  148. package/src/modules/design_system/gallery/entries/feedback.tsx +746 -0
  149. package/src/modules/design_system/gallery/entries/filters.tsx +570 -0
  150. package/src/modules/design_system/gallery/entries/foundations.tsx +529 -0
  151. package/src/modules/design_system/gallery/entries/icons.tsx +168 -0
  152. package/src/modules/design_system/gallery/entries/inputs.tsx +1516 -0
  153. package/src/modules/design_system/gallery/entries/messages.tsx +339 -0
  154. package/src/modules/design_system/gallery/entries/navigation.tsx +573 -0
  155. package/src/modules/design_system/gallery/entries/notifications.tsx +285 -0
  156. package/src/modules/design_system/gallery/entries/overlays.tsx +677 -0
  157. package/src/modules/design_system/gallery/entries/scaffolding.tsx +430 -0
  158. package/src/modules/design_system/gallery/entries/schedule.tsx +307 -0
  159. package/src/modules/design_system/gallery/registry.ts +152 -0
  160. package/src/modules/design_system/gallery/types.ts +32 -0
  161. package/src/modules/design_system/i18n/.hardcoded-allowlist.json +71 -0
  162. package/src/modules/design_system/i18n/de.json +46 -0
  163. package/src/modules/design_system/i18n/en.json +46 -0
  164. package/src/modules/design_system/i18n/es.json +46 -0
  165. package/src/modules/design_system/i18n/pl.json +46 -0
  166. package/src/modules/design_system/index.ts +7 -0
  167. package/src/modules/design_system/setup.ts +12 -0
  168. package/src/modules/inbox_ops/i18n/de.json +3 -0
  169. package/src/modules/inbox_ops/i18n/en.json +3 -0
  170. package/src/modules/inbox_ops/i18n/es.json +3 -0
  171. package/src/modules/inbox_ops/i18n/pl.json +3 -0
  172. package/src/modules/inbox_ops/search.ts +20 -4
  173. package/src/modules/integrations/api/[id]/credentials/route.ts +11 -5
  174. package/src/modules/integrations/api/[id]/health/route.ts +6 -3
  175. package/src/modules/integrations/api/[id]/route.ts +6 -3
  176. package/src/modules/integrations/api/[id]/state/route.ts +6 -3
  177. package/src/modules/integrations/api/[id]/version/route.ts +6 -3
  178. package/src/modules/integrations/api/logs/route.ts +6 -3
  179. package/src/modules/integrations/api/route.ts +6 -3
  180. package/src/modules/integrations/api/umes-read.ts +2 -2
  181. package/src/modules/integrations/lib/organization-scope.ts +5 -25
  182. package/src/modules/messages/i18n/de.json +2 -0
  183. package/src/modules/messages/i18n/en.json +2 -0
  184. package/src/modules/messages/i18n/es.json +2 -0
  185. package/src/modules/messages/i18n/pl.json +2 -0
  186. package/src/modules/messages/search.ts +11 -5
  187. package/src/modules/query_index/data/entities.ts +7 -0
  188. package/src/modules/query_index/lib/engine.ts +40 -63
  189. package/src/modules/query_index/migrations/.snapshot-open-mercato.json +12 -0
  190. package/src/modules/query_index/migrations/Migration20260731105052_query_index.ts +35 -0
@@ -1,6 +1,7 @@
1
1
  import { NextResponse } from 'next/server'
2
2
  import { z } from 'zod'
3
3
  import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
4
+ import { organizationScopeRequiredResponse, resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'
4
5
  import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
5
6
  import type { EntityManager } from '@mikro-orm/postgresql'
6
7
  import { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'
@@ -36,9 +37,13 @@ async function resolveParams(ctx: { params?: Promise<{ id?: string }> | { id?: s
36
37
 
37
38
  export async function GET(req: Request, ctx: { params?: Promise<{ id?: string }> | { id?: string } }) {
38
39
  const auth = await getAuthFromRequest(req)
39
- if (!auth?.tenantId || !auth.orgId) {
40
+ if (!auth?.tenantId) {
40
41
  return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
41
42
  }
43
+ const organizationId = resolveActiveOrganizationId(auth)
44
+ if (!organizationId) {
45
+ return organizationScopeRequiredResponse()
46
+ }
42
47
 
43
48
  const parsedParams = await resolveParams(ctx)
44
49
  if (!parsedParams.success) {
@@ -47,14 +52,14 @@ export async function GET(req: Request, ctx: { params?: Promise<{ id?: string }>
47
52
 
48
53
  const container = await createRequestContainer()
49
54
  const em = container.resolve('em') as EntityManager
50
- const scope = { organizationId: auth.orgId as string, tenantId: auth.tenantId }
55
+ const scope = { organizationId, tenantId: auth.tenantId }
51
56
 
52
57
  const mapping = await findOneWithDecryption(
53
58
  em,
54
59
  SyncMapping,
55
60
  {
56
61
  id: parsedParams.data.id,
57
- organizationId: auth.orgId as string,
62
+ organizationId,
58
63
  tenantId: auth.tenantId,
59
64
  },
60
65
  undefined,
@@ -77,9 +82,13 @@ export async function GET(req: Request, ctx: { params?: Promise<{ id?: string }>
77
82
 
78
83
  export async function PUT(req: Request, ctx: { params?: Promise<{ id?: string }> | { id?: string } }) {
79
84
  const auth = await getAuthFromRequest(req)
80
- if (!auth?.tenantId || !auth.orgId) {
85
+ if (!auth?.tenantId) {
81
86
  return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
82
87
  }
88
+ const organizationId = resolveActiveOrganizationId(auth)
89
+ if (!organizationId) {
90
+ return organizationScopeRequiredResponse()
91
+ }
83
92
 
84
93
  const parsedParams = await resolveParams(ctx)
85
94
  if (!parsedParams.success) {
@@ -94,14 +103,14 @@ export async function PUT(req: Request, ctx: { params?: Promise<{ id?: string }>
94
103
 
95
104
  const container = await createRequestContainer()
96
105
  const em = container.resolve('em') as EntityManager
97
- const scope = { organizationId: auth.orgId as string, tenantId: auth.tenantId }
106
+ const scope = { organizationId, tenantId: auth.tenantId }
98
107
 
99
108
  const mapping = await findOneWithDecryption(
100
109
  em,
101
110
  SyncMapping,
102
111
  {
103
112
  id: parsedParams.data.id,
104
- organizationId: auth.orgId as string,
113
+ organizationId,
105
114
  tenantId: auth.tenantId,
106
115
  },
107
116
  undefined,
@@ -155,9 +164,13 @@ export async function PUT(req: Request, ctx: { params?: Promise<{ id?: string }>
155
164
 
156
165
  export async function DELETE(req: Request, ctx: { params?: Promise<{ id?: string }> | { id?: string } }) {
157
166
  const auth = await getAuthFromRequest(req)
158
- if (!auth?.tenantId || !auth.orgId) {
167
+ if (!auth?.tenantId) {
159
168
  return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
160
169
  }
170
+ const organizationId = resolveActiveOrganizationId(auth)
171
+ if (!organizationId) {
172
+ return organizationScopeRequiredResponse()
173
+ }
161
174
 
162
175
  const parsedParams = await resolveParams(ctx)
163
176
  if (!parsedParams.success) {
@@ -166,14 +179,14 @@ export async function DELETE(req: Request, ctx: { params?: Promise<{ id?: string
166
179
 
167
180
  const container = await createRequestContainer()
168
181
  const em = container.resolve('em') as EntityManager
169
- const scope = { organizationId: auth.orgId as string, tenantId: auth.tenantId }
182
+ const scope = { organizationId, tenantId: auth.tenantId }
170
183
 
171
184
  const mapping = await findOneWithDecryption(
172
185
  em,
173
186
  SyncMapping,
174
187
  {
175
188
  id: parsedParams.data.id,
176
- organizationId: auth.orgId as string,
189
+ organizationId,
177
190
  tenantId: auth.tenantId,
178
191
  },
179
192
  undefined,
@@ -1,6 +1,7 @@
1
1
  import { NextResponse } from 'next/server'
2
2
  import { z } from 'zod'
3
3
  import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
4
+ import { organizationScopeRequiredResponse, resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'
4
5
  import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
5
6
  import type { EntityManager, FilterQuery } from '@mikro-orm/postgresql'
6
7
  import { findAndCountWithDecryption, findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'
@@ -35,9 +36,13 @@ export const openApi = {
35
36
 
36
37
  export async function GET(req: Request) {
37
38
  const auth = await getAuthFromRequest(req)
38
- if (!auth?.tenantId || !auth.orgId) {
39
+ if (!auth?.tenantId) {
39
40
  return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
40
41
  }
42
+ const organizationId = resolveActiveOrganizationId(auth)
43
+ if (!organizationId) {
44
+ return organizationScopeRequiredResponse()
45
+ }
41
46
 
42
47
  const url = new URL(req.url)
43
48
  const parsed = listMappingsQuerySchema.safeParse({
@@ -53,7 +58,7 @@ export async function GET(req: Request) {
53
58
 
54
59
  const container = await createRequestContainer()
55
60
  const em = container.resolve('em') as EntityManager
56
- const scope = { organizationId: auth.orgId as string, tenantId: auth.tenantId }
61
+ const scope = { organizationId, tenantId: auth.tenantId }
57
62
 
58
63
  const where: FilterQuery<SyncMapping> = {
59
64
  organizationId: scope.organizationId,
@@ -92,9 +97,13 @@ export async function GET(req: Request) {
92
97
 
93
98
  export async function POST(req: Request) {
94
99
  const auth = await getAuthFromRequest(req)
95
- if (!auth?.tenantId || !auth.orgId) {
100
+ if (!auth?.tenantId) {
96
101
  return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
97
102
  }
103
+ const organizationId = resolveActiveOrganizationId(auth)
104
+ if (!organizationId) {
105
+ return organizationScopeRequiredResponse()
106
+ }
98
107
 
99
108
  const payload = await req.json().catch(() => null)
100
109
  const parsed = createMappingSchema.safeParse(payload)
@@ -104,7 +113,7 @@ export async function POST(req: Request) {
104
113
 
105
114
  const container = await createRequestContainer()
106
115
  const em = container.resolve('em') as EntityManager
107
- const scope = { organizationId: auth.orgId as string, tenantId: auth.tenantId }
116
+ const scope = { organizationId, tenantId: auth.tenantId }
108
117
 
109
118
  const existing = await findOneWithDecryption(
110
119
  em,
@@ -1,5 +1,6 @@
1
1
  import { NextResponse } from 'next/server'
2
2
  import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
3
+ import { organizationScopeRequiredResponse, resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'
3
4
  import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
4
5
  import { getAllIntegrations } from '@open-mercato/shared/modules/integrations/types'
5
6
  import type { CredentialsService } from '../../integrations/lib/credentials-service'
@@ -17,14 +18,18 @@ export const openApi = {
17
18
 
18
19
  export async function GET(req: Request) {
19
20
  const auth = await getAuthFromRequest(req)
20
- if (!auth?.tenantId || !auth.orgId) {
21
+ if (!auth?.tenantId) {
21
22
  return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
22
23
  }
24
+ const organizationId = resolveActiveOrganizationId(auth)
25
+ if (!organizationId) {
26
+ return organizationScopeRequiredResponse()
27
+ }
23
28
 
24
29
  const container = await createRequestContainer()
25
30
  const credentialsService = container.resolve('integrationCredentialsService') as CredentialsService
26
31
  const stateService = container.resolve('integrationStateService') as IntegrationStateService
27
- const scope = { organizationId: auth.orgId as string, tenantId: auth.tenantId }
32
+ const scope = { organizationId, tenantId: auth.tenantId }
28
33
 
29
34
  const items = await Promise.all(
30
35
  getAllIntegrations()
@@ -1,5 +1,6 @@
1
1
  import { NextResponse } from 'next/server'
2
2
  import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
3
+ import { organizationScopeRequiredResponse, resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'
3
4
  import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
4
5
  import { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'
5
6
  import { getIntegration } from '@open-mercato/shared/modules/integrations/types'
@@ -29,9 +30,13 @@ export const openApi = {
29
30
  export async function POST(req: Request) {
30
31
  try {
31
32
  const auth = await getAuthFromRequest(req)
32
- if (!auth?.tenantId || !auth.orgId) {
33
+ if (!auth?.tenantId) {
33
34
  return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
34
35
  }
36
+ const organizationId = resolveActiveOrganizationId(auth)
37
+ if (!organizationId) {
38
+ return organizationScopeRequiredResponse()
39
+ }
35
40
 
36
41
  const payload = await readJsonSafe(req)
37
42
  const parsed = runSyncSchema.safeParse(payload)
@@ -45,7 +50,7 @@ export async function POST(req: Request) {
45
50
  const integrationStateService = container.resolve('integrationStateService') as IntegrationStateService
46
51
 
47
52
  const scope = {
48
- organizationId: auth.orgId as string,
53
+ organizationId,
49
54
  tenantId: auth.tenantId,
50
55
  }
51
56
 
@@ -1,6 +1,7 @@
1
1
  import { NextResponse } from 'next/server'
2
2
  import { z } from 'zod'
3
3
  import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
4
+ import { organizationScopeRequiredResponse, resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'
4
5
  import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
5
6
  import type { IntegrationLogService } from '../../../../integrations/lib/log-service'
6
7
  import type { IntegrationStateService } from '../../../../integrations/lib/state-service'
@@ -24,9 +25,13 @@ export const openApi = {
24
25
 
25
26
  export async function POST(req: Request, ctx: { params?: Promise<{ id?: string }> | { id?: string } }) {
26
27
  const auth = await getAuthFromRequest(req)
27
- if (!auth?.tenantId || !auth.orgId) {
28
+ if (!auth?.tenantId) {
28
29
  return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
29
30
  }
31
+ const organizationId = resolveActiveOrganizationId(auth)
32
+ if (!organizationId) {
33
+ return organizationScopeRequiredResponse()
34
+ }
30
35
 
31
36
  const rawParams = (ctx.params && typeof (ctx.params as Promise<unknown>).then === 'function')
32
37
  ? await (ctx.params as Promise<{ id?: string }>)
@@ -42,7 +47,7 @@ export async function POST(req: Request, ctx: { params?: Promise<{ id?: string }
42
47
  const progressService = container.resolve('progressService') as ProgressService
43
48
  const integrationLogService = container.resolve('integrationLogService') as IntegrationLogService
44
49
  const integrationStateService = container.resolve('integrationStateService') as IntegrationStateService
45
- const scope = { organizationId: auth.orgId as string, tenantId: auth.tenantId }
50
+ const scope = { organizationId, tenantId: auth.tenantId }
46
51
 
47
52
  const run = await syncRunService.getRun(parsed.data.id, scope)
48
53
  if (!run) {
@@ -69,7 +74,7 @@ export async function POST(req: Request, ctx: { params?: Promise<{ id?: string }
69
74
 
70
75
  const progressCtx = {
71
76
  tenantId: auth.tenantId,
72
- organizationId: auth.orgId,
77
+ organizationId,
73
78
  userId: auth.sub,
74
79
  }
75
80
 
@@ -1,6 +1,7 @@
1
1
  import { NextResponse } from 'next/server'
2
2
  import { z } from 'zod'
3
3
  import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
4
+ import { organizationScopeRequiredResponse, resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'
4
5
  import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
5
6
  import { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'
6
7
  import type { ProgressService } from '../../../../progress/lib/progressService'
@@ -25,9 +26,13 @@ export const openApi = {
25
26
 
26
27
  export async function POST(req: Request, ctx: { params?: Promise<{ id?: string }> | { id?: string } }) {
27
28
  const auth = await getAuthFromRequest(req)
28
- if (!auth?.tenantId || !auth.orgId) {
29
+ if (!auth?.tenantId) {
29
30
  return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
30
31
  }
32
+ const organizationId = resolveActiveOrganizationId(auth)
33
+ if (!organizationId) {
34
+ return organizationScopeRequiredResponse()
35
+ }
31
36
 
32
37
  const rawParams = (ctx.params && typeof (ctx.params as Promise<unknown>).then === 'function')
33
38
  ? await (ctx.params as Promise<{ id?: string }>)
@@ -47,7 +52,7 @@ export async function POST(req: Request, ctx: { params?: Promise<{ id?: string }
47
52
  const container = await createRequestContainer()
48
53
  const syncRunService = container.resolve('dataSyncRunService') as SyncRunService
49
54
  const progressService = container.resolve('progressService') as ProgressService
50
- const scope = { organizationId: auth.orgId as string, tenantId: auth.tenantId }
55
+ const scope = { organizationId, tenantId: auth.tenantId }
51
56
 
52
57
  const previous = await syncRunService.getRun(parsedParams.data.id, scope)
53
58
  if (!previous) {
@@ -1,6 +1,7 @@
1
1
  import { NextResponse } from 'next/server'
2
2
  import { z } from 'zod'
3
3
  import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
4
+ import { organizationScopeRequiredResponse, resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'
4
5
  import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
5
6
  import type { ProgressService } from '../../../../progress/lib/progressService'
6
7
  import type { SyncRunService } from '../../../lib/sync-run-service'
@@ -18,9 +19,13 @@ export const openApi = {
18
19
 
19
20
  export async function GET(req: Request, ctx: { params?: Promise<{ id?: string }> | { id?: string } }) {
20
21
  const auth = await getAuthFromRequest(req)
21
- if (!auth?.tenantId || !auth.orgId) {
22
+ if (!auth?.tenantId) {
22
23
  return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
23
24
  }
25
+ const organizationId = resolveActiveOrganizationId(auth)
26
+ if (!organizationId) {
27
+ return organizationScopeRequiredResponse()
28
+ }
24
29
 
25
30
  const rawParams = (ctx.params && typeof (ctx.params as Promise<unknown>).then === 'function')
26
31
  ? await (ctx.params as Promise<{ id?: string }>)
@@ -34,7 +39,7 @@ export async function GET(req: Request, ctx: { params?: Promise<{ id?: string }>
34
39
  const container = await createRequestContainer()
35
40
  const syncRunService = container.resolve('dataSyncRunService') as SyncRunService
36
41
  const progressService = container.resolve('progressService') as ProgressService
37
- const scope = { organizationId: auth.orgId as string, tenantId: auth.tenantId }
42
+ const scope = { organizationId, tenantId: auth.tenantId }
38
43
 
39
44
  const run = await syncRunService.getRun(parsed.data.id, scope)
40
45
  if (!run) {
@@ -44,7 +49,7 @@ export async function GET(req: Request, ctx: { params?: Promise<{ id?: string }>
44
49
  const progressJob = run.progressJobId
45
50
  ? await progressService.getJob(run.progressJobId, {
46
51
  tenantId: auth.tenantId,
47
- organizationId: auth.orgId,
52
+ organizationId,
48
53
  userId: auth.sub,
49
54
  })
50
55
  : null
@@ -1,5 +1,6 @@
1
1
  import { NextResponse } from 'next/server'
2
2
  import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
3
+ import { organizationScopeRequiredResponse, resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'
3
4
  import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
4
5
  import { listSyncRunsQuerySchema } from '../data/validators'
5
6
  import type { SyncRunService } from '../lib/sync-run-service'
@@ -15,9 +16,13 @@ export const openApi = {
15
16
 
16
17
  export async function GET(req: Request) {
17
18
  const auth = await getAuthFromRequest(req)
18
- if (!auth?.tenantId || !auth.orgId) {
19
+ if (!auth?.tenantId) {
19
20
  return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
20
21
  }
22
+ const organizationId = resolveActiveOrganizationId(auth)
23
+ if (!organizationId) {
24
+ return organizationScopeRequiredResponse()
25
+ }
21
26
 
22
27
  const url = new URL(req.url)
23
28
  const parsed = listSyncRunsQuerySchema.safeParse({
@@ -38,7 +43,7 @@ export async function GET(req: Request) {
38
43
  const syncRunService = container.resolve('dataSyncRunService') as SyncRunService
39
44
 
40
45
  const { items, total } = await syncRunService.listRuns(parsed.data, {
41
- organizationId: auth.orgId as string,
46
+ organizationId,
42
47
  tenantId: auth.tenantId,
43
48
  })
44
49
 
@@ -1,6 +1,7 @@
1
1
  import { NextResponse } from 'next/server'
2
2
  import { z } from 'zod'
3
3
  import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
4
+ import { organizationScopeRequiredResponse, resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'
4
5
  import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
5
6
  import { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'
6
7
  import { readOptimisticLockExpected } from '@open-mercato/shared/lib/crud/optimistic-lock-command'
@@ -30,9 +31,13 @@ export const openApi = {
30
31
 
31
32
  export async function GET(req: Request, ctx: { params?: Promise<{ id?: string }> | { id?: string } }) {
32
33
  const auth = await getAuthFromRequest(req)
33
- if (!auth?.tenantId || !auth.orgId) {
34
+ if (!auth?.tenantId) {
34
35
  return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
35
36
  }
37
+ const organizationId = resolveActiveOrganizationId(auth)
38
+ if (!organizationId) {
39
+ return organizationScopeRequiredResponse()
40
+ }
36
41
 
37
42
  const rawParams = (ctx.params && typeof (ctx.params as Promise<unknown>).then === 'function')
38
43
  ? await (ctx.params as Promise<{ id?: string }>)
@@ -46,7 +51,7 @@ export async function GET(req: Request, ctx: { params?: Promise<{ id?: string }>
46
51
  const container = await createRequestContainer()
47
52
  const scheduleService = container.resolve('dataSyncScheduleService') as SyncScheduleService
48
53
  const schedule = await scheduleService.getById(parsedParams.data.id, {
49
- organizationId: auth.orgId as string,
54
+ organizationId,
50
55
  tenantId: auth.tenantId,
51
56
  })
52
57
 
@@ -59,9 +64,13 @@ export async function GET(req: Request, ctx: { params?: Promise<{ id?: string }>
59
64
 
60
65
  export async function PUT(req: Request, ctx: { params?: Promise<{ id?: string }> | { id?: string } }) {
61
66
  const auth = await getAuthFromRequest(req)
62
- if (!auth?.tenantId || !auth.orgId) {
67
+ if (!auth?.tenantId) {
63
68
  return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
64
69
  }
70
+ const organizationId = resolveActiveOrganizationId(auth)
71
+ if (!organizationId) {
72
+ return organizationScopeRequiredResponse()
73
+ }
65
74
 
66
75
  const rawParams = (ctx.params && typeof (ctx.params as Promise<unknown>).then === 'function')
67
76
  ? await (ctx.params as Promise<{ id?: string }>)
@@ -80,7 +89,7 @@ export async function PUT(req: Request, ctx: { params?: Promise<{ id?: string }>
80
89
 
81
90
  const container = await createRequestContainer()
82
91
  const scheduleService = container.resolve('dataSyncScheduleService') as SyncScheduleService
83
- const scope = { organizationId: auth.orgId as string, tenantId: auth.tenantId }
92
+ const scope = { organizationId, tenantId: auth.tenantId }
84
93
  const current = await scheduleService.getById(parsedParams.data.id, scope)
85
94
 
86
95
  if (!current) {
@@ -141,9 +150,13 @@ export async function PUT(req: Request, ctx: { params?: Promise<{ id?: string }>
141
150
 
142
151
  export async function DELETE(req: Request, ctx: { params?: Promise<{ id?: string }> | { id?: string } }) {
143
152
  const auth = await getAuthFromRequest(req)
144
- if (!auth?.tenantId || !auth.orgId) {
153
+ if (!auth?.tenantId) {
145
154
  return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
146
155
  }
156
+ const organizationId = resolveActiveOrganizationId(auth)
157
+ if (!organizationId) {
158
+ return organizationScopeRequiredResponse()
159
+ }
147
160
 
148
161
  const rawParams = (ctx.params && typeof (ctx.params as Promise<unknown>).then === 'function')
149
162
  ? await (ctx.params as Promise<{ id?: string }>)
@@ -156,7 +169,7 @@ export async function DELETE(req: Request, ctx: { params?: Promise<{ id?: string
156
169
 
157
170
  const container = await createRequestContainer()
158
171
  const scheduleService = container.resolve('dataSyncScheduleService') as SyncScheduleService
159
- const scope = { organizationId: auth.orgId as string, tenantId: auth.tenantId }
172
+ const scope = { organizationId, tenantId: auth.tenantId }
160
173
 
161
174
  const guardResult = await validateCrudMutationGuard(container, {
162
175
  tenantId: auth.tenantId,
@@ -1,5 +1,6 @@
1
1
  import { NextResponse } from 'next/server'
2
2
  import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
3
+ import { organizationScopeRequiredResponse, resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'
3
4
  import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
4
5
  import { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'
5
6
  import { createSyncScheduleSchema, listSyncSchedulesQuerySchema } from '../../data/validators'
@@ -24,9 +25,13 @@ export const openApi = {
24
25
 
25
26
  export async function GET(req: Request) {
26
27
  const auth = await getAuthFromRequest(req)
27
- if (!auth?.tenantId || !auth.orgId) {
28
+ if (!auth?.tenantId) {
28
29
  return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
29
30
  }
31
+ const organizationId = resolveActiveOrganizationId(auth)
32
+ if (!organizationId) {
33
+ return organizationScopeRequiredResponse()
34
+ }
30
35
 
31
36
  const url = new URL(req.url)
32
37
  const parsed = listSyncSchedulesQuerySchema.safeParse({
@@ -43,7 +48,7 @@ export async function GET(req: Request) {
43
48
 
44
49
  const container = await createRequestContainer()
45
50
  const scheduleService = container.resolve('dataSyncScheduleService') as SyncScheduleService
46
- const scope = { organizationId: auth.orgId as string, tenantId: auth.tenantId }
51
+ const scope = { organizationId, tenantId: auth.tenantId }
47
52
  const { items, total } = await scheduleService.listSchedules(parsed.data, scope)
48
53
 
49
54
  return NextResponse.json({
@@ -57,9 +62,13 @@ export async function GET(req: Request) {
57
62
 
58
63
  export async function POST(req: Request) {
59
64
  const auth = await getAuthFromRequest(req)
60
- if (!auth?.tenantId || !auth.orgId) {
65
+ if (!auth?.tenantId) {
61
66
  return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
62
67
  }
68
+ const organizationId = resolveActiveOrganizationId(auth)
69
+ if (!organizationId) {
70
+ return organizationScopeRequiredResponse()
71
+ }
63
72
 
64
73
  const payload = await readJsonSafe(req)
65
74
  const parsed = createSyncScheduleSchema.safeParse(payload)
@@ -69,7 +78,7 @@ export async function POST(req: Request) {
69
78
 
70
79
  const container = await createRequestContainer()
71
80
  const scheduleService = container.resolve('dataSyncScheduleService') as SyncScheduleService
72
- const scope = { organizationId: auth.orgId as string, tenantId: auth.tenantId }
81
+ const scope = { organizationId, tenantId: auth.tenantId }
73
82
 
74
83
  const guardResult = await validateCrudMutationGuard(container, {
75
84
  tenantId: auth.tenantId,
@@ -1,5 +1,6 @@
1
1
  import { NextResponse } from 'next/server'
2
2
  import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
3
+ import { organizationScopeRequiredResponse, resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'
3
4
  import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
4
5
  import { getIntegration } from '@open-mercato/shared/modules/integrations/types'
5
6
  import type { CredentialsService } from '../../integrations/lib/credentials-service'
@@ -17,9 +18,13 @@ export const openApi = {
17
18
 
18
19
  export async function POST(req: Request) {
19
20
  const auth = await getAuthFromRequest(req)
20
- if (!auth?.tenantId || !auth.orgId) {
21
+ if (!auth?.tenantId) {
21
22
  return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
22
23
  }
24
+ const organizationId = resolveActiveOrganizationId(auth)
25
+ if (!organizationId) {
26
+ return organizationScopeRequiredResponse()
27
+ }
23
28
 
24
29
  const parsed = validateConnectionSchema.safeParse(await req.json())
25
30
  if (!parsed.success) {
@@ -39,7 +44,7 @@ export async function POST(req: Request) {
39
44
  const container = await createRequestContainer()
40
45
  const credentialsService = container.resolve('integrationCredentialsService') as CredentialsService
41
46
  const credentials = await credentialsService.resolve(integration.id, {
42
- organizationId: auth.orgId as string,
47
+ organizationId,
43
48
  tenantId: auth.tenantId,
44
49
  })
45
50
 
@@ -50,7 +55,7 @@ export async function POST(req: Request) {
50
55
  const mapping = await adapter.getMapping({
51
56
  entityType: parsed.data.entityType,
52
57
  scope: {
53
- organizationId: auth.orgId as string,
58
+ organizationId,
54
59
  tenantId: auth.tenantId,
55
60
  },
56
61
  })
@@ -64,7 +69,7 @@ export async function POST(req: Request) {
64
69
  credentials,
65
70
  mapping,
66
71
  scope: {
67
- organizationId: auth.orgId as string,
72
+ organizationId,
68
73
  tenantId: auth.tenantId,
69
74
  },
70
75
  })
@@ -0,0 +1,34 @@
1
+ # Design System Module — Agent Guidelines
2
+
3
+ Live component gallery at `/backend/design-system`, gated by `design_system.view`. Entries are plain data (`gallery/entries/<family>.tsx`) listed in the family manifest (`gallery/registry.ts`) and lazy-loaded per family. The gallery is a DS consumer: it must showcase the DS without ever violating it.
4
+
5
+ ## Registry Contract
6
+
7
+ - `gallery/types.ts` defines `GalleryVariant` / `GalleryEntry` / `GalleryFamily` — do not extend them casually; the shapes are the spec contract (`.ai/specs/2026-07-05-ds-live-component-gallery.md`).
8
+ - A family = one manifest row in `galleryFamilies` + one `entries/<id>.tsx` exporting `entries: GalleryEntry[]`.
9
+ - Every variant keeps `render` and `code` side by side in one object literal; review them together — colocation is the drift defense.
10
+
11
+ ## Always
12
+
13
+ 1. **MUST keep every variant `code` snippet containing the entry's `importPath`** — enforced by `gallery/__tests__/registry-integrity.test.ts`.
14
+ 2. **MUST update the coverage allowlist honestly** — when adding a primitive entry, delete its row from `PENDING_FAMILIES` in `gallery/__tests__/gallery-coverage.test.ts`; when a new primitive lands without an entry, add it there with a one-line reason. `PENDING_FAMILIES` must only shrink as families land.
15
+ 3. **MUST use semantic tokens only** in gallery chrome (`border-border`, `bg-background`, `bg-muted`, `text-muted-foreground`) and lucide icons only.
16
+ 4. **MUST route all gallery chrome strings through `i18n/` in all four locales** (en, pl, es, de) via `useT()`. Component titles and variant names (`Button`, `destructive-soft`) are proper nouns and stay untranslated.
17
+ 5. **MUST render entries with inline mock props only** — the gallery never calls tenant APIs and never renders tenant data.
18
+ 6. **MUST keep `figmaNodeId` in `<page>:<node>` format** pointing into `DS_FIGMA_FILE`; omit it when unknown — never guess node ids.
19
+
20
+ ## Never
21
+
22
+ - Never add gallery-specific props or code to `packages/ui` — the gallery consumes primitives exactly as any other module does.
23
+ - Never hardcode colors, arbitrary sizes, or full-pill chips in gallery chrome.
24
+ - Never add API routes, entities, DI registrations, or tenant-scoped anything to this module.
25
+ - Never remove a file from the primitives coverage enumeration by loosening the test — only entries or allowlist rows with reasons.
26
+
27
+ ## Validation Commands
28
+
29
+ ```bash
30
+ yarn generate
31
+ yarn workspace @open-mercato/core test --testPathPattern design_system
32
+ yarn workspace @open-mercato/core typecheck
33
+ yarn i18n:check-hardcoded
34
+ ```
@@ -0,0 +1,5 @@
1
+ export const features = [
2
+ { id: 'design_system.view', title: 'View the design system gallery', module: 'design_system' },
3
+ ]
4
+
5
+ export default features
@@ -0,0 +1,11 @@
1
+ export const metadata = {
2
+ requireAuth: true,
3
+ requireFeatures: ['design_system.view'],
4
+ pageTitle: 'Design system',
5
+ pageTitleKey: 'design_system.nav.title',
6
+ pageGroup: 'Developer',
7
+ pageGroupKey: 'design_system.nav.group',
8
+ pageOrder: 900,
9
+ icon: 'shapes',
10
+ breadcrumb: [{ label: 'Design system', labelKey: 'design_system.nav.title' }],
11
+ }
@@ -0,0 +1,14 @@
1
+ "use client"
2
+
3
+ import { Page, PageBody } from '@open-mercato/ui/backend/Page'
4
+ import { GalleryShell } from '../../gallery/components/GalleryShell'
5
+
6
+ export default function DesignSystemGalleryPage() {
7
+ return (
8
+ <Page>
9
+ <PageBody>
10
+ <GalleryShell />
11
+ </PageBody>
12
+ </Page>
13
+ )
14
+ }