@selvajs/platform 0.14.2 → 0.15.0-beta.1

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 (196) hide show
  1. package/LICENSE +1 -1
  2. package/dist/auth.d.ts +60 -0
  3. package/dist/auth.d.ts.map +1 -0
  4. package/dist/auth.js +12 -0
  5. package/dist/auth.js.map +1 -0
  6. package/dist/compute.d.ts +47 -0
  7. package/dist/compute.d.ts.map +1 -0
  8. package/dist/compute.js +11 -0
  9. package/dist/compute.js.map +1 -0
  10. package/dist/computeServer/index.d.ts +2 -0
  11. package/dist/computeServer/index.d.ts.map +1 -1
  12. package/dist/computeServer/index.js +6 -0
  13. package/dist/computeServer/index.js.map +1 -1
  14. package/dist/computeServer/interface.d.ts +10 -0
  15. package/dist/computeServer/interface.d.ts.map +1 -1
  16. package/dist/computeServer/secrets.d.ts +53 -0
  17. package/dist/computeServer/secrets.d.ts.map +1 -0
  18. package/dist/computeServer/secrets.js +67 -0
  19. package/dist/computeServer/secrets.js.map +1 -0
  20. package/dist/context.d.ts +7 -0
  21. package/dist/context.d.ts.map +1 -1
  22. package/dist/context.js +13 -0
  23. package/dist/context.js.map +1 -1
  24. package/dist/data/interface.d.ts +33 -0
  25. package/dist/data/interface.d.ts.map +1 -1
  26. package/dist/definitions/interface.d.ts +18 -0
  27. package/dist/definitions/interface.d.ts.map +1 -1
  28. package/dist/definitions/schemas.d.ts +1 -0
  29. package/dist/definitions/schemas.d.ts.map +1 -1
  30. package/dist/definitions/schemas.js +3 -0
  31. package/dist/definitions/schemas.js.map +1 -1
  32. package/dist/definitions/service.d.ts +62 -0
  33. package/dist/definitions/service.d.ts.map +1 -0
  34. package/dist/definitions/service.js +149 -0
  35. package/dist/definitions/service.js.map +1 -0
  36. package/dist/definitions/types.d.ts +24 -1
  37. package/dist/definitions/types.d.ts.map +1 -1
  38. package/dist/definitions.d.ts +146 -0
  39. package/dist/definitions.d.ts.map +1 -0
  40. package/dist/definitions.js +23 -0
  41. package/dist/definitions.js.map +1 -0
  42. package/dist/errors/interface.d.ts +44 -0
  43. package/dist/errors/interface.d.ts.map +1 -0
  44. package/dist/errors/interface.js +9 -0
  45. package/dist/errors/interface.js.map +1 -0
  46. package/dist/events/interface.d.ts +23 -0
  47. package/dist/events/interface.d.ts.map +1 -1
  48. package/dist/events/interface.js.map +1 -1
  49. package/dist/index.d.ts +14 -5
  50. package/dist/index.d.ts.map +1 -1
  51. package/dist/index.js +7 -2
  52. package/dist/index.js.map +1 -1
  53. package/dist/invites/schemas.d.ts +24 -0
  54. package/dist/invites/schemas.d.ts.map +1 -0
  55. package/dist/invites/schemas.js +17 -0
  56. package/dist/invites/schemas.js.map +1 -0
  57. package/dist/metrics/interface.d.ts +6 -0
  58. package/dist/metrics/interface.d.ts.map +1 -1
  59. package/dist/metrics/interface.js.map +1 -1
  60. package/dist/organizations/index.d.ts +4 -3
  61. package/dist/organizations/index.d.ts.map +1 -1
  62. package/dist/organizations/index.js +2 -1
  63. package/dist/organizations/index.js.map +1 -1
  64. package/dist/organizations/interface.d.ts +1 -1
  65. package/dist/organizations/interface.d.ts.map +1 -1
  66. package/dist/organizations/paths.d.ts +22 -0
  67. package/dist/organizations/paths.d.ts.map +1 -0
  68. package/dist/organizations/paths.js +43 -0
  69. package/dist/organizations/paths.js.map +1 -0
  70. package/dist/organizations/schemas.d.ts +10 -0
  71. package/dist/organizations/schemas.d.ts.map +1 -1
  72. package/dist/organizations/schemas.js +6 -0
  73. package/dist/organizations/schemas.js.map +1 -1
  74. package/dist/organizations/types.d.ts +10 -1
  75. package/dist/organizations/types.d.ts.map +1 -1
  76. package/dist/organizations.d.ts +93 -0
  77. package/dist/organizations.d.ts.map +1 -0
  78. package/dist/organizations.js +14 -0
  79. package/dist/organizations.js.map +1 -0
  80. package/dist/solveCache/interface.d.ts +86 -0
  81. package/dist/solveCache/interface.d.ts.map +1 -0
  82. package/dist/solveCache/interface.js +12 -0
  83. package/dist/solveCache/interface.js.map +1 -0
  84. package/dist/storage/assetClasses.d.ts +59 -0
  85. package/dist/storage/assetClasses.d.ts.map +1 -0
  86. package/dist/storage/assetClasses.js +86 -0
  87. package/dist/storage/assetClasses.js.map +1 -0
  88. package/dist/storage/cacheBust.d.ts +21 -0
  89. package/dist/storage/cacheBust.d.ts.map +1 -0
  90. package/dist/storage/cacheBust.js +29 -0
  91. package/dist/storage/cacheBust.js.map +1 -0
  92. package/dist/storage/image.d.ts +6 -1
  93. package/dist/storage/image.d.ts.map +1 -1
  94. package/dist/storage/image.js +8 -3
  95. package/dist/storage/image.js.map +1 -1
  96. package/dist/storage/index.d.ts +3 -0
  97. package/dist/storage/index.d.ts.map +1 -1
  98. package/dist/storage/index.js +2 -0
  99. package/dist/storage/index.js.map +1 -1
  100. package/dist/testing/adapterSuite.d.ts +33 -0
  101. package/dist/testing/adapterSuite.d.ts.map +1 -0
  102. package/dist/testing/adapterSuite.js +166 -0
  103. package/dist/testing/adapterSuite.js.map +1 -0
  104. package/dist/testing/suites/definitionStoreSuite.d.ts.map +1 -1
  105. package/dist/testing/suites/definitionStoreSuite.js +87 -0
  106. package/dist/testing/suites/definitionStoreSuite.js.map +1 -1
  107. package/dist/testing/suites/eventSinkSuite.js +1 -0
  108. package/dist/testing/suites/eventSinkSuite.js.map +1 -1
  109. package/dist/testing/suites/orgStoreSuite.d.ts.map +1 -1
  110. package/dist/testing/suites/orgStoreSuite.js +12 -0
  111. package/dist/testing/suites/orgStoreSuite.js.map +1 -1
  112. package/dist/testing/suites/platformPermissionStoreSuite.d.ts +9 -0
  113. package/dist/testing/suites/platformPermissionStoreSuite.d.ts.map +1 -1
  114. package/dist/testing/suites/platformPermissionStoreSuite.js +34 -1
  115. package/dist/testing/suites/platformPermissionStoreSuite.js.map +1 -1
  116. package/dist/testing/suites/runner.d.ts +21 -0
  117. package/dist/testing/suites/runner.d.ts.map +1 -0
  118. package/dist/testing/suites/runner.js +7 -0
  119. package/dist/testing/suites/runner.js.map +1 -0
  120. package/dist/testing/suites/storageProviderSuite.d.ts.map +1 -1
  121. package/dist/testing/suites/storageProviderSuite.js +18 -0
  122. package/dist/testing/suites/storageProviderSuite.js.map +1 -1
  123. package/package.json +9 -24
  124. package/src/access/index.ts +0 -23
  125. package/src/access/rules.ts +0 -276
  126. package/src/auth/index.ts +0 -8
  127. package/src/auth/interface.ts +0 -279
  128. package/src/auth/types.ts +0 -32
  129. package/src/bindings/index.ts +0 -2
  130. package/src/bindings/interface.ts +0 -61
  131. package/src/computeServer/index.ts +0 -17
  132. package/src/computeServer/interface.ts +0 -62
  133. package/src/computeServer/types.ts +0 -74
  134. package/src/computeServer/utils.ts +0 -112
  135. package/src/config.ts +0 -99
  136. package/src/context.ts +0 -66
  137. package/src/data/index.ts +0 -1
  138. package/src/data/interface.ts +0 -70
  139. package/src/definitions/index.ts +0 -26
  140. package/src/definitions/interface.ts +0 -78
  141. package/src/definitions/paths.ts +0 -31
  142. package/src/definitions/schemas.ts +0 -64
  143. package/src/definitions/types.ts +0 -111
  144. package/src/errors.ts +0 -16
  145. package/src/events/audit.ts +0 -67
  146. package/src/events/index.ts +0 -9
  147. package/src/events/interface.ts +0 -102
  148. package/src/index.ts +0 -219
  149. package/src/invites/index.ts +0 -2
  150. package/src/invites/interface.ts +0 -38
  151. package/src/invites/types.ts +0 -39
  152. package/src/metrics/interface.ts +0 -86
  153. package/src/organizations/index.ts +0 -14
  154. package/src/organizations/interface.ts +0 -68
  155. package/src/organizations/schemas.ts +0 -52
  156. package/src/organizations/types.ts +0 -31
  157. package/src/pagination.ts +0 -45
  158. package/src/permissions/index.ts +0 -3
  159. package/src/permissions/interface.ts +0 -60
  160. package/src/permissions/types.ts +0 -21
  161. package/src/platformProjects/index.ts +0 -3
  162. package/src/platformProjects/interface.ts +0 -27
  163. package/src/platformProjects/schemas.ts +0 -13
  164. package/src/platformProjects/types.ts +0 -22
  165. package/src/projects/index.ts +0 -4
  166. package/src/projects/interface.ts +0 -58
  167. package/src/projects/schemas.ts +0 -28
  168. package/src/projects/types.ts +0 -36
  169. package/src/shareLinks/index.ts +0 -5
  170. package/src/shareLinks/interface.ts +0 -35
  171. package/src/shareLinks/schemas.ts +0 -21
  172. package/src/shareLinks/types.ts +0 -34
  173. package/src/storage/image.ts +0 -77
  174. package/src/storage/index.ts +0 -9
  175. package/src/storage/interface.ts +0 -27
  176. package/src/testing/index.ts +0 -47
  177. package/src/testing/suites/authProviderSuite.ts +0 -207
  178. package/src/testing/suites/computeServerStoreSuite.ts +0 -195
  179. package/src/testing/suites/definitionStoreSuite.ts +0 -585
  180. package/src/testing/suites/emailLinkAuthSuite.ts +0 -83
  181. package/src/testing/suites/eventSinkSuite.ts +0 -379
  182. package/src/testing/suites/helpers.ts +0 -87
  183. package/src/testing/suites/inviteStoreSuite.ts +0 -143
  184. package/src/testing/suites/orgStoreSuite.ts +0 -412
  185. package/src/testing/suites/platformPermissionStoreSuite.ts +0 -196
  186. package/src/testing/suites/platformProjectGrantStoreSuite.ts +0 -166
  187. package/src/testing/suites/projectStoreSuite.ts +0 -381
  188. package/src/testing/suites/shareLinkStoreSuite.ts +0 -203
  189. package/src/testing/suites/solveMetricSinkSuite.ts +0 -135
  190. package/src/testing/suites/storageProviderSuite.ts +0 -175
  191. package/src/testing/suites/userProfileStoreSuite.ts +0 -134
  192. package/src/userProfile/index.ts +0 -3
  193. package/src/userProfile/interface.ts +0 -48
  194. package/src/userProfile/types.ts +0 -24
  195. package/src/utils/audit.ts +0 -46
  196. package/src/utils/index.ts +0 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@selvajs/platform",
