create-mercato-app 0.6.5-develop.4964.1.ae0edca575 → 0.6.5-develop.5048.1.fd82f4ae17

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-mercato-app",
3
- "version": "0.6.5-develop.4964.1.ae0edca575",
3
+ "version": "0.6.5-develop.5048.1.fd82f4ae17",
4
4
  "type": "module",
5
5
  "description": "Create a new Open Mercato application",
6
6
  "main": "./dist/index.js",
@@ -21,9 +21,21 @@ import { applicationLifecycleEvents, type ApplicationLifecycleEventId } from '@o
21
21
  bootstrap()
22
22
  registerApiRouteManifests(apiRoutes)
23
23
 
24
+ const warnedDeprecatedRequireRoles = new Set<string>()
25
+
26
+ function warnDeprecatedRequireRoles(pathname: string, method: HttpMethod): void {
27
+ const warnKey = `${method} ${pathname}`
28
+ if (warnedDeprecatedRequireRoles.has(warnKey)) return
29
+ warnedDeprecatedRequireRoles.add(warnKey)
30
+ console.warn(
31
+ '[api] Ignoring deprecated `requireRoles` guard — role names are mutable and spoofable, so they no longer authorize requests. Migrate to `requireFeatures` with immutable acl.ts feature IDs.',
32
+ { path: pathname, method },
33
+ )
34
+ }
35
+
24
36
  type MethodMetadata = {
25
37
  requireAuth?: boolean
26
- /** @deprecated Use `requireFeatures` instead — role names are mutable and can be spoofed */
38
+ /** @deprecated Ignored at runtime — role names are mutable and can be spoofed. Use `requireFeatures` instead. */
27
39
  requireRoles?: string[]
28
40
  requireFeatures?: string[]
29
41
  rateLimit?: RateLimitConfig
@@ -138,14 +150,14 @@ async function checkAuthorization(
138
150
  return NextResponse.json({ error: t('api.errors.unauthorized', 'Unauthorized') }, { status: 401 })
139
151
  }
140
152
 
141
- const requiredRoles = methodMetadata?.requireRoles ?? []
142
153
  const requiredFeatures = methodMetadata?.requireFeatures ?? []
143
154
 
144
- if (
145
- requiredRoles.length &&
146
- (!auth || !Array.isArray(auth.roles) || !requiredRoles.some((role) => auth.roles!.includes(role)))
147
- ) {
148
- return NextResponse.json({ error: t('api.errors.forbidden', 'Forbidden'), requiredRoles }, { status: 403 })
155
+ // `requireRoles` is deprecated and intentionally NOT enforced: role names are
156
+ // tenant-mutable and spoofable, so honoring them would let a tenant admin create
157
+ // or rename a role to satisfy the guard. Authorization decisions must use
158
+ // immutable feature IDs via `requireFeatures`. We warn so operators migrate.
159
+ if (methodMetadata?.requireRoles?.length) {
160
+ warnDeprecatedRequireRoles(req.nextUrl.pathname, req.method.toUpperCase() as HttpMethod)
149
161
  }
150
162
 
151
163
  let container: Awaited<ReturnType<typeof createRequestContainer>> | null = null
@@ -236,7 +248,7 @@ function sanitizeTenantCandidate(candidate: unknown): unknown {
236
248
  return candidate
237
249
  }
238
250
 
239
- async function extractTenantCandidate(req: NextRequest): Promise<unknown> {
251
+ export async function extractTenantCandidate(req: NextRequest): Promise<unknown> {
240
252
  const tenantParams = req.nextUrl?.searchParams?.getAll?.('tenantId') ?? []
241
253
  if (tenantParams.length > 0) {
242
254
  return tenantParams[tenantParams.length - 1]
@@ -261,7 +273,7 @@ async function extractTenantCandidate(req: NextRequest): Promise<unknown> {
261
273
  const form = await req.clone().formData()
262
274
  if (form.has('tenantId')) {
263
275
  const value = form.get('tenantId')
264
- if (value instanceof File) return value.name
276
+ if (value instanceof File) return undefined
265
277
  return value
266
278
  }
267
279
  }