@checkstack/auth-common 0.2.0 → 0.4.0
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/CHANGELOG.md +65 -0
- package/package.json +1 -1
- package/src/routes.ts +2 -0
- package/src/rpc-contract.ts +334 -274
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,70 @@
|
|
|
1
1
|
# @checkstack/auth-common
|
|
2
2
|
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- df6ac7b: Added onboarding flow and user profile
|
|
8
|
+
|
|
9
|
+
## 0.3.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- 7a23261: ## TanStack Query Integration
|
|
14
|
+
|
|
15
|
+
Migrated all frontend components to use `usePluginClient` hook with TanStack Query integration, replacing the legacy `forPlugin()` pattern.
|
|
16
|
+
|
|
17
|
+
### New Features
|
|
18
|
+
|
|
19
|
+
- **`usePluginClient` hook**: Provides type-safe access to plugin APIs with `.useQuery()` and `.useMutation()` methods
|
|
20
|
+
- **Automatic request deduplication**: Multiple components requesting the same data share a single network request
|
|
21
|
+
- **Built-in caching**: Configurable stale time and cache duration per query
|
|
22
|
+
- **Loading/error states**: TanStack Query provides `isLoading`, `error`, `isRefetching` states automatically
|
|
23
|
+
- **Background refetching**: Stale data is automatically refreshed when components mount
|
|
24
|
+
|
|
25
|
+
### Contract Changes
|
|
26
|
+
|
|
27
|
+
All RPC contracts now require `operationType: "query"` or `operationType: "mutation"` metadata:
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
const getItems = proc()
|
|
31
|
+
.meta({ operationType: "query", access: [access.read] })
|
|
32
|
+
.output(z.array(itemSchema))
|
|
33
|
+
.query();
|
|
34
|
+
|
|
35
|
+
const createItem = proc()
|
|
36
|
+
.meta({ operationType: "mutation", access: [access.manage] })
|
|
37
|
+
.input(createItemSchema)
|
|
38
|
+
.output(itemSchema)
|
|
39
|
+
.mutation();
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Migration
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
// Before (forPlugin pattern)
|
|
46
|
+
const api = useApi(myPluginApiRef);
|
|
47
|
+
const [items, setItems] = useState<Item[]>([]);
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
api.getItems().then(setItems);
|
|
50
|
+
}, [api]);
|
|
51
|
+
|
|
52
|
+
// After (usePluginClient pattern)
|
|
53
|
+
const client = usePluginClient(MyPluginApi);
|
|
54
|
+
const { data: items, isLoading } = client.getItems.useQuery({});
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Bug Fixes
|
|
58
|
+
|
|
59
|
+
- Fixed `rpc.test.ts` test setup for middleware type inference
|
|
60
|
+
- Fixed `SearchDialog` to use `setQuery` instead of deprecated `search` method
|
|
61
|
+
- Fixed null→undefined warnings in notification and queue frontends
|
|
62
|
+
|
|
63
|
+
### Patch Changes
|
|
64
|
+
|
|
65
|
+
- Updated dependencies [7a23261]
|
|
66
|
+
- @checkstack/common@0.3.0
|
|
67
|
+
|
|
3
68
|
## 0.2.0
|
|
4
69
|
|
|
5
70
|
### Minor Changes
|
package/package.json
CHANGED
package/src/routes.ts
CHANGED
package/src/rpc-contract.ts
CHANGED
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
import { oc } from "@orpc/contract";
|
|
2
1
|
import {
|
|
3
2
|
createClientDefinition,
|
|
4
|
-
|
|
3
|
+
proc,
|
|
5
4
|
lucideIconSchema,
|
|
6
5
|
} from "@checkstack/common";
|
|
7
6
|
import { z } from "zod";
|
|
8
7
|
import { authAccess } from "./access";
|
|
9
8
|
import { pluginMetadata } from "./plugin-metadata";
|
|
10
9
|
|
|
11
|
-
// Base builder with full metadata support
|
|
12
|
-
const _base = oc.$meta<ProcedureMetadata>({});
|
|
13
|
-
|
|
14
10
|
// Zod schemas for return types
|
|
15
11
|
const UserDtoSchema = z.object({
|
|
16
12
|
id: z.string(),
|
|
@@ -25,7 +21,7 @@ const RoleDtoSchema = z.object({
|
|
|
25
21
|
description: z.string().optional().nullable(),
|
|
26
22
|
accessRules: z.array(z.string()),
|
|
27
23
|
isSystem: z.boolean().optional(),
|
|
28
|
-
isAssignable: z.boolean().optional(),
|
|
24
|
+
isAssignable: z.boolean().optional(),
|
|
29
25
|
});
|
|
30
26
|
|
|
31
27
|
const AccessRuleDtoSchema = z.object({
|
|
@@ -40,9 +36,9 @@ const StrategyDtoSchema = z.object({
|
|
|
40
36
|
icon: lucideIconSchema.optional(),
|
|
41
37
|
enabled: z.boolean(),
|
|
42
38
|
configVersion: z.number(),
|
|
43
|
-
configSchema: z.record(z.string(), z.unknown()),
|
|
44
|
-
config: z.record(z.string(), z.unknown()).optional(),
|
|
45
|
-
adminInstructions: z.string().optional(),
|
|
39
|
+
configSchema: z.record(z.string(), z.unknown()),
|
|
40
|
+
config: z.record(z.string(), z.unknown()).optional(),
|
|
41
|
+
adminInstructions: z.string().optional(),
|
|
46
42
|
});
|
|
47
43
|
|
|
48
44
|
const EnabledStrategyDtoSchema = z.object({
|
|
@@ -58,32 +54,25 @@ const RegistrationStatusSchema = z.object({
|
|
|
58
54
|
allowRegistration: z.boolean(),
|
|
59
55
|
});
|
|
60
56
|
|
|
61
|
-
//
|
|
62
|
-
// SERVICE-TO-SERVICE SCHEMAS (for auth provider plugins like LDAP)
|
|
63
|
-
// ==========================================================================
|
|
64
|
-
|
|
57
|
+
// Service-to-service schemas
|
|
65
58
|
const FindUserByEmailInputSchema = z.object({
|
|
66
59
|
email: z.string().email(),
|
|
67
60
|
});
|
|
68
61
|
|
|
69
|
-
const FindUserByEmailOutputSchema = z
|
|
70
|
-
.object({
|
|
71
|
-
id: z.string(),
|
|
72
|
-
})
|
|
73
|
-
.optional();
|
|
62
|
+
const FindUserByEmailOutputSchema = z.object({ id: z.string() }).optional();
|
|
74
63
|
|
|
75
64
|
const UpsertExternalUserInputSchema = z.object({
|
|
76
65
|
email: z.string().email(),
|
|
77
66
|
name: z.string(),
|
|
78
|
-
providerId: z.string(),
|
|
79
|
-
accountId: z.string(),
|
|
80
|
-
password: z.string(),
|
|
81
|
-
autoUpdateUser: z.boolean().optional(),
|
|
67
|
+
providerId: z.string(),
|
|
68
|
+
accountId: z.string(),
|
|
69
|
+
password: z.string(),
|
|
70
|
+
autoUpdateUser: z.boolean().optional(),
|
|
82
71
|
});
|
|
83
72
|
|
|
84
73
|
const UpsertExternalUserOutputSchema = z.object({
|
|
85
74
|
userId: z.string(),
|
|
86
|
-
created: z.boolean(),
|
|
75
|
+
created: z.boolean(),
|
|
87
76
|
});
|
|
88
77
|
|
|
89
78
|
const CreateSessionInputSchema = z.object({
|
|
@@ -95,7 +84,7 @@ const CreateSessionInputSchema = z.object({
|
|
|
95
84
|
const CreateCredentialUserInputSchema = z.object({
|
|
96
85
|
email: z.string().email(),
|
|
97
86
|
name: z.string().min(1),
|
|
98
|
-
password: z.string(),
|
|
87
|
+
password: z.string(),
|
|
99
88
|
});
|
|
100
89
|
|
|
101
90
|
const CreateCredentialUserOutputSchema = z.object({
|
|
@@ -106,90 +95,160 @@ const CreateCredentialUserOutputSchema = z.object({
|
|
|
106
95
|
export const authContract = {
|
|
107
96
|
// ==========================================================================
|
|
108
97
|
// ANONYMOUS ENDPOINTS (userType: "anonymous")
|
|
109
|
-
// These can be called without authentication (login/registration pages)
|
|
110
98
|
// ==========================================================================
|
|
111
99
|
|
|
112
|
-
getEnabledStrategies:
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
100
|
+
getEnabledStrategies: proc({
|
|
101
|
+
operationType: "query",
|
|
102
|
+
userType: "anonymous",
|
|
103
|
+
access: [],
|
|
104
|
+
}).output(z.array(EnabledStrategyDtoSchema)),
|
|
105
|
+
|
|
106
|
+
getRegistrationStatus: proc({
|
|
107
|
+
operationType: "query",
|
|
108
|
+
userType: "anonymous",
|
|
109
|
+
access: [],
|
|
110
|
+
}).output(RegistrationStatusSchema),
|
|
111
|
+
|
|
112
|
+
getOnboardingStatus: proc({
|
|
113
|
+
operationType: "query",
|
|
114
|
+
userType: "anonymous",
|
|
115
|
+
access: [],
|
|
116
|
+
}).output(z.object({ needsOnboarding: z.boolean() })),
|
|
117
|
+
|
|
118
|
+
completeOnboarding: proc({
|
|
119
|
+
operationType: "mutation",
|
|
120
|
+
userType: "anonymous",
|
|
121
|
+
access: [],
|
|
122
|
+
})
|
|
123
|
+
.input(
|
|
124
|
+
z.object({
|
|
125
|
+
name: z.string().min(1),
|
|
126
|
+
email: z.string().email(),
|
|
127
|
+
password: z.string(),
|
|
128
|
+
}),
|
|
129
|
+
)
|
|
130
|
+
.output(z.object({ success: z.boolean() })),
|
|
119
131
|
|
|
120
132
|
// ==========================================================================
|
|
121
|
-
// AUTHENTICATED ENDPOINTS (userType: "authenticated"
|
|
133
|
+
// AUTHENTICATED ENDPOINTS (userType: "authenticated")
|
|
122
134
|
// ==========================================================================
|
|
123
135
|
|
|
124
|
-
accessRules:
|
|
125
|
-
|
|
126
|
-
|
|
136
|
+
accessRules: proc({
|
|
137
|
+
operationType: "query",
|
|
138
|
+
userType: "authenticated",
|
|
139
|
+
access: [],
|
|
140
|
+
}).output(z.object({ accessRules: z.array(z.string()) })),
|
|
141
|
+
|
|
142
|
+
getCurrentUserProfile: proc({
|
|
143
|
+
operationType: "query",
|
|
144
|
+
userType: "user",
|
|
145
|
+
access: [],
|
|
146
|
+
}).output(
|
|
147
|
+
z.object({
|
|
148
|
+
id: z.string(),
|
|
149
|
+
name: z.string(),
|
|
150
|
+
email: z.string(),
|
|
151
|
+
hasCredentialAccount: z.boolean(),
|
|
152
|
+
}),
|
|
153
|
+
),
|
|
154
|
+
|
|
155
|
+
updateCurrentUser: proc({
|
|
156
|
+
operationType: "mutation",
|
|
157
|
+
userType: "user",
|
|
158
|
+
access: [],
|
|
159
|
+
})
|
|
160
|
+
.input(
|
|
161
|
+
z.object({
|
|
162
|
+
name: z.string().min(1).optional(),
|
|
163
|
+
email: z.string().email().optional(),
|
|
164
|
+
}),
|
|
165
|
+
)
|
|
166
|
+
.output(z.void()),
|
|
127
167
|
|
|
128
168
|
// ==========================================================================
|
|
129
169
|
// USER MANAGEMENT (userType: "user" with access)
|
|
130
170
|
// ==========================================================================
|
|
131
171
|
|
|
132
|
-
getUsers:
|
|
133
|
-
|
|
134
|
-
|
|
172
|
+
getUsers: proc({
|
|
173
|
+
operationType: "query",
|
|
174
|
+
userType: "user",
|
|
175
|
+
access: [authAccess.users.read],
|
|
176
|
+
}).output(z.array(UserDtoSchema)),
|
|
135
177
|
|
|
136
|
-
deleteUser:
|
|
137
|
-
|
|
178
|
+
deleteUser: proc({
|
|
179
|
+
operationType: "mutation",
|
|
180
|
+
userType: "user",
|
|
181
|
+
access: [authAccess.users.manage],
|
|
182
|
+
})
|
|
138
183
|
.input(z.string())
|
|
139
184
|
.output(z.void()),
|
|
140
185
|
|
|
141
|
-
createCredentialUser:
|
|
142
|
-
|
|
186
|
+
createCredentialUser: proc({
|
|
187
|
+
operationType: "mutation",
|
|
188
|
+
userType: "user",
|
|
189
|
+
access: [authAccess.users.create],
|
|
190
|
+
})
|
|
143
191
|
.input(CreateCredentialUserInputSchema)
|
|
144
192
|
.output(CreateCredentialUserOutputSchema),
|
|
145
193
|
|
|
146
|
-
updateUserRoles:
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
})
|
|
153
|
-
)
|
|
194
|
+
updateUserRoles: proc({
|
|
195
|
+
operationType: "mutation",
|
|
196
|
+
userType: "user",
|
|
197
|
+
access: [authAccess.users.manage],
|
|
198
|
+
})
|
|
199
|
+
.input(z.object({ userId: z.string(), roles: z.array(z.string()) }))
|
|
154
200
|
.output(z.void()),
|
|
155
201
|
|
|
156
202
|
// ==========================================================================
|
|
157
203
|
// ROLE MANAGEMENT (userType: "user" with access)
|
|
158
204
|
// ==========================================================================
|
|
159
205
|
|
|
160
|
-
getRoles:
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
206
|
+
getRoles: proc({
|
|
207
|
+
operationType: "query",
|
|
208
|
+
userType: "user",
|
|
209
|
+
access: [authAccess.roles.read],
|
|
210
|
+
}).output(z.array(RoleDtoSchema)),
|
|
211
|
+
|
|
212
|
+
getAccessRules: proc({
|
|
213
|
+
operationType: "query",
|
|
214
|
+
userType: "user",
|
|
215
|
+
access: [authAccess.roles.read],
|
|
216
|
+
}).output(z.array(AccessRuleDtoSchema)),
|
|
217
|
+
|
|
218
|
+
createRole: proc({
|
|
219
|
+
operationType: "mutation",
|
|
220
|
+
userType: "user",
|
|
221
|
+
access: [authAccess.roles.create],
|
|
222
|
+
})
|
|
170
223
|
.input(
|
|
171
224
|
z.object({
|
|
172
225
|
name: z.string(),
|
|
173
226
|
description: z.string().optional(),
|
|
174
227
|
accessRules: z.array(z.string()),
|
|
175
|
-
})
|
|
228
|
+
}),
|
|
176
229
|
)
|
|
177
230
|
.output(z.void()),
|
|
178
231
|
|
|
179
|
-
updateRole:
|
|
180
|
-
|
|
232
|
+
updateRole: proc({
|
|
233
|
+
operationType: "mutation",
|
|
234
|
+
userType: "user",
|
|
235
|
+
access: [authAccess.roles.update],
|
|
236
|
+
})
|
|
181
237
|
.input(
|
|
182
238
|
z.object({
|
|
183
239
|
id: z.string(),
|
|
184
240
|
name: z.string().optional(),
|
|
185
241
|
description: z.string().optional(),
|
|
186
242
|
accessRules: z.array(z.string()),
|
|
187
|
-
})
|
|
243
|
+
}),
|
|
188
244
|
)
|
|
189
245
|
.output(z.void()),
|
|
190
246
|
|
|
191
|
-
deleteRole:
|
|
192
|
-
|
|
247
|
+
deleteRole: proc({
|
|
248
|
+
operationType: "mutation",
|
|
249
|
+
userType: "user",
|
|
250
|
+
access: [authAccess.roles.delete],
|
|
251
|
+
})
|
|
193
252
|
.input(z.string())
|
|
194
253
|
.output(z.void()),
|
|
195
254
|
|
|
@@ -197,41 +256,47 @@ export const authContract = {
|
|
|
197
256
|
// STRATEGY MANAGEMENT (userType: "user" with access)
|
|
198
257
|
// ==========================================================================
|
|
199
258
|
|
|
200
|
-
getStrategies:
|
|
201
|
-
|
|
202
|
-
|
|
259
|
+
getStrategies: proc({
|
|
260
|
+
operationType: "query",
|
|
261
|
+
userType: "user",
|
|
262
|
+
access: [authAccess.strategies],
|
|
263
|
+
}).output(z.array(StrategyDtoSchema)),
|
|
203
264
|
|
|
204
|
-
updateStrategy:
|
|
205
|
-
|
|
265
|
+
updateStrategy: proc({
|
|
266
|
+
operationType: "mutation",
|
|
267
|
+
userType: "user",
|
|
268
|
+
access: [authAccess.strategies],
|
|
269
|
+
})
|
|
206
270
|
.input(
|
|
207
271
|
z.object({
|
|
208
272
|
id: z.string(),
|
|
209
273
|
enabled: z.boolean(),
|
|
210
274
|
config: z.record(z.string(), z.unknown()).optional(),
|
|
211
|
-
})
|
|
275
|
+
}),
|
|
212
276
|
)
|
|
213
277
|
.output(z.object({ success: z.boolean() })),
|
|
214
278
|
|
|
215
|
-
reloadAuth:
|
|
216
|
-
|
|
217
|
-
|
|
279
|
+
reloadAuth: proc({
|
|
280
|
+
operationType: "mutation",
|
|
281
|
+
userType: "user",
|
|
282
|
+
access: [authAccess.strategies],
|
|
283
|
+
}).output(z.object({ success: z.boolean() })),
|
|
218
284
|
|
|
219
285
|
// ==========================================================================
|
|
220
286
|
// REGISTRATION MANAGEMENT (userType: "user" with access)
|
|
221
287
|
// ==========================================================================
|
|
222
288
|
|
|
223
|
-
getRegistrationSchema:
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
})
|
|
289
|
+
getRegistrationSchema: proc({
|
|
290
|
+
operationType: "query",
|
|
291
|
+
userType: "user",
|
|
292
|
+
access: [authAccess.registration],
|
|
293
|
+
}).output(z.record(z.string(), z.unknown())),
|
|
294
|
+
|
|
295
|
+
setRegistrationStatus: proc({
|
|
296
|
+
operationType: "mutation",
|
|
297
|
+
userType: "user",
|
|
298
|
+
access: [authAccess.registration],
|
|
299
|
+
})
|
|
235
300
|
.input(RegistrationStatusSchema)
|
|
236
301
|
.output(z.object({ success: z.boolean() })),
|
|
237
302
|
|
|
@@ -239,48 +304,41 @@ export const authContract = {
|
|
|
239
304
|
// INTERNAL SERVICE ENDPOINTS (userType: "service")
|
|
240
305
|
// ==========================================================================
|
|
241
306
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
.meta({ userType: "service" })
|
|
248
|
-
.output(z.array(z.string())),
|
|
307
|
+
getAnonymousAccessRules: proc({
|
|
308
|
+
operationType: "query",
|
|
309
|
+
userType: "service",
|
|
310
|
+
access: [],
|
|
311
|
+
}).output(z.array(z.string())),
|
|
249
312
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
.meta({ userType: "service" })
|
|
313
|
+
findUserByEmail: proc({
|
|
314
|
+
operationType: "query",
|
|
315
|
+
userType: "service",
|
|
316
|
+
access: [],
|
|
317
|
+
})
|
|
256
318
|
.input(FindUserByEmailInputSchema)
|
|
257
319
|
.output(FindUserByEmailOutputSchema),
|
|
258
320
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
upsertExternalUser: _base
|
|
265
|
-
.meta({ userType: "service" })
|
|
321
|
+
upsertExternalUser: proc({
|
|
322
|
+
operationType: "mutation",
|
|
323
|
+
userType: "service",
|
|
324
|
+
access: [],
|
|
325
|
+
})
|
|
266
326
|
.input(UpsertExternalUserInputSchema)
|
|
267
327
|
.output(UpsertExternalUserOutputSchema),
|
|
268
328
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
.meta({ userType: "service" })
|
|
329
|
+
createSession: proc({
|
|
330
|
+
operationType: "mutation",
|
|
331
|
+
userType: "service",
|
|
332
|
+
access: [],
|
|
333
|
+
})
|
|
275
334
|
.input(CreateSessionInputSchema)
|
|
276
335
|
.output(z.object({ sessionId: z.string() })),
|
|
277
336
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
.meta({ userType: "service" })
|
|
337
|
+
getUserById: proc({
|
|
338
|
+
operationType: "query",
|
|
339
|
+
userType: "service",
|
|
340
|
+
access: [],
|
|
341
|
+
})
|
|
284
342
|
.input(z.object({ userId: z.string() }))
|
|
285
343
|
.output(
|
|
286
344
|
z
|
|
@@ -289,57 +347,54 @@ export const authContract = {
|
|
|
289
347
|
email: z.string(),
|
|
290
348
|
name: z.string().nullable(),
|
|
291
349
|
})
|
|
292
|
-
.optional()
|
|
350
|
+
.optional(),
|
|
293
351
|
),
|
|
294
352
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
.meta({ userType: "service" })
|
|
353
|
+
filterUsersByAccessRule: proc({
|
|
354
|
+
operationType: "query",
|
|
355
|
+
userType: "service",
|
|
356
|
+
access: [],
|
|
357
|
+
})
|
|
301
358
|
.input(
|
|
302
359
|
z.object({
|
|
303
360
|
userIds: z.array(z.string()),
|
|
304
|
-
accessRule: z.string(),
|
|
305
|
-
})
|
|
361
|
+
accessRule: z.string(),
|
|
362
|
+
}),
|
|
306
363
|
)
|
|
307
|
-
.output(z.array(z.string())),
|
|
364
|
+
.output(z.array(z.string())),
|
|
308
365
|
|
|
309
366
|
// ==========================================================================
|
|
310
367
|
// APPLICATION MANAGEMENT (userType: "user" with access)
|
|
311
|
-
// External API applications (API keys) with RBAC integration
|
|
312
368
|
// ==========================================================================
|
|
313
369
|
|
|
314
|
-
getApplications:
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
.
|
|
320
|
-
z.
|
|
321
|
-
z.
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
})
|
|
330
|
-
)
|
|
370
|
+
getApplications: proc({
|
|
371
|
+
operationType: "query",
|
|
372
|
+
userType: "user",
|
|
373
|
+
access: [authAccess.applications],
|
|
374
|
+
}).output(
|
|
375
|
+
z.array(
|
|
376
|
+
z.object({
|
|
377
|
+
id: z.string(),
|
|
378
|
+
name: z.string(),
|
|
379
|
+
description: z.string().optional().nullable(),
|
|
380
|
+
roles: z.array(z.string()),
|
|
381
|
+
createdById: z.string(),
|
|
382
|
+
createdAt: z.coerce.date(),
|
|
383
|
+
lastUsedAt: z.coerce.date().optional().nullable(),
|
|
384
|
+
}),
|
|
331
385
|
),
|
|
386
|
+
),
|
|
332
387
|
|
|
333
|
-
createApplication:
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
388
|
+
createApplication: proc({
|
|
389
|
+
operationType: "mutation",
|
|
390
|
+
userType: "user",
|
|
391
|
+
access: [authAccess.applications],
|
|
392
|
+
})
|
|
338
393
|
.input(
|
|
339
394
|
z.object({
|
|
340
395
|
name: z.string().min(1).max(100),
|
|
341
396
|
description: z.string().max(500).optional(),
|
|
342
|
-
})
|
|
397
|
+
}),
|
|
343
398
|
)
|
|
344
399
|
.output(
|
|
345
400
|
z.object({
|
|
@@ -351,69 +406,66 @@ export const authContract = {
|
|
|
351
406
|
createdById: z.string(),
|
|
352
407
|
createdAt: z.coerce.date(),
|
|
353
408
|
}),
|
|
354
|
-
secret: z.string(),
|
|
355
|
-
})
|
|
409
|
+
secret: z.string(),
|
|
410
|
+
}),
|
|
356
411
|
),
|
|
357
412
|
|
|
358
|
-
updateApplication:
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
413
|
+
updateApplication: proc({
|
|
414
|
+
operationType: "mutation",
|
|
415
|
+
userType: "user",
|
|
416
|
+
access: [authAccess.applications],
|
|
417
|
+
})
|
|
363
418
|
.input(
|
|
364
419
|
z.object({
|
|
365
420
|
id: z.string(),
|
|
366
421
|
name: z.string().optional(),
|
|
367
422
|
description: z.string().optional().nullable(),
|
|
368
423
|
roles: z.array(z.string()).optional(),
|
|
369
|
-
})
|
|
424
|
+
}),
|
|
370
425
|
)
|
|
371
426
|
.output(z.void()),
|
|
372
427
|
|
|
373
|
-
deleteApplication:
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
428
|
+
deleteApplication: proc({
|
|
429
|
+
operationType: "mutation",
|
|
430
|
+
userType: "user",
|
|
431
|
+
access: [authAccess.applications],
|
|
432
|
+
})
|
|
378
433
|
.input(z.string())
|
|
379
434
|
.output(z.void()),
|
|
380
435
|
|
|
381
|
-
regenerateApplicationSecret:
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
436
|
+
regenerateApplicationSecret: proc({
|
|
437
|
+
operationType: "mutation",
|
|
438
|
+
userType: "user",
|
|
439
|
+
access: [authAccess.applications],
|
|
440
|
+
})
|
|
386
441
|
.input(z.string())
|
|
387
|
-
.output(z.object({ secret: z.string() })),
|
|
442
|
+
.output(z.object({ secret: z.string() })),
|
|
388
443
|
|
|
389
444
|
// ==========================================================================
|
|
390
445
|
// TEAM MANAGEMENT (userType: "authenticated" with access)
|
|
391
|
-
// Resource-level access control via teams
|
|
392
|
-
// Both users and applications can manage teams with proper access
|
|
393
446
|
// ==========================================================================
|
|
394
447
|
|
|
395
|
-
getTeams:
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
.
|
|
401
|
-
z.
|
|
402
|
-
z.
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
})
|
|
409
|
-
)
|
|
448
|
+
getTeams: proc({
|
|
449
|
+
operationType: "query",
|
|
450
|
+
userType: "authenticated",
|
|
451
|
+
access: [authAccess.teams.read],
|
|
452
|
+
}).output(
|
|
453
|
+
z.array(
|
|
454
|
+
z.object({
|
|
455
|
+
id: z.string(),
|
|
456
|
+
name: z.string(),
|
|
457
|
+
description: z.string().optional().nullable(),
|
|
458
|
+
memberCount: z.number(),
|
|
459
|
+
isManager: z.boolean(),
|
|
460
|
+
}),
|
|
410
461
|
),
|
|
462
|
+
),
|
|
411
463
|
|
|
412
|
-
getTeam:
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
464
|
+
getTeam: proc({
|
|
465
|
+
operationType: "query",
|
|
466
|
+
userType: "authenticated",
|
|
467
|
+
access: [authAccess.teams.read],
|
|
468
|
+
})
|
|
417
469
|
.input(z.object({ teamId: z.string() }))
|
|
418
470
|
.output(
|
|
419
471
|
z
|
|
@@ -422,87 +474,87 @@ export const authContract = {
|
|
|
422
474
|
name: z.string(),
|
|
423
475
|
description: z.string().optional().nullable(),
|
|
424
476
|
members: z.array(
|
|
425
|
-
z.object({ id: z.string(), name: z.string(), email: z.string() })
|
|
477
|
+
z.object({ id: z.string(), name: z.string(), email: z.string() }),
|
|
426
478
|
),
|
|
427
479
|
managers: z.array(
|
|
428
|
-
z.object({ id: z.string(), name: z.string(), email: z.string() })
|
|
480
|
+
z.object({ id: z.string(), name: z.string(), email: z.string() }),
|
|
429
481
|
),
|
|
430
482
|
})
|
|
431
|
-
.optional()
|
|
483
|
+
.optional(),
|
|
432
484
|
),
|
|
433
485
|
|
|
434
|
-
createTeam:
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
486
|
+
createTeam: proc({
|
|
487
|
+
operationType: "mutation",
|
|
488
|
+
userType: "authenticated",
|
|
489
|
+
access: [authAccess.teams.manage],
|
|
490
|
+
})
|
|
439
491
|
.input(
|
|
440
492
|
z.object({
|
|
441
493
|
name: z.string().min(1).max(100),
|
|
442
494
|
description: z.string().max(500).optional(),
|
|
443
|
-
})
|
|
495
|
+
}),
|
|
444
496
|
)
|
|
445
497
|
.output(z.object({ id: z.string() })),
|
|
446
498
|
|
|
447
|
-
updateTeam:
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
499
|
+
updateTeam: proc({
|
|
500
|
+
operationType: "mutation",
|
|
501
|
+
userType: "authenticated",
|
|
502
|
+
access: [authAccess.teams.read],
|
|
503
|
+
})
|
|
452
504
|
.input(
|
|
453
505
|
z.object({
|
|
454
506
|
id: z.string(),
|
|
455
507
|
name: z.string().optional(),
|
|
456
508
|
description: z.string().optional().nullable(),
|
|
457
|
-
})
|
|
509
|
+
}),
|
|
458
510
|
)
|
|
459
511
|
.output(z.void()),
|
|
460
512
|
|
|
461
|
-
deleteTeam:
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
513
|
+
deleteTeam: proc({
|
|
514
|
+
operationType: "mutation",
|
|
515
|
+
userType: "authenticated",
|
|
516
|
+
access: [authAccess.teams.manage],
|
|
517
|
+
})
|
|
466
518
|
.input(z.string())
|
|
467
519
|
.output(z.void()),
|
|
468
520
|
|
|
469
|
-
addUserToTeam:
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
521
|
+
addUserToTeam: proc({
|
|
522
|
+
operationType: "mutation",
|
|
523
|
+
userType: "authenticated",
|
|
524
|
+
access: [authAccess.teams.read],
|
|
525
|
+
})
|
|
474
526
|
.input(z.object({ teamId: z.string(), userId: z.string() }))
|
|
475
527
|
.output(z.void()),
|
|
476
528
|
|
|
477
|
-
removeUserFromTeam:
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
529
|
+
removeUserFromTeam: proc({
|
|
530
|
+
operationType: "mutation",
|
|
531
|
+
userType: "authenticated",
|
|
532
|
+
access: [authAccess.teams.read],
|
|
533
|
+
})
|
|
482
534
|
.input(z.object({ teamId: z.string(), userId: z.string() }))
|
|
483
535
|
.output(z.void()),
|
|
484
536
|
|
|
485
|
-
addTeamManager:
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
537
|
+
addTeamManager: proc({
|
|
538
|
+
operationType: "mutation",
|
|
539
|
+
userType: "authenticated",
|
|
540
|
+
access: [authAccess.teams.manage],
|
|
541
|
+
})
|
|
490
542
|
.input(z.object({ teamId: z.string(), userId: z.string() }))
|
|
491
543
|
.output(z.void()),
|
|
492
544
|
|
|
493
|
-
removeTeamManager:
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
545
|
+
removeTeamManager: proc({
|
|
546
|
+
operationType: "mutation",
|
|
547
|
+
userType: "authenticated",
|
|
548
|
+
access: [authAccess.teams.manage],
|
|
549
|
+
})
|
|
498
550
|
.input(z.object({ teamId: z.string(), userId: z.string() }))
|
|
499
551
|
.output(z.void()),
|
|
500
552
|
|
|
501
|
-
getResourceTeamAccess:
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
553
|
+
getResourceTeamAccess: proc({
|
|
554
|
+
operationType: "query",
|
|
555
|
+
userType: "authenticated",
|
|
556
|
+
access: [authAccess.teams.read],
|
|
557
|
+
})
|
|
506
558
|
.input(z.object({ resourceType: z.string(), resourceId: z.string() }))
|
|
507
559
|
.output(
|
|
508
560
|
z.array(
|
|
@@ -511,15 +563,15 @@ export const authContract = {
|
|
|
511
563
|
teamName: z.string(),
|
|
512
564
|
canRead: z.boolean(),
|
|
513
565
|
canManage: z.boolean(),
|
|
514
|
-
})
|
|
515
|
-
)
|
|
566
|
+
}),
|
|
567
|
+
),
|
|
516
568
|
),
|
|
517
569
|
|
|
518
|
-
setResourceTeamAccess:
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
570
|
+
setResourceTeamAccess: proc({
|
|
571
|
+
operationType: "mutation",
|
|
572
|
+
userType: "authenticated",
|
|
573
|
+
access: [authAccess.teams.manage],
|
|
574
|
+
})
|
|
523
575
|
.input(
|
|
524
576
|
z.object({
|
|
525
577
|
resourceType: z.string(),
|
|
@@ -527,44 +579,43 @@ export const authContract = {
|
|
|
527
579
|
teamId: z.string(),
|
|
528
580
|
canRead: z.boolean().optional(),
|
|
529
581
|
canManage: z.boolean().optional(),
|
|
530
|
-
})
|
|
582
|
+
}),
|
|
531
583
|
)
|
|
532
584
|
.output(z.void()),
|
|
533
585
|
|
|
534
|
-
removeResourceTeamAccess:
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
586
|
+
removeResourceTeamAccess: proc({
|
|
587
|
+
operationType: "mutation",
|
|
588
|
+
userType: "authenticated",
|
|
589
|
+
access: [authAccess.teams.manage],
|
|
590
|
+
})
|
|
539
591
|
.input(
|
|
540
592
|
z.object({
|
|
541
593
|
resourceType: z.string(),
|
|
542
594
|
resourceId: z.string(),
|
|
543
595
|
teamId: z.string(),
|
|
544
|
-
})
|
|
596
|
+
}),
|
|
545
597
|
)
|
|
546
598
|
.output(z.void()),
|
|
547
599
|
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
})
|
|
600
|
+
getResourceAccessSettings: proc({
|
|
601
|
+
operationType: "query",
|
|
602
|
+
userType: "authenticated",
|
|
603
|
+
access: [authAccess.teams.read],
|
|
604
|
+
})
|
|
554
605
|
.input(z.object({ resourceType: z.string(), resourceId: z.string() }))
|
|
555
606
|
.output(z.object({ teamOnly: z.boolean() })),
|
|
556
607
|
|
|
557
|
-
setResourceAccessSettings:
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
608
|
+
setResourceAccessSettings: proc({
|
|
609
|
+
operationType: "mutation",
|
|
610
|
+
userType: "authenticated",
|
|
611
|
+
access: [authAccess.teams.manage],
|
|
612
|
+
})
|
|
562
613
|
.input(
|
|
563
614
|
z.object({
|
|
564
615
|
resourceType: z.string(),
|
|
565
616
|
resourceId: z.string(),
|
|
566
617
|
teamOnly: z.boolean(),
|
|
567
|
-
})
|
|
618
|
+
}),
|
|
568
619
|
)
|
|
569
620
|
.output(z.void()),
|
|
570
621
|
|
|
@@ -572,8 +623,11 @@ export const authContract = {
|
|
|
572
623
|
// S2S ENDPOINTS FOR TEAM ACCESS (userType: "service")
|
|
573
624
|
// ==========================================================================
|
|
574
625
|
|
|
575
|
-
checkResourceTeamAccess:
|
|
576
|
-
|
|
626
|
+
checkResourceTeamAccess: proc({
|
|
627
|
+
operationType: "query",
|
|
628
|
+
userType: "service",
|
|
629
|
+
access: [],
|
|
630
|
+
})
|
|
577
631
|
.input(
|
|
578
632
|
z.object({
|
|
579
633
|
userId: z.string(),
|
|
@@ -582,12 +636,15 @@ export const authContract = {
|
|
|
582
636
|
resourceId: z.string(),
|
|
583
637
|
action: z.enum(["read", "manage"]),
|
|
584
638
|
hasGlobalAccess: z.boolean(),
|
|
585
|
-
})
|
|
639
|
+
}),
|
|
586
640
|
)
|
|
587
641
|
.output(z.object({ hasAccess: z.boolean() })),
|
|
588
642
|
|
|
589
|
-
getAccessibleResourceIds:
|
|
590
|
-
|
|
643
|
+
getAccessibleResourceIds: proc({
|
|
644
|
+
operationType: "query",
|
|
645
|
+
userType: "service",
|
|
646
|
+
access: [],
|
|
647
|
+
})
|
|
591
648
|
.input(
|
|
592
649
|
z.object({
|
|
593
650
|
userId: z.string(),
|
|
@@ -596,12 +653,15 @@ export const authContract = {
|
|
|
596
653
|
resourceIds: z.array(z.string()),
|
|
597
654
|
action: z.enum(["read", "manage"]),
|
|
598
655
|
hasGlobalAccess: z.boolean(),
|
|
599
|
-
})
|
|
656
|
+
}),
|
|
600
657
|
)
|
|
601
658
|
.output(z.array(z.string())),
|
|
602
659
|
|
|
603
|
-
deleteResourceGrants:
|
|
604
|
-
|
|
660
|
+
deleteResourceGrants: proc({
|
|
661
|
+
operationType: "mutation",
|
|
662
|
+
userType: "service",
|
|
663
|
+
access: [],
|
|
664
|
+
})
|
|
605
665
|
.input(z.object({ resourceType: z.string(), resourceId: z.string() }))
|
|
606
666
|
.output(z.void()),
|
|
607
667
|
};
|