3
- "version": "0.14.2",
3
+ "version": "0.15.0-beta.1",
4
4
  "description": "Pure TypeScript interfaces for Selva platform providers (auth, definitions, compute)",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -8,106 +8,91 @@
8
8
  },
9
9
  "repository": {
10
10
  "type": "git",
11
- "url": "https://github.com/VektorNode/selva.git",
11
+ "url": "git+https://github.com/VektorNode/selva.git",
12
12
  "directory": "packages/platform"
13
13
  },
14
+ "engines": {
15
+ "node": ">=22.0.0"
16
+ },
14
17
  "type": "module",
15
18
  "main": "./dist/index.js",
16
19
  "types": "./dist/index.d.ts",
17
20
  "exports": {
18
21
  ".": {
19
- "source": "./src/index.ts",
20
22
  "types": "./dist/index.d.ts",
21
23
  "import": "./dist/index.js"
22
24
  },
23
25
  "./auth": {
24
- "source": "./src/auth/index.ts",
25
26
  "types": "./dist/auth/index.d.ts",
26
27
  "import": "./dist/auth/index.js"
27
28
  },
28
29
  "./data": {
29
- "source": "./src/data/index.ts",
30
30
  "types": "./dist/data/index.d.ts",
31
31
  "import": "./dist/data/index.js"
32
32
  },
33
33
  "./storage": {
34
- "source": "./src/storage/index.ts",
35
34
  "types": "./dist/storage/index.d.ts",
36
35
  "import": "./dist/storage/index.js"
37
36
  },
38
37
  "./permissions": {
39
- "source": "./src/permissions/index.ts",
40
38
  "types": "./dist/permissions/index.d.ts",
41
39
  "import": "./dist/permissions/index.js"
42
40
  },
43
41
  "./userProfile": {
44
- "source": "./src/userProfile/index.ts",
45
42
  "types": "./dist/userProfile/index.d.ts",
46
43
  "import": "./dist/userProfile/index.js"
47
44
  },
48
45
  "./projects": {
49
- "source": "./src/projects/index.ts",
50
46
  "types": "./dist/projects/index.d.ts",
51
47
  "import": "./dist/projects/index.js"
52
48
  },
53
49
  "./platformProjects": {
54
- "source": "./src/platformProjects/index.ts",
55
50
  "types": "./dist/platformProjects/index.d.ts",
56
51
  "import": "./dist/platformProjects/index.js"
57
52
  },
58
53
  "./organizations": {
59
- "source": "./src/organizations/index.ts",
60
54
  "types": "./dist/organizations/index.d.ts",
61
55
  "import": "./dist/organizations/index.js"
62
56
  },
63
57
  "./invites": {
64
- "source": "./src/invites/index.ts",
65
58
  "types": "./dist/invites/index.d.ts",
66
59
  "import": "./dist/invites/index.js"
67
60
  },
68
61
  "./shareLinks": {
69
- "source": "./src/shareLinks/index.ts",
70
62
  "types": "./dist/shareLinks/index.d.ts",
71
63
  "import": "./dist/shareLinks/index.js"
72
64
  },
73
65
  "./definitions": {
74
- "source": "./src/definitions/index.ts",
75
66
  "types": "./dist/definitions/index.d.ts",
76
67
  "import": "./dist/definitions/index.js"
77
68
  },
78
69
  "./computeServer": {
79
- "source": "./src/computeServer/index.ts",
80
70
  "types": "./dist/computeServer/index.d.ts",
81
71
  "import": "./dist/computeServer/index.js"
82
72
  },
83
73
  "./access": {
84
- "source": "./src/access/index.ts",
85
74
  "types": "./dist/access/index.d.ts",
86
75
  "import": "./dist/access/index.js"
87
76
  },
88
77
  "./events": {
89
- "source": "./src/events/index.ts",
90
78
  "types": "./dist/events/index.d.ts",
91
79
  "import": "./dist/events/index.js"
92
80
  },
93
81
  "./utils": {
94
- "source": "./src/utils/index.ts",
95
82
  "types": "./dist/utils/index.d.ts",
96
83
  "import": "./dist/utils/index.js"
97
84
  },
98
85
  "./testing": {
99
- "source": "./src/testing/index.ts",
100
86
  "types": "./dist/testing/index.d.ts",
101
87
  "import": "./dist/testing/index.js"
102
88
  }
103
89
  },
