@igstack/app-catalog-backend-core 0.3.1-alpha-20260403020019 → 0.3.1-alpha-20260405015231

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 (83) hide show
  1. package/dist/db/syncAppCatalog.d.mts +11 -1
  2. package/dist/db/syncAppCatalog.d.mts.map +1 -1
  3. package/dist/db/syncAppCatalog.mjs +54 -2
  4. package/dist/db/syncAppCatalog.mjs.map +1 -1
  5. package/dist/db/tableSyncMagazine.d.mts +18 -0
  6. package/dist/db/tableSyncMagazine.d.mts.map +1 -1
  7. package/dist/db/tableSyncMagazine.mjs +18 -0
  8. package/dist/db/tableSyncMagazine.mjs.map +1 -1
  9. package/dist/generated/prisma/client.mjs.map +1 -1
  10. package/dist/generated/prisma/commonInputTypes.d.mts +50 -50
  11. package/dist/generated/prisma/commonInputTypes.d.mts.map +1 -1
  12. package/dist/generated/prisma/enums.d.mts +2 -0
  13. package/dist/generated/prisma/enums.d.mts.map +1 -1
  14. package/dist/generated/prisma/internal/class.d.mts +48 -0
  15. package/dist/generated/prisma/internal/class.d.mts.map +1 -1
  16. package/dist/generated/prisma/internal/class.mjs +4 -4
  17. package/dist/generated/prisma/internal/class.mjs.map +1 -1
  18. package/dist/generated/prisma/internal/prismaNamespace.d.mts +362 -12
  19. package/dist/generated/prisma/internal/prismaNamespace.d.mts.map +1 -1
  20. package/dist/generated/prisma/models/DbAppForCatalog.d.mts +198 -3
  21. package/dist/generated/prisma/models/DbAppForCatalog.d.mts.map +1 -1
  22. package/dist/generated/prisma/models/DbAsset.d.mts +2 -8
  23. package/dist/generated/prisma/models/DbAsset.d.mts.map +1 -1
  24. package/dist/generated/prisma/models/DbGroup.d.mts +1124 -0
  25. package/dist/generated/prisma/models/DbGroup.d.mts.map +1 -0
  26. package/dist/generated/prisma/models/DbGroupMembership.d.mts +1199 -0
  27. package/dist/generated/prisma/models/DbGroupMembership.d.mts.map +1 -0
  28. package/dist/generated/prisma/models/DbPerson.d.mts +1155 -0
  29. package/dist/generated/prisma/models/DbPerson.d.mts.map +1 -0
  30. package/dist/generated/prisma/models/DbSubResource.d.mts +1468 -0
  31. package/dist/generated/prisma/models/DbSubResource.d.mts.map +1 -0
  32. package/dist/generated/prisma/models/SourceReference.d.mts +1 -1
  33. package/dist/generated/prisma/models.d.mts +6 -2
  34. package/dist/index.d.mts +5 -3
  35. package/dist/middleware/featureRegistry.mjs +5 -1
  36. package/dist/middleware/featureRegistry.mjs.map +1 -1
  37. package/dist/modules/appCatalog/checkLinks.d.mts.map +1 -1
  38. package/dist/modules/appCatalog/checkLinks.mjs +31 -2
  39. package/dist/modules/appCatalog/checkLinks.mjs.map +1 -1
  40. package/dist/modules/appCatalog/service.mjs +52 -5
  41. package/dist/modules/appCatalog/service.mjs.map +1 -1
  42. package/dist/modules/auth/registerAuthRoutes.mjs +5 -1
  43. package/dist/modules/auth/registerAuthRoutes.mjs.map +1 -1
  44. package/dist/modules/lighthouseKeeper/tools.d.mts +1 -1
  45. package/dist/modules/lighthouseKeeper/tools.mjs +1 -1
  46. package/dist/modules/lighthouseKeeper/tools.mjs.map +1 -1
  47. package/dist/types/common/appCatalogTypes.d.mts +19 -1
  48. package/dist/types/common/appCatalogTypes.d.mts.map +1 -1
  49. package/dist/types/common/approvalMethodTypes.d.mts +52 -36
  50. package/dist/types/common/approvalMethodTypes.d.mts.map +1 -1
  51. package/dist/types/common/personGroupTypes.d.mts +22 -0
  52. package/dist/types/common/personGroupTypes.d.mts.map +1 -0
  53. package/dist/types/common/subResourceTypes.d.mts +24 -0
  54. package/dist/types/common/subResourceTypes.d.mts.map +1 -0
  55. package/package.json +3 -3
  56. package/prisma/schema.prisma +59 -0
  57. package/src/db/syncAppCatalog.ts +73 -1
  58. package/src/db/tableSyncMagazine.ts +18 -0
  59. package/src/generated/prisma/browser.ts +20 -0
  60. package/src/generated/prisma/client.ts +20 -0
  61. package/src/generated/prisma/commonInputTypes.ts +54 -54
  62. package/src/generated/prisma/enums.ts +3 -1
  63. package/src/generated/prisma/internal/class.ts +44 -4
  64. package/src/generated/prisma/internal/prismaNamespace.ts +373 -15
  65. package/src/generated/prisma/internal/prismaNamespaceBrowser.ts +58 -0
  66. package/src/generated/prisma/models/DbAppForCatalog.ts +208 -1
  67. package/src/generated/prisma/models/DbAsset.ts +0 -8
  68. package/src/generated/prisma/models/DbGroup.ts +1324 -0
  69. package/src/generated/prisma/models/DbGroupMembership.ts +1432 -0
  70. package/src/generated/prisma/models/DbPerson.ts +1356 -0
  71. package/src/generated/prisma/models/DbSubResource.ts +1692 -0
  72. package/src/generated/prisma/models.ts +4 -0
  73. package/src/middleware/featureRegistry.ts +4 -1
  74. package/src/modules/appCatalog/checkLinks.ts +58 -5
  75. package/src/modules/appCatalog/service.ts +80 -6
  76. package/src/modules/auth/registerAuthRoutes.ts +4 -1
  77. package/src/modules/lighthouseKeeper/tools.ts +1 -1
  78. package/src/prisma-json-types.d.ts +6 -0
  79. package/src/types/common/appCatalogTypes.ts +23 -0
  80. package/src/types/common/approvalMethodTypes.ts +59 -57
  81. package/src/types/common/personGroupTypes.ts +20 -0
  82. package/src/types/common/subResourceTypes.ts +20 -0
  83. package/src/types/index.ts +2 -0
