spine-framework 0.3.58 → 0.3.60

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.
@@ -309,7 +309,8 @@ interface SpineConfig {
309
309
  default_role?: string
310
310
  allow_url_override?: boolean
311
311
  apps?: Record<string, {
312
- role: string
312
+ roles: string[]
313
+ default_role: string
313
314
  path: string
314
315
  enabled: boolean
315
316
  }>
@@ -344,9 +345,10 @@ function updateRegistrationConfig(appSlug: string, regConfig: RegistrationConfig
344
345
  config.registration.apps = {}
345
346
  }
346
347
 
347
- // Add/update this app's registration entry
348
+ // Add/update this app's registration entry with multi-role support
348
349
  config.registration.apps[appSlug] = {
349
- role: regConfig.default_role,
350
+ roles: [regConfig.default_role], // Start with default role from manifest
351
+ default_role: regConfig.default_role,
350
352
  path: regConfig.redirect_path,
351
353
  enabled: regConfig.enabled,
352
354
  }
@@ -214,6 +214,7 @@ export const validateToken = createHandler(async (_ctx, _body) => {
214
214
  */
215
215
  export const completeRegistration = createHandler(async (ctx, body) => {
216
216
  const { path, account_name, email, role_slug } = body
217
+ console.log('completeRegistration called with:', { path, account_name, email, role_slug })
217
218
 
218
219
  if (!path || !email) {
219
220
  throw new Error('path and email are required')
@@ -240,27 +241,33 @@ export const completeRegistration = createHandler(async (ctx, body) => {
240
241
 
241
242
  // Resolve role from role_slug param, or fall back to member_admin/member lookup
242
243
  const targetRoleSlug = role_slug || 'member'
244
+ console.log('Looking for role:', targetRoleSlug)
245
+
243
246
  let { data: roles } = await adminDb
244
247
  .from('roles')
245
- .select('id')
248
+ .select('id, slug')
246
249
  .eq('slug', targetRoleSlug)
247
250
  .limit(1)
248
251
 
249
252
  let role = roles?.[0]
253
+ console.log('Found role:', role)
250
254
 
251
255
  // If specific role not found, try member_admin or member as fallback
252
256
  if (!role) {
257
+ console.log('Role not found, trying fallbacks...')
253
258
  const { data: fallbackRoles } = await adminDb
254
259
  .from('roles')
255
- .select('id')
260
+ .select('id, slug')
256
261
  .in('slug', ['member_admin', 'member'])
257
262
  .order('slug')
258
263
  .limit(1)
259
264
  role = fallbackRoles?.[0]
265
+ console.log('Fallback role:', role)
260
266
  }
261
267
 
262
- // If no roles exist yet (apps not installed), create a default member role
263
- if (!role) {
268
+ // If no roles exist yet and no specific role was requested, create a default member role
269
+ // But only if we're not trying to assign a specific app role
270
+ if (!role && !role_slug) {
264
271
  const { data: newRole, error: roleErr } = await adminDb
265
272
  .from('roles')
266
273
  .insert({
@@ -53,7 +53,8 @@ interface RegistrationConfig {
53
53
  default_role: string
54
54
  allow_url_override: boolean
55
55
  apps: Record<string, {
56
- role: string
56
+ roles: string[]
57
+ default_role: string
57
58
  path: string
58
59
  enabled: boolean
59
60
  }>
@@ -237,7 +238,27 @@ export function RegisterPage() {
237
238
  // Determine role from URL params or config
238
239
  const urlRole = searchParams.get('role')
239
240
  const urlApp = searchParams.get('app')
240
- const effectiveRole = urlRole || (urlApp && regConfig?.apps[urlApp]?.role) || regConfig?.default_role || 'member'
241
+ console.log('Role resolution:', { urlRole, urlApp, regConfig })
242
+
243
+ let effectiveRole = regConfig?.default_role || 'member'
244
+
245
+ // If app is specified, use app's default role
246
+ if (urlApp && regConfig?.apps[urlApp]) {
247
+ const appConfig = regConfig.apps[urlApp]
248
+
249
+ // If URL role is provided, validate it against app's available roles
250
+ if (urlRole && appConfig.roles.includes(urlRole)) {
251
+ effectiveRole = urlRole
252
+ } else {
253
+ effectiveRole = appConfig.default_role
254
+ }
255
+ }
256
+ // If only URL role is specified (no app), use it directly
257
+ else if (urlRole) {
258
+ effectiveRole = urlRole
259
+ }
260
+
261
+ console.log('Effective role:', effectiveRole)
241
262
 
242
263
  if (domainMatchChoice === 'join') {
243
264
  // Join existing account as access_request
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spine-framework",
3
- "version": "0.3.58",
3
+ "version": "0.3.60",
4
4
  "description": "Multi-tenant, modular application platform for modern SaaS systems",
5
5
  "type": "module",
6
6
  "bin": {
package/spine.config.json CHANGED
@@ -6,12 +6,14 @@
6
6
  "allow_url_override": true,
7
7
  "apps": {
8
8
  "portal": {
9
- "role": "member",
9
+ "roles": ["member"],
10
+ "default_role": "member",
10
11
  "path": "/portal",
11
12
  "enabled": true
12
13
  },
13
14
  "cortex": {
14
- "role": "support",
15
+ "roles": ["support", "support_admin"],
16
+ "default_role": "support",
15
17
  "path": "/cortex",
16
18
  "enabled": true
17
19
  }