104
90
  "files": [
105
- "dist",
106
- "src"
91
+ "dist"
107
92
  ],
108
93
  "dependencies": {
109
94
  "zod": "^4.3.6",
110
- "@selvajs/schemas": "4.6.1"
95
+ "@selvajs/schemas": "^4.7.0-beta.0"
111
96
  },
112
97
  "peerDependencies": {
113
98
  "sharp": "^0.34.0",
@@ -123,8 +108,8 @@
123
108
  },
124
109
  "devDependencies": {
125
110
  "sharp": "^0.34.5",
126
- "typescript": "^5.9.3",
127
- "vitest": "^3.2.6"
111
+ "typescript": "^6.0.3",
112
+ "vitest": "^3.2.7"
128
113
  },
129
114
  "scripts": {
130
115
  "build": "tsc",
@@ -1,23 +0,0 @@
1
- export type {
2
- ProjectAccessInput,
3
- DefinitionAccessInput,
4
- VisibilityChangeInput,
5
- ReclaimAccessInput,
6
- CreateProjectAccessInput,
7
- OwnerRemovalInput,
8
- OwnerRemovalCheck
9
- } from './rules.js';
10
-
11
- export {
12
- canView,
13
- canSolve,
14
- canEdit,
15
- canManage,
16
- canEditProjectSettings,
17
- canChangeVisibilityToPublic,
18
- canEditDefinition,
19
- canReclaim,
20
- canCreateProject,
21
- checkOwnerRemoval,
22
- withAdminBypass
23
- } from './rules.js';
@@ -1,276 +0,0 @@
1
- import type { PlatformPermission } from '../permissions/types.js';
2
- import type { OrgPermission } from '../organizations/schemas.js';
3
- import type { Project, ProjectMember } from '../projects/types.js';
4
- import type { OrgMember } from '../organizations/types.js';
5
- import type { DefinitionRecord } from '../definitions/types.js';
6
- import type { PlatformProjectGrant } from '../platformProjects/types.js';
7
-
8
- /**
9
- * Pure access-control rules — single source of truth for UI gating across
10
- * adapters. Mutating store methods MUST re-enforce the same predicate
11
- * independently (RLS in SQL, code in local/JSON).
12
- *
13
- * `instance_admin` bypass is NOT baked into rule bodies — wrap calls with
14
- * `withAdminBypass` at the call site.
15
- */
16
-
17
- function isInstanceAdmin(platformPermissions: readonly PlatformPermission[]): boolean {
18
- return platformPermissions.includes('instance_admin');
19
- }
20
-
21
- export function withAdminBypass(
22
- platformPermissions: readonly PlatformPermission[],
23
- rule: () => boolean
24
- ): boolean {
25
- if (isInstanceAdmin(platformPermissions)) return true;
26
- return rule();
27
- }
28
-
29
- export interface ProjectAccessInput {
30
- orgPermissions: readonly OrgPermission[];
31
- platformPermissions: readonly PlatformPermission[];
32
- project: Project | null;
33
- member: ProjectMember | null;
34
- orgMember: OrgMember | null;
35
- /**
36
- * `ALLOW_CROSS_ORG_PUBLIC` flag. When false, `public` visibility means
37
- * "everyone in the parent org" rather than "everyone on the instance".
38
- */
39
- allowCrossOrgPublic: boolean;
40
- /**
41
- * `ENABLE_PLATFORM_PROJECTS` flag. When false, every rule treats a
42
- * `platform`-visibility project as inaccessible — even for instance
43
- * admins — so the feature can be hidden silently without deleting data.
44
- */
45
- enablePlatformProjects: boolean;
46
- /**
47
- * Grants for `platform`-visibility projects. Pass an empty array for
48
- * non-platform projects — the rule only consults this for `platform`.
49
- */
50
- platformGrants: readonly PlatformProjectGrant[];
51
- /** `ctx.actingOrgId` — used to match org grants on platform projects. */
52
- actingOrgId: string | null;
53
- /** `ctx.userId` — used to match user grants on platform projects. */
54
- userId: string;
55
- }
56
-
57
- /**
58
- * Authenticated-user view rule. Anonymous access is delivered via share-link
59
- * tokens — the route resolves a valid token before this rule runs.
60
- *
61
- * For `platform` projects: `instance_admin` always passes; otherwise any
62
- * grant (view-only or canSolve) satisfies view access.
63
- */
64
- export function canView(input: ProjectAccessInput): boolean {
65
- const {
66
- project,
67
- member,
68
- orgMember,
69
- allowCrossOrgPublic,
70
- enablePlatformProjects,
71
- platformPermissions,
72
- platformGrants,
73
- actingOrgId,
74
- userId
75
- } = input;
76
- if (!project) return false;
77
-
78
- if (project.visibility === 'platform') {
79
- if (!enablePlatformProjects) return false;
80
- if (isInstanceAdmin(platformPermissions)) return true;
81
- return platformGrants.some(
82
- (g) =>
83
- (g.granteeType === 'user' && g.granteeId === userId) ||
84
- (g.granteeType === 'org' && g.granteeId === actingOrgId)
85
- );
86
- }
87
-
88
- if (project.visibility === 'private') return member !== null;
89
- if (project.visibility === 'org') return orgMember !== null;
90
- if (project.visibility === 'public') return allowCrossOrgPublic ? true : orgMember !== null;
91
- return false;
92
- }
93
-
94
- /**
95
- * For non-platform projects: same as `canView` today — kept distinct for
96
- * future cost gating.
97
- *
98
- * For `platform` projects: `instance_admin` always passes; a view-only grant
99
- * satisfies `canView` but NOT `canSolve` — the grant must have `canSolve=true`.
100
- */
101
- export function canSolve(input: ProjectAccessInput): boolean {
102
- const {
103
- project,
104
- enablePlatformProjects,
105
- platformPermissions,
106
- platformGrants,
107
- actingOrgId,
108
- userId
109
- } = input;
110
- if (!project) return false;
111
-
112
- if (project.visibility === 'platform') {
113
- if (!enablePlatformProjects) return false;
114
- if (isInstanceAdmin(platformPermissions)) return true;
115
- return platformGrants.some(
116
- (g) =>
117
- g.canSolve &&
118
- ((g.granteeType === 'user' && g.granteeId === userId) ||
119
- (g.granteeType === 'org' && g.granteeId === actingOrgId))
120
- );
121
- }
122
-
123
- return canView(input);
124
- }
125
-
126
- /**
127
- * Platform projects: `instance_admin` only (they have no member rows).
128
- * All other visibilities: project owner/editor.
129
- */
130
- export function canEdit(input: ProjectAccessInput): boolean {
131
- const { member, project, enablePlatformProjects, platformPermissions } = input;
132
- if (project?.visibility === 'platform') {
133
- if (!enablePlatformProjects) return false;
134
- return isInstanceAdmin(platformPermissions);
135
- }
136
- return member?.role === 'owner' || member?.role === 'editor';
137
- }
138
-
139
- /** Platform projects: `instance_admin` only. All other visibilities: project owner. */
140
- export function canManage(input: ProjectAccessInput): boolean {
141
- if (input.project?.visibility === 'platform') {
142
- if (!input.enablePlatformProjects) return false;
143
- return isInstanceAdmin(input.platformPermissions);
144
- }
145
- return input.member?.role === 'owner';
146
- }
147
-
148
- /** Platform projects: `instance_admin` only. All other visibilities: project owner. */
149
- export function canEditProjectSettings(input: ProjectAccessInput): boolean {
150
- if (input.project?.visibility === 'platform') {
151
- if (!input.enablePlatformProjects) return false;
152
- return isInstanceAdmin(input.platformPermissions);
153
- }
154
- return input.member?.role === 'owner';
155
- }
156
-
157
- export interface VisibilityChangeInput {
158
- orgMember: OrgMember | null;
159
- }
160
-
161
- /**
162
- * Authorization to flip a project to `public`. The `ALLOW_CROSS_ORG_PUBLIC`
163
- * flag only changes what `public` means post-flip; the flip itself is gated
164
- * by org owner/admin role.
165
- */
166
- export function canChangeVisibilityToPublic(input: VisibilityChangeInput): boolean {
167
- const role = input.orgMember?.role;
168
- return role === 'owner' || role === 'admin';
169
- }
170
-
171
- export interface DefinitionAccessInput {
172
- project: Project | null;
173
- definition: DefinitionRecord | null;
174
- member: ProjectMember | null;
175
- userId: string;
176
- platformPermissions: readonly PlatformPermission[];
177
- /**
178
- * `ENABLE_PLATFORM_PROJECTS` flag. When false, definitions in
179
- * platform-visibility projects are not editable by anyone, matching the
180
- * other project rules.
181
- */
182
- enablePlatformProjects: boolean;
183
- }
184
-
185
- /**
186
- * For platform projects: `instance_admin` only.
187
- * For all other projects: project editor/owner can always edit (moderation).
188
- * On commons projects (`autoJoinOnUpload=true`) the definition owner can edit their own.
189
- */
190
- export function canEditDefinition(input: DefinitionAccessInput): boolean {
191
- const { project, definition, member, userId, platformPermissions, enablePlatformProjects } =
192
- input;
193
- if (!project || !definition) return false;
194
-
195
- if (project.visibility === 'platform') {
196
- if (!enablePlatformProjects) return false;
197
- return isInstanceAdmin(platformPermissions);
198
- }
199
-
200
- if (member?.role === 'owner' || member?.role === 'editor') return true;
201
- if (project.autoJoinOnUpload && userId === definition.ownerId) return true;
202
-
203
- return false;
204
- }
205
-
206
- export interface ReclaimAccessInput {
207
- project: Project | null;
208
- orgMember: OrgMember | null;
209
- /** `ctx.actingOrgId` — must match `project.orgId`. */
210
- actingOrgId: string | null;
211
- }
212
-
213
- /**
214
- * Org leadership escape hatch. Reclaim adds the actor as co-owner; it does
215
- * NOT demote the existing owner. Tenancy must match.
216
- *
217
- * Platform projects cannot be reclaimed — `instance_admin` always has
218
- * management access to them without needing the Reclaim mechanism.
219
- */
220
- export function canReclaim(input: ReclaimAccessInput): boolean {
221
- const { project, orgMember, actingOrgId } = input;
222
- if (!project || !actingOrgId) return false;
223
- if (project.visibility === 'platform') return false;
224
- if (actingOrgId !== project.orgId) return false;
225
- const role = orgMember?.role;
226
- return role === 'owner' || role === 'admin';
227
- }
228
-
229
- export interface CreateProjectAccessInput {
230
- orgPermissions: readonly OrgPermission[];
231
- orgMember: OrgMember | null;
232
- actingOrgId: string | null;
233
- targetOrgId: string;
234
- }
235
-
236
- /**
237
- * Owner/admin can always create. A `member` needs `manage_projects` org
238
- * permission. Tenancy is enforced.
239
- *
240
- * Platform projects (`visibility='platform'`) are created via the admin API
241
- * and gated on `instance_admin` — this rule is not consulted for them.
242
- */
243
- export function canCreateProject(input: CreateProjectAccessInput): boolean {
244
- const { orgMember, orgPermissions, actingOrgId, targetOrgId } = input;
245
- if (actingOrgId !== targetOrgId) return false;
246
- const role = orgMember?.role;
247
- if (role === 'owner' || role === 'admin') return true;
248
- if (role === 'member' && orgPermissions.includes('manage_projects')) return true;
249
- return false;
250
- }
251
-
252
- /**
253
- * Pre-flight check for project-owner removal. Pure function over already-
254
- * loaded membership rows so route handlers can call it after `canManage`.
255
- *
256
- * - `ok` — proceed
257
- * - `sole_owner` — last owner; route surfaces 409 + suggests reclaim
258
- * - `needs_confirm` — owner-on-owner removal without `?confirm=true`
259
- *
260
- * Non-owner targets always return `ok`.
261
- */
262
- export type OwnerRemovalCheck = 'ok' | 'sole_owner' | 'needs_confirm';
263
-
264
- export interface OwnerRemovalInput {
265
- target: { role: 'owner' | 'editor' | 'viewer' };
266
- allMembers: readonly { role: 'owner' | 'editor' | 'viewer' }[];
267
- confirmed: boolean;
268
- }
269
-
270
- export function checkOwnerRemoval(input: OwnerRemovalInput): OwnerRemovalCheck {
271
- if (input.target.role !== 'owner') return 'ok';
272
- const ownerCount = input.allMembers.filter((m) => m.role === 'owner').length;
273
- if (ownerCount <= 1) return 'sole_owner';
274
- if (!input.confirmed) return 'needs_confirm';
275
- return 'ok';
276
- }
package/src/auth/index.ts DELETED
@@ -1,8 +0,0 @@
1
- export type { AuthUser, UserManagementResult, LoginResult } from './types.js';
2
- export type {
3
- IAuthProvider,
4
- IOAuthAuth,
5
- IPasswordAuth,
6
- IEmailLinkAuth,
7
- IProxyAuth
8
- } from './interface.js';