@@ -1 +1 @@
1
- {"version":3,"file":"tools.mjs","names":[],"sources":["../../../src/modules/lighthouseKeeper/tools.ts"],"sourcesContent":["import type { Tool } from 'ai'\nimport { z } from 'zod'\nimport { PrismaClient } from '../../generated/prisma/client'\nimport { PrismaPg } from '@prisma/adapter-pg'\nimport pg from 'pg'\nimport type { AcDatabaseConfig } from '../../middleware/types.js'\n\n// ============================================================================\n// Database URL Helper\n// ============================================================================\n\nfunction getDatabaseUrl(config: AcDatabaseConfig): string {\n if ('url' in config) return config.url\n const { host, port, database, username, password, schema } = config\n const schemaParam = schema ? `?schema=${schema}` : ''\n return `postgresql://${username}:${password}@${host}:${port}/${database}${schemaParam}`\n}\n\n// ============================================================================\n// AI Tools for App Catalog\n// ============================================================================\n\n/**\n * Create AI tools for working with app catalog cards.\n * These tools allow the AI to fetch and inspect app information.\n */\nexport function createAppCatalogAITools(\n databaseConfig: AcDatabaseConfig,\n): Record<string, Tool> {\n const databaseUrl = getDatabaseUrl(databaseConfig)\n const pool = new pg.Pool({ connectionString: databaseUrl })\n const adapter = new PrismaPg(pool)\n const prisma = new PrismaClient({ adapter })\n\n const getAppCardSchema = z.object({\n slug: z.string().describe('The app slug to fetch'),\n })\n\n type GetAppCardInput = z.infer<typeof getAppCardSchema>\n\n const getAppCard: Tool<GetAppCardInput, unknown> = {\n description:\n 'Fetch complete app catalog card information by ID. Returns title, description, tags, access request details, links, and all other app metadata.',\n inputSchema: getAppCardSchema,\n execute: async ({ slug }: { slug: string }) => {\n try {\n const app = await prisma.dbAppForCatalog.findUnique({\n where: { slug },\n include: {\n sourceRefs: true,\n },\n })\n\n if (!app) {\n return { error: `App not found with slug: ${slug}` }\n }\n\n // Return structured card data\n return {\n success: true,\n card: {\n id: app.id,\n slug: app.slug,\n displayName: app.displayName,\n description: app.description,\n teams: app.teams,\n tags: app.tags,\n appUrl: app.appUrl,\n links: app.links,\n iconName: app.iconName,\n sources: app.sourceRefs.map((ref) => ref.url),\n notes: app.notes,\n accessRequest: app.accessRequest,\n deprecated: app.deprecated,\n createdAt: app.createdAt,\n updatedAt: app.updatedAt,\n },\n }\n } catch (error) {\n return {\n error: error instanceof Error ? error.message : 'Failed to fetch app',\n }\n }\n },\n }\n\n return {\n getAppCard,\n }\n}\n\n// ============================================================================\n// System Prompt\n// ============================================================================\n\n/**\n * Default system prompt for AI working with app catalog cards.\n * Use this when configuring lighthouseKeeper for card updates.\n */\nexport const APP_CATALOG_AI_SYSTEM_PROMPT = `You are an assistant that helps update app catalog cards based on information from provided links.\n\nWhen given a link and an app ID:\n1. Use getAppCard to fetch the current card information\n2. Analyze the provided link for relevant information\n3. Output a new card structure with updated information based on the link\n\nReturn the updated card as a structured JSON object matching the card format:\n- displayName: App title\n- description: Full description\n- tags: Array of tags\n- teams: Array of team names\n- appUrl: Main application URL\n- links: Array of {url, title} objects for related links\n- sources: Array of source URLs (documentation, Confluence pages, etc.)\n- accessRequest: Object with approvalMethodId, comments, requestPrompt, postApprovalInstructions, roles, approvers, urls, whoToReachOut\n- notes: Additional notes\n- deprecated: Optional deprecation info with type, replacementSlug, comment\n\nDo NOT save the card to the database. Only output the updated structure.`\n"],"mappings":";;;;;;AAWA,SAAS,eAAe,QAAkC;AACxD,KAAI,SAAS,OAAQ,QAAO,OAAO;CACnC,MAAM,EAAE,MAAM,MAAM,UAAU,UAAU,UAAU,WAAW;AAE7D,QAAO,gBAAgB,SAAS,GAAG,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG,WAD3C,SAAS,WAAW,WAAW;;;;;;AAYrD,SAAgB,wBACd,gBACsB;CACtB,MAAM,cAAc,eAAe,eAAe;CAGlD,MAAM,SAAS,IAAI,aAAa,EAAE,SADlB,IAAI,SADP,IAAI,GAAG,KAAK,EAAE,kBAAkB,aAAa,CAAC,CACzB,EACS,CAAC;AAsD5C,QAAO,EACL,YA/CiD;EACjD,aACE;EACF,aATuB,EAAE,OAAO,EAChC,MAAM,EAAE,QAAQ,CAAC,SAAS,wBAAwB,EACnD,CAAC;EAQA,SAAS,OAAO,EAAE,WAA6B;AAC7C,OAAI;IACF,MAAM,MAAM,MAAM,OAAO,gBAAgB,WAAW;KAClD,OAAO,EAAE,MAAM;KACf,SAAS,EACP,YAAY,MACb;KACF,CAAC;AAEF,QAAI,CAAC,IACH,QAAO,EAAE,OAAO,4BAA4B,QAAQ;AAItD,WAAO;KACL,SAAS;KACT,MAAM;MACJ,IAAI,IAAI;MACR,MAAM,IAAI;MACV,aAAa,IAAI;MACjB,aAAa,IAAI;MACjB,OAAO,IAAI;MACX,MAAM,IAAI;MACV,QAAQ,IAAI;MACZ,OAAO,IAAI;MACX,UAAU,IAAI;MACd,SAAS,IAAI,WAAW,KAAK,QAAQ,IAAI,IAAI;MAC7C,OAAO,IAAI;MACX,eAAe,IAAI;MACnB,YAAY,IAAI;MAChB,WAAW,IAAI;MACf,WAAW,IAAI;MAChB;KACF;YACM,OAAO;AACd,WAAO,EACL,OAAO,iBAAiB,QAAQ,MAAM,UAAU,uBACjD;;;EAGN,EAIA;;;;;;AAWH,MAAa,+BAA+B"}
1
+ {"version":3,"file":"tools.mjs","names":[],"sources":["../../../src/modules/lighthouseKeeper/tools.ts"],"sourcesContent":["import type { Tool } from 'ai'\nimport { z } from 'zod'\nimport { PrismaClient } from '../../generated/prisma/client'\nimport { PrismaPg } from '@prisma/adapter-pg'\nimport pg from 'pg'\nimport type { AcDatabaseConfig } from '../../middleware/types.js'\n\n// ============================================================================\n// Database URL Helper\n// ============================================================================\n\nfunction getDatabaseUrl(config: AcDatabaseConfig): string {\n if ('url' in config) return config.url\n const { host, port, database, username, password, schema } = config\n const schemaParam = schema ? `?schema=${schema}` : ''\n return `postgresql://${username}:${password}@${host}:${port}/${database}${schemaParam}`\n}\n\n// ============================================================================\n// AI Tools for App Catalog\n// ============================================================================\n\n/**\n * Create AI tools for working with app catalog cards.\n * These tools allow the AI to fetch and inspect app information.\n */\nexport function createAppCatalogAITools(\n databaseConfig: AcDatabaseConfig,\n): Record<string, Tool> {\n const databaseUrl = getDatabaseUrl(databaseConfig)\n const pool = new pg.Pool({ connectionString: databaseUrl })\n const adapter = new PrismaPg(pool)\n const prisma = new PrismaClient({ adapter })\n\n const getAppCardSchema = z.object({\n slug: z.string().describe('The app slug to fetch'),\n })\n\n type GetAppCardInput = z.infer<typeof getAppCardSchema>\n\n const getAppCard: Tool<GetAppCardInput, unknown> = {\n description:\n 'Fetch complete app catalog card information by ID. Returns title, description, tags, access request details, links, and all other app metadata.',\n inputSchema: getAppCardSchema,\n execute: async ({ slug }: { slug: string }) => {\n try {\n const app = await prisma.dbAppForCatalog.findUnique({\n where: { slug },\n include: {\n sourceRefs: true,\n },\n })\n\n if (!app) {\n return { error: `App not found with slug: ${slug}` }\n }\n\n // Return structured card data\n return {\n success: true,\n card: {\n id: app.id,\n slug: app.slug,\n displayName: app.displayName,\n description: app.description,\n teams: app.teams,\n tags: app.tags,\n appUrl: app.appUrl,\n links: app.links,\n iconName: app.iconName,\n sources: app.sourceRefs.map((ref) => ref.url),\n notes: app.notes,\n accessRequest: app.accessRequest,\n deprecated: app.deprecated,\n createdAt: app.createdAt,\n updatedAt: app.updatedAt,\n },\n }\n } catch (error) {\n return {\n error: error instanceof Error ? error.message : 'Failed to fetch app',\n }\n }\n },\n }\n\n return {\n getAppCard,\n }\n}\n\n// ============================================================================\n// System Prompt\n// ============================================================================\n\n/**\n * Default system prompt for AI working with app catalog cards.\n * Use this when configuring lighthouseKeeper for card updates.\n */\nexport const APP_CATALOG_AI_SYSTEM_PROMPT = `You are an assistant that helps update app catalog cards based on information from provided links.\n\nWhen given a link and an app ID:\n1. Use getAppCard to fetch the current card information\n2. Analyze the provided link for relevant information\n3. Output a new card structure with updated information based on the link\n\nReturn the updated card as a structured JSON object matching the card format:\n- displayName: App title\n- description: Full description\n- tags: Array of tags\n- teams: Array of team names\n- appUrl: Main application URL\n- links: Array of {url, title} objects for related links\n- sources: Array of source URLs (documentation, Confluence pages, etc.)\n- accessRequest: Object with approvalMethodSlug, comments, requestPrompt, postApprovalInstructions, roles, approverPersonSlugs, urls\n- notes: Additional notes\n- deprecated: Optional deprecation info with type, replacementSlug, comment\n\nDo NOT save the card to the database. Only output the updated structure.`\n"],"mappings":";;;;;;AAWA,SAAS,eAAe,QAAkC;AACxD,KAAI,SAAS,OAAQ,QAAO,OAAO;CACnC,MAAM,EAAE,MAAM,MAAM,UAAU,UAAU,UAAU,WAAW;AAE7D,QAAO,gBAAgB,SAAS,GAAG,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG,WAD3C,SAAS,WAAW,WAAW;;;;;;AAYrD,SAAgB,wBACd,gBACsB;CACtB,MAAM,cAAc,eAAe,eAAe;CAGlD,MAAM,SAAS,IAAI,aAAa,EAAE,SADlB,IAAI,SADP,IAAI,GAAG,KAAK,EAAE,kBAAkB,aAAa,CAAC,CACzB,EACS,CAAC;AAsD5C,QAAO,EACL,YA/CiD;EACjD,aACE;EACF,aATuB,EAAE,OAAO,EAChC,MAAM,EAAE,QAAQ,CAAC,SAAS,wBAAwB,EACnD,CAAC;EAQA,SAAS,OAAO,EAAE,WAA6B;AAC7C,OAAI;IACF,MAAM,MAAM,MAAM,OAAO,gBAAgB,WAAW;KAClD,OAAO,EAAE,MAAM;KACf,SAAS,EACP,YAAY,MACb;KACF,CAAC;AAEF,QAAI,CAAC,IACH,QAAO,EAAE,OAAO,4BAA4B,QAAQ;AAItD,WAAO;KACL,SAAS;KACT,MAAM;MACJ,IAAI,IAAI;MACR,MAAM,IAAI;MACV,aAAa,IAAI;MACjB,aAAa,IAAI;MACjB,OAAO,IAAI;MACX,MAAM,IAAI;MACV,QAAQ,IAAI;MACZ,OAAO,IAAI;MACX,UAAU,IAAI;MACd,SAAS,IAAI,WAAW,KAAK,QAAQ,IAAI,IAAI;MAC7C,OAAO,IAAI;MACX,eAAe,IAAI;MACnB,YAAY,IAAI;MAChB,WAAW,IAAI;MACf,WAAW,IAAI;MAChB;KACF;YACM,OAAO;AACd,WAAO,EACL,OAAO,iBAAiB,QAAQ,MAAM,UAAU,uBACjD;;;EAGN,EAIA;;;;;;AAWH,MAAa,+BAA+B"}
@@ -1,6 +1,19 @@
1
1
  import { AppAccessRequest, ApprovalMethod } from "./approvalMethodTypes.mjs";
2
+ import { Group, Person } from "./personGroupTypes.mjs";
3
+ import { SubResource } from "./subResourceTypes.mjs";
2
4
 
3
5
  //#region src/types/common/appCatalogTypes.d.ts
6
+ /**
7
+ * A tier variant of an app (e.g., prod/dev environments).
8
+ * Each tier can have its own URL and access process.
9
+ */
10
+ interface AppTierVariant {
11
+ tierSlug: string;
12
+ displayName?: string;
13
+ description?: string;
14
+ appUrl?: string;
15
+ accessRequest?: AppAccessRequest;
16
+ }
4
17
  /**
5
18
  * Source reference with metadata (used in API responses)
6
19
  * Note: parseDate is string (ISO-8601) when serialized from API, null when not yet parsed
@@ -41,6 +54,8 @@ interface AppForCatalog {
41
54
  aiPrompt?: string;
42
55
  /** URL health issues detected by automated scanning */
43
56
  urlIssues?: string[];
57
+ /** Optional tier variants (e.g., prod/dev) with per-tier URLs and access */
58
+ tiers?: AppTierVariant[];
44
59
  }
45
60
  interface AppCategory {
46
61
  id: string;
@@ -72,8 +87,11 @@ interface AppCatalogData {
72
87
  apps: AppForCatalog[];
73
88
  tagsDefinitions: GroupingTagDefinition[];
74
89
  approvalMethods: AppApprovalMethod[];
90
+ persons: Person[];
91
+ groups: Group[];
92
+ subResources: SubResource[];
75
93
  versions?: AppVersionInfo;
76
94
  }
77
95
  //#endregion
78
- export { AppApprovalMethod, AppCatalogData, AppCategory, AppForCatalog, AppVersionInfo, GroupingTagDefinition, GroupingTagValue, SourceReference, VersionInfo };
96
+ export { AppApprovalMethod, AppCatalogData, AppCategory, AppForCatalog, AppTierVariant, AppVersionInfo, GroupingTagDefinition, GroupingTagValue, SourceReference, VersionInfo };
79
97
  //# sourceMappingURL=appCatalogTypes.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"appCatalogTypes.d.mts","names":[],"sources":["../../../src/types/common/appCatalogTypes.ts"],"mappings":";;;;;;;UAkBiB,eAAA;EACf,UAAA;EACA,GAAA;EACA,SAAA;AAAA;;;;UAMe,aAAA;EACf,EAAA;EACA,IAAA;EACA,WAAA;EACA,YAAA;EACA,SAAA;EACA,WAAA;EACA,KAAA;EACA,aAAA,GAAgB,gBAAA;EAChB,KAAA;EACA,IAAA;EACA,MAAA;EACA,KAAA;IAAU,GAAA;IAAa,KAAA;EAAA;EACvB,QAAA;EACA,aAAA;EACA,OAAA,cAAqB,eAAA;EACrB,UAAA;IAWA,0HATE,IAAA,iCASO;IAPP,eAAA,WAWwB;IATxB,OAAA;EAAA;EAWE;EARJ,QAAA;EAWoC;EATpC,SAAA;AAAA;AAAA,UAIe,WAAA;EACf,EAAA;EACA,IAAA;AAAA;AAAA,UAGe,qBAAA;EACf,MAAA;EACA,WAAA;EACA,WAAA;EACA,MAAA,EAAQ,gBAAA;AAAA;AAAA,KAGL,gBAAA,8BAA8C,CAAA,eAC/C,IAAA,CAAK,CAAA,EAAG,IAAA;AAAA,KAGA,iBAAA,GAAoB,gBAAA,CAC9B,cAAA;AAAA,UAIe,gBAAA;EACf,KAAA;EACA,WAAA;EACA,WAAA;AAAA;AAAA,UAGe,WAAA;EACf,WAAA;EACA,GAAA;AAAA;AAAA,UAGe,cAAA;EACf,OAAA,GAAU,WAAA;EACV,QAAA,GAAW,WAAA;EACX,WAAA,GAAc,WAAA;AAAA;AAAA,UAGC,cAAA;EACf,IAAA,EAAM,aAAA;EACN,eAAA,EAAiB,qBAAA;EACjB,eAAA,EAAiB,iBAAA;EACjB,QAAA,GAAW,cAAA;AAAA"}
1
+ {"version":3,"file":"appCatalogTypes.d.mts","names":[],"sources":["../../../src/types/common/appCatalogTypes.ts"],"mappings":";;;;;;;;;UAoBiB,cAAA;EACf,QAAA;EACA,WAAA;EACA,WAAA;EACA,MAAA;EACA,aAAA,GAAgB,gBAAA;AAAA;;;;;UAWD,eAAA;EACf,UAAA;EACA,GAAA;EACA,SAAA;AAAA;;;;UAMe,aAAA;EACf,EAAA;EACA,IAAA;EACA,WAAA;EACA,YAAA;EACA,SAAA;EACA,WAAA;EACA,KAAA;EACA,aAAA,GAAgB,gBAAA;EAChB,KAAA;EACA,IAAA;EACA,MAAA;EACA,KAAA;IAAU,GAAA;IAAa,KAAA;EAAA;EACvB,QAAA;EACA,aAAA;EACA,OAAA,cAAqB,eAAA;EACrB,UAAA;IAAA,0HAEE,IAAA,iCAEA;IAAA,eAAA,WAKF;IAHE,OAAA;EAAA;EAOM;EAJR,QAAA;EAIsB;EAFtB,SAAA;EAM0B;EAJ1B,KAAA,GAAQ,cAAA;AAAA;AAAA,UAIO,WAAA;EACf,EAAA;EACA,IAAA;AAAA;AAAA,UAGe,qBAAA;EACf,MAAA;EACA,WAAA;EACA,WAAA;EACA,MAAA,EAAQ,gBAAA;AAAA;AAAA,KAGL,gBAAA,8BAA8C,CAAA,eAC/C,IAAA,CAAK,CAAA,EAAG,IAAA;AAAA,KAGA,iBAAA,GAAoB,gBAAA,CAC9B,cAAA;AAAA,UAIe,gBAAA;EACf,KAAA;EACA,WAAA;EACA,WAAA;AAAA;AAAA,UAGe,WAAA;EACf,WAAA;EACA,GAAA;AAAA;AAAA,UAGe,cAAA;EACf,OAAA,GAAU,WAAA;EACV,QAAA,GAAW,WAAA;EACX,WAAA,GAAc,WAAA;AAAA;AAAA,UAGC,cAAA;EACf,IAAA,EAAM,aAAA;EACN,eAAA,EAAiB,qBAAA;EACjB,eAAA,EAAiB,iBAAA;EACjB,OAAA,EAAS,MAAA;EACT,MAAA,EAAQ,KAAA;EACR,YAAA,EAAc,WAAA;EACd,QAAA,GAAW,cAAA;AAAA"}
@@ -3,16 +3,9 @@
3
3
  * Approval Method Types
4
4
  *
5
5
  * Global approval method templates that apps can link to.
6
- * Each method has a type (service, personTeam, custom) with type-specific config.
6
+ * Each method has a type (service, custom, noAccessRequired, unknown) with type-specific config.
7
7
  */
8
- type ApprovalMethodType = 'service' | 'personTeam' | 'custom';
9
- /**
10
- * Contact for reaching out (not necessarily the approver)
11
- */
12
- interface ReachOutContact {
13
- displayName: string;
14
- contact: string;
15
- }
8
+ type ApprovalMethodType = 'service' | 'personTeam' | 'custom' | 'noAccessRequired' | 'unknown';
16
9
  /**
17
10
  * Service type config - for bots, ticketing systems, self-service portals
18
11
  */
@@ -21,10 +14,11 @@ interface ServiceConfig {
21
14
  icon?: string;
22
15
  }
23
16
  /**
24
- * Person/Team type config - for human approvers
17
+ * PersonTeam type config - for person/group-based approval
25
18
  */
26
19
  interface PersonTeamConfig {
27
- reachOutContacts?: ReachOutContact[];
20
+ personSlugs?: string[];
21
+ groupSlugs?: string[];
28
22
  }
29
23
  /**
30
24
  * Custom type config - generic, no additional fields
@@ -39,7 +33,13 @@ type ApprovalMethodConfig = ServiceConfig | PersonTeamConfig | CustomConfig;
39
33
  */
40
34
  type ApprovalMethod = {
41
35
  slug: string;
42
- displayName: string; /** Old/migrated URLs that map to this approval method (e.g., jira.natera.com → natera.atlassian.net) */
36
+ /**
37
+ * Displayed approval method
38
+ */
39
+ displayName: string;
40
+ /**
41
+ * Optionally - older name of approval method if there were migration in organization.
42
+ */
43
43
  deprecatedAliases?: string[];
44
44
  createdAt?: Date;
45
45
  updatedAt?: Date;
@@ -52,22 +52,30 @@ type ApprovalMethod = {
52
52
  } | {
53
53
  type: 'custom';
54
54
  config: CustomConfig;
55
+ } | {
56
+ type: 'noAccessRequired';
57
+ config: CustomConfig;
58
+ } | {
59
+ type: 'unknown';
60
+ config: CustomConfig;
55
61
  });
56
62
  /**
57
63
  * Role that can be requested for an app
58
64
  */
59
65
  interface AppRole {
66
+ /**
67
+ * User-friendly role name.
68
+ */
60
69
  displayName: string;
70
+ /**
71
+ * Description of role.
72
+ */
61
73
  description?: string;
74
+ /**
75
+ * Notes for admins/approvers (Not for requestores)
76
+ */
62
77
  adminNotes?: string;
63
78
  }
64
- /**
65
- * Approver contact (person who approves, may differ from reach-out contact)
66
- */
67
- interface ApproverContact {
68
- displayName: string;
69
- contact?: string;
70
- }
71
79
  /**
72
80
  * URL link with optional label
73
81
  */
@@ -76,30 +84,38 @@ interface ApprovalUrl {
76
84
  url: string;
77
85
  }
78
86
  /**
79
- * Per-app approval details - stored as JSON in DbAppForCatalog
80
- * All comment/text-like strings are markdown
87
+ * Used to store ONLY instructions related to access request
81
88
  */
82
89
  interface AppAccessRequest {
83
- approvalMethodId: string;
90
+ /**
91
+ * Method of asking for access.
92
+ */
93
+ approvalMethodSlug: string;
94
+ /**
95
+ * Additional comments, if no other fields are fit.
96
+ */
84
97
  comments?: string;
98
+ /**
99
+ * A template to put into a request ask.
100
+ */
85
101
  requestPrompt?: string;
102
+ /**
103
+ * Recommended steps post approvel to get access to specific resources.
104
+ */
86
105
  postApprovalInstructions?: string;
106
+ /**
107
+ * Available roles for given resource.
108
+ */
87
109
  roles?: AppRole[];
88
- approvers?: ApproverContact[];
110
+ /**
111
+ * Individuals that will approve request within given approval method. No need to reach them directly unless specified.
112
+ */
113
+ approverPersonSlugs?: string[];
114
+ /**
115
+ * Additional instructions to get approvals
116
+ */
89
117
  urls?: ApprovalUrl[];
90
- whoToReachOut?: string;
91
- }
92
- interface CreateApprovalMethodInput {
93
- type: ApprovalMethodType;
94
- displayName: string;
95
- config?: ApprovalMethodConfig;
96
- }
97
- interface UpdateApprovalMethodInput {
98
- id: string;
99
- type?: ApprovalMethodType;
100
- displayName?: string;
101
- config?: ApprovalMethodConfig;
102
118
  }
103
119
  //#endregion
104
- export { AppAccessRequest, AppRole, ApprovalMethod, ApprovalMethodConfig, ApprovalMethodType, ApprovalUrl, ApproverContact, CreateApprovalMethodInput, CustomConfig, PersonTeamConfig, ReachOutContact, ServiceConfig, UpdateApprovalMethodInput };
120
+ export { AppAccessRequest, AppRole, ApprovalMethod, ApprovalMethodConfig, ApprovalMethodType, ApprovalUrl, CustomConfig, PersonTeamConfig, ServiceConfig };
105
121
  //# sourceMappingURL=approvalMethodTypes.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"approvalMethodTypes.d.mts","names":[],"sources":["../../../src/types/common/approvalMethodTypes.ts"],"mappings":";;AAWA;;;;;KAAY,kBAAA;;;;UAKK,eAAA;EACf,WAAA;EACA,OAAA;AAAA;;;AAcF;UARiB,aAAA;EACf,GAAA;EACA,IAAA;AAAA;AAaF;;;AAAA,UAPiB,gBAAA;EACf,gBAAA,GAAmB,eAAA;AAAA;;;;UAMJ,YAAA;;;;KAOL,oBAAA,GACR,aAAA,GACA,gBAAA,GACA,YAAA;;;;KAcQ,cAAA;EACV,IAAA;EACA,WAAA,UAGY;EADZ,iBAAA;EACA,SAAA,GAAY,IAAA;EACZ,SAAA,GAAY,IAAA;AAAA;EAGR,IAAA;EACA,MAAA,EAAQ,aAAA;AAAA;EAGR,IAAA;EACA,MAAA,EAAQ,gBAAA;AAAA;EAGR,IAAA;EACA,MAAA,EAAQ,YAAA;AAAA;;;;UAWG,OAAA;EACf,WAAA;EACA,WAAA;EACA,UAAA;AAAA;;;;UAMe,eAAA;EACf,WAAA;EACA,OAAA;AAAA;;;;UAMe,WAAA;EACf,KAAA;EACA,GAAA;AAAA;;;;AAFF;UASiB,gBAAA;EACf,gBAAA;EAGA,QAAA;EACA,aAAA;EACA,wBAAA;EAGA,KAAA,GAAQ,OAAA;EACR,SAAA,GAAY,eAAA;EACZ,IAAA,GAAO,WAAA;EAGP,aAAA;AAAA;AAAA,UAOe,yBAAA;EACf,IAAA,EAAM,kBAAA;EACN,WAAA;EACA,MAAA,GAAS,oBAAA;AAAA;AAAA,UAGM,yBAAA;EACf,EAAA;EACA,IAAA,GAAO,kBAAA;EACP,WAAA;EACA,MAAA,GAAS,oBAAA;AAAA"}
1
+ {"version":3,"file":"approvalMethodTypes.d.mts","names":[],"sources":["../../../src/types/common/approvalMethodTypes.ts"],"mappings":";;AAWA;;;;;KAAY,kBAAA;;;;UAUK,aAAA;EACf,GAAA;EACA,IAAA;AAAA;;;AAcF;UARiB,gBAAA;EACf,WAAA;EACA,UAAA;AAAA;AAaF;;;AAAA,UAPiB,YAAA;;;;KAOL,oBAAA,GACR,aAAA,GACA,gBAAA,GACA,YAAA;;;;KAKQ,cAAA;EACV,IAAA;EADwB;;;EAKxB,WAAA;EAUY;;;EANZ,iBAAA;EACA,SAAA,GAAY,IAAA;EACZ,SAAA,GAAY,IAAA;AAAA;EAGR,IAAA;EACA,MAAA,EAAQ,aAAA;AAAA;EAGR,IAAA;EACA,MAAA,EAAQ,gBAAA;AAAA;EAGR,IAAA;EACA,MAAA,EAAQ,YAAA;AAAA;EAGR,IAAA;EACA,MAAA,EAAQ,YAAA;AAAA;EAGR,IAAA;EACA,MAAA,EAAQ,YAAA;AAAA;;;;UAWG,OAAA;EAZX;;;EAgBJ,WAAA;EAfwB;AAW1B;;EAQE,WAAA;EARsB;;;EAYtB,UAAA;AAAA;;AAMF;;UAAiB,WAAA;EACf,KAAA;EACA,GAAA;AAAA;;;;UAMe,gBAAA;EASf;;;EALA,kBAAA;EAkBQ;;;EAbR,QAAA;EAsBkB;;;EAlBlB,aAAA;;;;EAIA,wBAAA;;;;EAKA,KAAA,GAAQ,OAAA;;;;EAKR,mBAAA;;;;EAIA,IAAA,GAAO,WAAA;AAAA"}
@@ -0,0 +1,22 @@
1
+ //#region src/types/common/personGroupTypes.d.ts
2
+ /**
3
+ * Person & Group Types
4
+ *
5
+ * Persons represent individuals (employees, contacts).
6
+ * Groups represent named sets of persons (teams, distribution lists).
7
+ */
8
+ interface Person {
9
+ slug: string;
10
+ firstName: string;
11
+ lastName: string;
12
+ email?: string;
13
+ }
14
+ interface Group {
15
+ slug: string;
16
+ displayName?: string;
17
+ email?: string;
18
+ memberSlugs: string[];
19
+ }
20
+ //#endregion
21
+ export { Group, Person };
22
+ //# sourceMappingURL=personGroupTypes.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"personGroupTypes.d.mts","names":[],"sources":["../../../src/types/common/personGroupTypes.ts"],"mappings":";;AAOA;;;;;UAAiB,MAAA;EACf,IAAA;EACA,SAAA;EACA,QAAA;EACA,KAAA;AAAA;AAAA,UAGe,KAAA;EACf,IAAA;EACA,WAAA;EACA,KAAA;EACA,WAAA;AAAA"}
@@ -0,0 +1,24 @@
1
+ import { AppAccessRequest } from "./approvalMethodTypes.mjs";
2
+
3
+ //#region src/types/common/subResourceTypes.d.ts
4
+ /**
5
+ * A sub-resource within an app.
6
+ * Example: an AWS account under the "AWS Console" app.
7
+ */
8
+ interface SubResource {
9
+ slug: string;
10
+ displayName: string;
11
+ description?: string;
12
+ appSlug: string;
13
+ familySlug?: string;
14
+ tierSlug?: string;
15
+ aliases: string[];
16
+ ownerPersonSlug?: string;
17
+ accessMaintainerGroupSlugs: string[];
18
+ accessRequest?: AppAccessRequest;
19
+ accessComments?: string;
20
+ extra?: Record<string, unknown>;
21
+ }
22
+ //#endregion
23
+ export { SubResource };
24
+ //# sourceMappingURL=subResourceTypes.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subResourceTypes.d.mts","names":[],"sources":["../../../src/types/common/subResourceTypes.ts"],"mappings":";;;;;AAMA;;UAAiB,WAAA;EACf,IAAA;EACA,WAAA;EACA,WAAA;EACA,OAAA;EACA,UAAA;EACA,QAAA;EACA,OAAA;EACA,eAAA;EACA,0BAAA;EACA,aAAA,GAAgB,gBAAA;EAChB,cAAA;EACA,KAAA,GAAQ,MAAA;AAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@igstack/app-catalog-backend-core",
3
- "version": "0.3.1-alpha-20260403020019",
3
+ "version": "0.3.1-alpha-20260405015231",
4
4
  "description": "Backend core library for App Catalog",
5
5
  "homepage": "https://github.com/lislon/app-catalog",
6
6
  "repository": {
@@ -45,8 +45,8 @@
45
45
  "tsyringe": "^4.10.0",
46
46
  "yaml": "^2.8.0",
47
47
  "zod": "^4.3.5",
48
- "@igstack/app-catalog-shared-core": "0.3.1-alpha-20260403020019",
49
- "@igstack/app-catalog-table-sync": "0.3.1-alpha-20260403020019"
48
+ "@igstack/app-catalog-shared-core": "0.3.1-alpha-20260405015231",
49
+ "@igstack/app-catalog-table-sync": "0.3.1-alpha-20260405015231"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@tanstack/vite-config": "^0.4.3",
@@ -76,6 +76,39 @@ enum ApprovalMethodType {
76
76
  service
77
77
  personTeam
78
78
  custom
79
+ noAccessRequired
80
+ unknown
81
+ }
82
+
83
+ // ========== Person & Group Models ==========
84
+
85
+ model DbPerson {
86
+ slug String @id // email or synthetic
87
+ firstName String
88
+ lastName String
89
+ email String? @unique
90
+ memberships DbGroupMembership[]
91
+ createdAt DateTime @default(now())
92
+ updatedAt DateTime @updatedAt
93
+ }
94
+
95
+ model DbGroup {
96
+ slug String @id
97
+ displayName String?
98
+ email String? // team alias
99
+ memberships DbGroupMembership[]
100
+ createdAt DateTime @default(now())
101
+ updatedAt DateTime @updatedAt
102
+ }
103
+
104
+ model DbGroupMembership {
105
+ id Int @id @default(autoincrement())
106
+ groupSlug String
107
+ group DbGroup @relation(fields: [groupSlug], references: [slug], onDelete: Cascade)
108
+ personSlug String
109
+ person DbPerson @relation(fields: [personSlug], references: [slug], onDelete: Cascade)
110
+
111
+ @@unique([groupSlug, personSlug])
79
112
  }
80
113
 
81
114
  model DbApprovalMethod {
@@ -114,7 +147,10 @@ model DbAppForCatalog {
114
147
  deprecated Json?
115
148
  aiPrompt String?
116
149
  urlIssues String[] @default([])
150
+ /// [AppTierVariant[]]
151
+ tiers Json?
117
152
  sourceRefs SourceReference[]
153
+ subResources DbSubResource[]
118
154
  createdAt DateTime @default(now())
119
155
  updatedAt DateTime @updatedAt
120
156
 
@@ -123,6 +159,29 @@ model DbAppForCatalog {
123
159
  @@index([tags])
124
160
  }
125
161
 
162
+ model DbSubResource {
163
+ id String @id @default(cuid())
164
+ slug String @unique
165
+ displayName String
166
+ description String?
167
+ appSlug String
168
+ app DbAppForCatalog @relation(fields: [appSlug], references: [slug], onDelete: Cascade)
169
+ familySlug String? // groups tier variants visually
170
+ tierSlug String?
171
+ aliases String[] @default([])
172
+ ownerPersonSlug String?
173
+ accessMaintainerGroupSlugs String[] @default([])
174
+ /// [AppAccessRequest]
175
+ accessRequest Json?
176
+ accessComments String?
177
+ /// [SubResourceExtra]
178
+ extra Json?
179
+ createdAt DateTime @default(now())
180
+ updatedAt DateTime @updatedAt
181
+
182
+ @@index([appSlug])
183
+ }
184
+
126
185
  model DbAppTagDefinition {
127
186
  id String @id @default(cuid())
128
187
  prefix String @unique
@@ -8,7 +8,7 @@ import { tableSyncPrisma } from './tableSyncPrismaAdapter'
8
8
  import { readFile, readdir, stat } from 'node:fs/promises'
9
9
  import { group } from 'radashi'
10
10
  import { upsertAsset } from '../modules/assets/upsertAsset'
11
- import type { ApprovalMethod } from '../types'
11
+ import type { ApprovalMethod, Group, Person, SubResource } from '../types'
12
12
  import type { PrismaClient } from '../generated/prisma/client'
13
13
  import { naturalSort } from '../utils/naturalSort'
14
14
  import { parseSourceSlug } from '../utils/parseSourceSlug'
@@ -165,6 +165,15 @@ async function syncAssetsFromFileSystem(
165
165
  }
166
166
  }
167
167
 
168
+ /**
169
+ * Optional data to sync alongside the core app catalog.
170
+ */
171
+ export interface SyncAppCatalogOptions {
172
+ persons?: Person[]
173
+ groups?: Group[]
174
+ subResources?: SubResource[]
175
+ }
176
+
168
177
  /**
169
178
  * Syncs app catalog data to the database using table sync.
170
179
  * This will create new apps, update existing ones, and delete any that are no longer in the input.
@@ -176,10 +185,50 @@ export async function syncAppCatalog(
176
185
  tagsDefinitions: GroupingTagDefinition[],
177
186
  approvalMethods: ApprovalMethod[],
178
187
  sreenshotsPath?: string,
188
+ options?: SyncAppCatalogOptions,
179
189
  ): Promise<SyncAppCatalogResult> {
180
190
  try {
181
191
  const prisma = getDbClient()
182
192
 
193
+ // Sync Persons first (groups depend on persons via memberships)
194
+ if (options?.persons) {
195
+ const dbPersons = options.persons.map((p) => ({
196
+ slug: p.slug,
197
+ firstName: p.firstName,
198
+ lastName: p.lastName,
199
+ email: p.email ?? null,
200
+ }))
201
+ await tableSyncPrisma({
202
+ prisma,
203
+ ...TABLE_SYNC_MAGAZINE.DbPerson,
204
+ }).sync(dbPersons)
205
+ }
206
+
207
+ // Sync Groups (without memberships first)
208
+ if (options?.groups) {
209
+ const dbGroups = options.groups.map((g) => ({
210
+ slug: g.slug,
211
+ displayName: g.displayName ?? null,
212
+ email: g.email ?? null,
213
+ }))
214
+ await tableSyncPrisma({
215
+ prisma,
216
+ ...TABLE_SYNC_MAGAZINE.DbGroup,
217
+ }).sync(dbGroups)
218
+
219
+ // Now sync GroupMemberships
220
+ const allMemberships = options.groups.flatMap((g) =>
221
+ g.memberSlugs.map((personSlug) => ({
222
+ groupSlug: g.slug,
223
+ personSlug,
224
+ })),
225
+ )
226
+ await tableSyncPrisma({
227
+ prisma,
228
+ ...TABLE_SYNC_MAGAZINE.DbGroupMembership,
229
+ }).sync(allMemberships)
230
+ }
231
+
183
232
  await tableSyncPrisma({
184
233
  prisma,
185
234
  ...TABLE_SYNC_MAGAZINE.DbApprovalMethod,
@@ -241,6 +290,7 @@ export async function syncAppCatalog(
241
290
  deprecated: app.deprecated ?? null,
242
291
  aiPrompt: app.aiPrompt ?? null,
243
292
  urlIssues: app.urlIssues ?? [],
293
+ tiers: app.tiers ?? null,
244
294
  }
245
295
  })
246
296
 
@@ -290,6 +340,28 @@ export async function syncAppCatalog(
290
340
  ...TABLE_SYNC_MAGAZINE.SourceReference,
291
341
  }).sync(allSourceRefs)
292
342
 
343
+ // Sync SubResources (after apps, since they reference appSlug)
344
+ if (options?.subResources) {
345
+ const dbSubResources = options.subResources.map((sr) => ({
346
+ slug: sr.slug,
347
+ displayName: sr.displayName,
348
+ description: sr.description ?? null,
349
+ appSlug: sr.appSlug,
350
+ familySlug: sr.familySlug ?? null,
351
+ tierSlug: sr.tierSlug ?? null,
352
+ aliases: sr.aliases,
353
+ ownerPersonSlug: sr.ownerPersonSlug ?? null,
354
+ accessMaintainerGroupSlugs: sr.accessMaintainerGroupSlugs,
355
+ accessRequest: sr.accessRequest ?? null,
356
+ accessComments: sr.accessComments ?? null,
357
+ extra: sr.extra ?? null,
358
+ }))
359
+ await tableSyncPrisma({
360
+ prisma,
361
+ ...TABLE_SYNC_MAGAZINE.DbSubResource,
362
+ }).sync(dbSubResources)
363
+ }
364
+
293
365
  // Get actual synced data to calculate stats
294
366
  const actual = result.getActual()
295
367
 
@@ -13,6 +13,20 @@ type TableSyncMagazineType = Partial<{
13
13
  }>
14
14
 
15
15
  export const TABLE_SYNC_MAGAZINE = {
16
+ DbPerson: {
17
+ id: 'slug',
18
+ prismaModelName: 'DbPerson',
19
+ uniqColumns: ['slug'],
20
+ },
21
+ DbGroup: {
22
+ id: 'slug',
23
+ prismaModelName: 'DbGroup',
24
+ uniqColumns: ['slug'],
25
+ },
26
+ DbGroupMembership: {
27
+ prismaModelName: 'DbGroupMembership',
28
+ uniqColumns: ['groupSlug', 'personSlug'],
29
+ },
16
30
  DbAppForCatalog: {
17
31
  prismaModelName: 'DbAppForCatalog',
18
32
  uniqColumns: ['slug'],
@@ -31,6 +45,10 @@ export const TABLE_SYNC_MAGAZINE = {
31
45
  prismaModelName: 'Source',
32
46
  uniqColumns: ['slug'],
33
47
  },
48
+ DbSubResource: {
49
+ prismaModelName: 'DbSubResource',
50
+ uniqColumns: ['slug'],
51
+ },
34
52
  SourceReference: {
35
53
  prismaModelName: 'SourceReference',
36
54
  uniqColumns: ['appId', 'url'],
@@ -37,6 +37,21 @@ export type account = Prisma.accountModel
37
37
  *
38
38
  */
39
39
  export type verification = Prisma.verificationModel
40
+ /**
41
+ * Model DbPerson
42
+ *
43
+ */
44
+ export type DbPerson = Prisma.DbPersonModel
45
+ /**
46
+ * Model DbGroup
47
+ *
48
+ */
49
+ export type DbGroup = Prisma.DbGroupModel
50
+ /**
51
+ * Model DbGroupMembership
52
+ *
53
+ */
54
+ export type DbGroupMembership = Prisma.DbGroupMembershipModel
40
55
  /**
41
56
  * Model DbApprovalMethod
42
57
  *
@@ -47,6 +62,11 @@ export type DbApprovalMethod = Prisma.DbApprovalMethodModel
47
62
  *
48
63
  */
49
64
  export type DbAppForCatalog = Prisma.DbAppForCatalogModel
65
+ /**
66
+ * Model DbSubResource
67
+ *
68
+ */
69
+ export type DbSubResource = Prisma.DbSubResourceModel
50
70
  /**
51
71
  * Model DbAppTagDefinition
52
72
  *
@@ -61,6 +61,21 @@ export type account = Prisma.accountModel
61
61
  *
62
62
  */
63
63
  export type verification = Prisma.verificationModel
64
+ /**
65
+ * Model DbPerson
66
+ *
67
+ */
68
+ export type DbPerson = Prisma.DbPersonModel
69
+ /**
70
+ * Model DbGroup
71
+ *
72
+ */
73
+ export type DbGroup = Prisma.DbGroupModel
74
+ /**
75
+ * Model DbGroupMembership
76
+ *
77
+ */
78
+ export type DbGroupMembership = Prisma.DbGroupMembershipModel
64
79
  /**
65
80
  * Model DbApprovalMethod
66
81
  *
@@ -71,6 +86,11 @@ export type DbApprovalMethod = Prisma.DbApprovalMethodModel
71
86
  *
72
87
  */
73
88
  export type DbAppForCatalog = Prisma.DbAppForCatalogModel
89
+ /**
90
+ * Model DbSubResource
91
+ *
92
+ */
93
+ export type DbSubResource = Prisma.DbSubResourceModel
74
94
  /**
75
95
  * Model DbAppTagDefinition
76
96
  *