@astrale-domains/shell 0.1.0-beta.12 → 0.1.0-beta.13
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/README.md +67 -46
- package/dist/actions/index.d.ts +1 -0
- package/dist/actions/index.js +1 -0
- package/dist/actions/user/index.d.ts +1 -0
- package/dist/actions/user/index.js +1 -0
- package/dist/actions/user/resolve-home.d.ts +3 -0
- package/dist/actions/user/resolve-home.js +19 -0
- package/dist/application.d.ts +6 -0
- package/dist/application.js +30 -0
- package/dist/entrypoints/application.d.ts +1 -0
- package/dist/entrypoints/application.js +1 -0
- package/dist/entrypoints/runtime.d.ts +1 -0
- package/dist/entrypoints/runtime.js +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/mutations/group/index.d.ts +1 -0
- package/dist/mutations/group/index.js +1 -0
- package/dist/mutations/group/membership.d.ts +19 -0
- package/dist/mutations/group/membership.js +19 -0
- package/dist/mutations/space/access.d.ts +25 -0
- package/dist/mutations/space/access.js +23 -0
- package/dist/mutations/space/default.d.ts +19 -0
- package/dist/mutations/space/default.js +23 -0
- package/dist/mutations/space/index.d.ts +2 -0
- package/dist/mutations/space/index.js +2 -0
- package/dist/mutations/user/index.d.ts +1 -0
- package/dist/mutations/user/index.js +1 -0
- package/dist/mutations/user/repair.d.ts +37 -0
- package/dist/mutations/user/repair.js +83 -0
- package/dist/queries/space/access.d.ts +9 -0
- package/dist/queries/space/access.js +12 -0
- package/dist/queries/space/admin.d.ts +9 -0
- package/dist/queries/space/admin.js +20 -0
- package/dist/queries/space/index.d.ts +3 -0
- package/dist/queries/space/index.js +3 -0
- package/dist/queries/space/member.d.ts +9 -0
- package/dist/queries/space/member.js +17 -0
- package/dist/queries/user/groups.d.ts +9 -0
- package/dist/queries/user/groups.js +17 -0
- package/dist/queries/user/home.d.ts +9 -0
- package/dist/queries/user/home.js +21 -0
- package/dist/queries/user/index.d.ts +5 -0
- package/dist/queries/user/index.js +5 -0
- package/dist/queries/user/owned-spaces.d.ts +9 -0
- package/dist/queries/user/owned-spaces.js +17 -0
- package/dist/queries/user/profile.d.ts +4 -0
- package/dist/queries/user/profile.js +16 -0
- package/dist/queries/user/setup.d.ts +13 -0
- package/dist/queries/user/setup.js +16 -0
- package/dist/runtime.d.ts +10 -0
- package/dist/runtime.js +17 -0
- package/dist/schema/domain/index.d.ts +69 -1640
- package/dist/schema/domain/index.js +3 -2
- package/dist/schema/group/class.d.ts +13 -321
- package/dist/schema/group/class.js +3 -2
- package/dist/schema/group/methods.d.ts +2 -2
- package/dist/schema/group/methods.js +1 -5
- package/dist/schema/index.d.ts +6 -6
- package/dist/schema/space/class.d.ts +10 -78
- package/dist/schema/space/class.js +3 -2
- package/dist/schema/space/methods.d.ts +4 -4
- package/dist/schema/space/methods.js +1 -5
- package/dist/schema/user/class.d.ts +14 -274
- package/dist/schema/user/class.js +5 -5
- package/dist/workflows/group/assign.d.ts +3 -0
- package/dist/workflows/group/assign.js +3 -0
- package/dist/workflows/group/change.d.ts +6 -0
- package/dist/workflows/group/change.js +31 -0
- package/dist/workflows/group/index.d.ts +3 -0
- package/dist/workflows/group/index.js +3 -0
- package/dist/workflows/group/unassign.d.ts +3 -0
- package/dist/workflows/group/unassign.js +3 -0
- package/dist/workflows/index.d.ts +3 -0
- package/dist/workflows/index.js +3 -0
- package/dist/workflows/setup/admin.d.ts +3 -0
- package/dist/workflows/setup/admin.js +3 -0
- package/dist/workflows/setup/index.d.ts +5 -0
- package/dist/workflows/setup/index.js +5 -0
- package/dist/workflows/setup/member.d.ts +3 -0
- package/dist/workflows/setup/member.js +3 -0
- package/dist/workflows/setup/plan.d.ts +18 -0
- package/dist/workflows/setup/plan.js +88 -0
- package/dist/workflows/setup/provision.d.ts +5 -0
- package/dist/workflows/setup/provision.js +57 -0
- package/dist/workflows/setup/run.d.ts +7 -0
- package/dist/workflows/setup/run.js +74 -0
- package/dist/workflows/space/access.d.ts +7 -0
- package/dist/workflows/space/access.js +41 -0
- package/dist/workflows/space/add.d.ts +3 -0
- package/dist/workflows/space/add.js +3 -0
- package/dist/workflows/space/default.d.ts +3 -0
- package/dist/workflows/space/default.js +37 -0
- package/dist/workflows/space/index.d.ts +4 -0
- package/dist/workflows/space/index.js +4 -0
- package/dist/workflows/space/remove.d.ts +3 -0
- package/dist/workflows/space/remove.js +3 -0
- package/package.json +27 -11
|
@@ -1,278 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}, import("@astrale-os/sdk/schema").ClassRef & import("@astrale-os/sdk/schema").ClassRef<"Identity"> & {
|
|
11
|
-
readonly origin: "kernel.astrale.ai";
|
|
12
|
-
}, "kernel.astrale.ai:class.Identity", readonly [import("@astrale-os/sdk/schema").ClassProjection<"node", import("@astrale-os/sdk/schema").NodeClassDefinition & {
|
|
13
|
-
readonly ref: import("@astrale-os/sdk/schema").ClassRef<"Node"> & {
|
|
14
|
-
readonly origin: "kernel.astrale.ai";
|
|
15
|
-
};
|
|
16
|
-
readonly kind: 'node';
|
|
17
|
-
readonly abstract: true;
|
|
18
|
-
}, import("@astrale-os/sdk/schema").ClassRef & import("@astrale-os/sdk/schema").ClassRef<"Node"> & {
|
|
19
|
-
readonly origin: "kernel.astrale.ai";
|
|
20
|
-
}, "kernel.astrale.ai:class.Node", readonly import("@astrale-os/sdk/schema").AnyResolvedClass[], never, never, never, never, never, never>, ...never[]], import("@astrale-os/sdk/schema").PropertyProjection<({
|
|
21
|
-
claim: string;
|
|
22
|
-
op: "contains";
|
|
23
|
-
value: unknown;
|
|
24
|
-
} | {
|
|
25
|
-
claim: string;
|
|
26
|
-
op: "eq";
|
|
27
|
-
value: unknown;
|
|
28
|
-
} | {
|
|
29
|
-
claim: string;
|
|
30
|
-
op: "exists";
|
|
31
|
-
})[], false, "requiredClaims", "kernel.astrale.ai:class.Identity.property.requiredClaims"> | import("@astrale-os/sdk/schema").PropertyProjection<string | number | boolean | import("@astrale-os/sdk/schema").Array | import("@astrale-os/sdk/schema").Object | null, false, "frozen", "kernel.astrale.ai:class.Identity.property.frozen"> | import("@astrale-os/sdk/schema").PropertyProjection<string | number | boolean | import("@astrale-os/sdk/schema").Array | import("@astrale-os/sdk/schema").Object | null, true, "iss", "kernel.astrale.ai:class.Identity.property.iss"> | import("@astrale-os/sdk/schema").PropertyProjection<string | number | boolean | import("@astrale-os/sdk/schema").Array | import("@astrale-os/sdk/schema").Object | null, true, "sub", "kernel.astrale.ai:class.Identity.property.sub">, import("@astrale-os/sdk/schema").MethodProjection<{
|
|
32
|
-
audience: string;
|
|
33
|
-
ttlSeconds: number;
|
|
34
|
-
attenuation: unknown;
|
|
35
|
-
}, {
|
|
36
|
-
readonly mode: 'value';
|
|
37
|
-
readonly value: string;
|
|
38
|
-
}, false, "default", "authenticated", "delegate", "kernel.astrale.ai:class.Identity.method.delegate">, import("@astrale-os/sdk/schema").MethodProjection<Record<string, never>, {
|
|
39
|
-
readonly mode: 'value';
|
|
40
|
-
readonly value: {
|
|
41
|
-
id: string;
|
|
42
|
-
issuer: string;
|
|
43
|
-
subject: string;
|
|
44
|
-
frozen: boolean;
|
|
45
|
-
requiredClaims: ({
|
|
46
|
-
claim: string;
|
|
47
|
-
op: "contains";
|
|
48
|
-
value: unknown;
|
|
49
|
-
} | {
|
|
50
|
-
claim: string;
|
|
51
|
-
op: "eq";
|
|
52
|
-
value: unknown;
|
|
53
|
-
} | {
|
|
54
|
-
claim: string;
|
|
55
|
-
op: "exists";
|
|
56
|
-
})[];
|
|
57
|
-
};
|
|
58
|
-
}, true, "default", "authenticated", "whoami", "kernel.astrale.ai:class.Identity.method.whoami"> | import("@astrale-os/sdk/schema").MethodProjection<{
|
|
59
|
-
policy: string;
|
|
60
|
-
object: string;
|
|
61
|
-
}, {
|
|
62
|
-
readonly mode: 'value';
|
|
63
|
-
readonly value: {
|
|
64
|
-
allowed: boolean;
|
|
65
|
-
};
|
|
66
|
-
}, true, "default", "authenticated", "can", "kernel.astrale.ai:class.Identity.method.can"> | import("@astrale-os/sdk/schema").MethodProjection<{
|
|
67
|
-
issuer: string;
|
|
68
|
-
subject: string;
|
|
69
|
-
}, {
|
|
70
|
-
readonly mode: 'value';
|
|
71
|
-
readonly value: {
|
|
72
|
-
id: string;
|
|
73
|
-
issuer: string;
|
|
74
|
-
subject: string;
|
|
75
|
-
frozen: boolean;
|
|
76
|
-
requiredClaims: ({
|
|
77
|
-
claim: string;
|
|
78
|
-
op: "contains";
|
|
79
|
-
value: unknown;
|
|
80
|
-
} | {
|
|
81
|
-
claim: string;
|
|
82
|
-
op: "eq";
|
|
83
|
-
value: unknown;
|
|
84
|
-
} | {
|
|
85
|
-
claim: string;
|
|
86
|
-
op: "exists";
|
|
87
|
-
})[];
|
|
88
|
-
} | null;
|
|
89
|
-
}, true, "default", "authorized", "whois", "kernel.astrale.ai:class.Identity.method.whois"> | import("@astrale-os/sdk/schema").MethodProjection<{
|
|
90
|
-
audience?: string | undefined;
|
|
91
|
-
ttlSeconds: number;
|
|
92
|
-
grant?: unknown;
|
|
93
|
-
}, {
|
|
94
|
-
readonly mode: 'value';
|
|
95
|
-
readonly value: string;
|
|
96
|
-
}, true, "default", "authorized", "mint", "kernel.astrale.ai:class.Identity.method.mint">, import("@astrale-os/sdk/schema").PropertyProjection<({
|
|
97
|
-
claim: string;
|
|
98
|
-
op: "contains";
|
|
99
|
-
value: unknown;
|
|
100
|
-
} | {
|
|
101
|
-
claim: string;
|
|
102
|
-
op: "eq";
|
|
103
|
-
value: unknown;
|
|
104
|
-
} | {
|
|
105
|
-
claim: string;
|
|
106
|
-
op: "exists";
|
|
107
|
-
})[], false, "requiredClaims", "kernel.astrale.ai:class.Identity.property.requiredClaims"> | import("@astrale-os/sdk/schema").PropertyProjection<string | number | boolean | import("@astrale-os/sdk/schema").Array | import("@astrale-os/sdk/schema").Object | null, false, "frozen", "kernel.astrale.ai:class.Identity.property.frozen"> | import("@astrale-os/sdk/schema").PropertyProjection<string | number | boolean | import("@astrale-os/sdk/schema").Array | import("@astrale-os/sdk/schema").Object | null, true, "iss", "kernel.astrale.ai:class.Identity.property.iss"> | import("@astrale-os/sdk/schema").PropertyProjection<string | number | boolean | import("@astrale-os/sdk/schema").Array | import("@astrale-os/sdk/schema").Object | null, true, "sub", "kernel.astrale.ai:class.Identity.property.sub">, import("@astrale-os/sdk/schema").MethodProjection<{
|
|
108
|
-
audience: string;
|
|
109
|
-
ttlSeconds: number;
|
|
110
|
-
attenuation: unknown;
|
|
111
|
-
}, {
|
|
112
|
-
readonly mode: 'value';
|
|
113
|
-
readonly value: string;
|
|
114
|
-
}, false, "default", "authenticated", "delegate", "kernel.astrale.ai:class.Identity.method.delegate">, import("@astrale-os/sdk/schema").MethodProjection<Record<string, never>, {
|
|
115
|
-
readonly mode: 'value';
|
|
116
|
-
readonly value: {
|
|
117
|
-
id: string;
|
|
118
|
-
issuer: string;
|
|
119
|
-
subject: string;
|
|
120
|
-
frozen: boolean;
|
|
121
|
-
requiredClaims: ({
|
|
122
|
-
claim: string;
|
|
123
|
-
op: "contains";
|
|
124
|
-
value: unknown;
|
|
125
|
-
} | {
|
|
126
|
-
claim: string;
|
|
127
|
-
op: "eq";
|
|
128
|
-
value: unknown;
|
|
129
|
-
} | {
|
|
130
|
-
claim: string;
|
|
131
|
-
op: "exists";
|
|
132
|
-
})[];
|
|
133
|
-
};
|
|
134
|
-
}, true, "default", "authenticated", "whoami", "kernel.astrale.ai:class.Identity.method.whoami"> | import("@astrale-os/sdk/schema").MethodProjection<{
|
|
135
|
-
policy: string;
|
|
136
|
-
object: string;
|
|
137
|
-
}, {
|
|
138
|
-
readonly mode: 'value';
|
|
139
|
-
readonly value: {
|
|
140
|
-
allowed: boolean;
|
|
141
|
-
};
|
|
142
|
-
}, true, "default", "authenticated", "can", "kernel.astrale.ai:class.Identity.method.can"> | import("@astrale-os/sdk/schema").MethodProjection<{
|
|
143
|
-
issuer: string;
|
|
144
|
-
subject: string;
|
|
145
|
-
}, {
|
|
146
|
-
readonly mode: 'value';
|
|
147
|
-
readonly value: {
|
|
148
|
-
id: string;
|
|
149
|
-
issuer: string;
|
|
150
|
-
subject: string;
|
|
151
|
-
frozen: boolean;
|
|
152
|
-
requiredClaims: ({
|
|
153
|
-
claim: string;
|
|
154
|
-
op: "contains";
|
|
155
|
-
value: unknown;
|
|
156
|
-
} | {
|
|
157
|
-
claim: string;
|
|
158
|
-
op: "eq";
|
|
159
|
-
value: unknown;
|
|
160
|
-
} | {
|
|
161
|
-
claim: string;
|
|
162
|
-
op: "exists";
|
|
163
|
-
})[];
|
|
164
|
-
} | null;
|
|
165
|
-
}, true, "default", "authorized", "whois", "kernel.astrale.ai:class.Identity.method.whois"> | import("@astrale-os/sdk/schema").MethodProjection<{
|
|
166
|
-
audience?: string | undefined;
|
|
167
|
-
ttlSeconds: number;
|
|
168
|
-
grant?: unknown;
|
|
169
|
-
}, {
|
|
170
|
-
readonly mode: 'value';
|
|
171
|
-
readonly value: string;
|
|
172
|
-
}, true, "default", "authorized", "mint", "kernel.astrale.ai:class.Identity.method.mint">>];
|
|
1
|
+
import { nodeClass, type Kernel } from '@astrale-os/sdk/schema';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { resolveHome } from './methods.js';
|
|
4
|
+
declare const displayName: import("@astrale-os/sdk/schema").Property<z.ZodString, {
|
|
5
|
+
readonly required: false;
|
|
6
|
+
}>;
|
|
7
|
+
export interface UserConfig {
|
|
8
|
+
readonly description: string;
|
|
9
|
+
readonly extends: readonly [Kernel['classes']['Identity']];
|
|
173
10
|
readonly properties: {
|
|
174
|
-
readonly displayName:
|
|
11
|
+
readonly displayName: typeof displayName;
|
|
175
12
|
};
|
|
176
13
|
readonly methods: {
|
|
177
|
-
readonly resolveHome:
|
|
178
|
-
readonly mode: 'value';
|
|
179
|
-
readonly value: {
|
|
180
|
-
userId: string;
|
|
181
|
-
personalSpaceId: string | null;
|
|
182
|
-
};
|
|
183
|
-
}, "authenticated", false, "default">>;
|
|
14
|
+
readonly resolveHome: typeof resolveHome;
|
|
184
15
|
};
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
}) | (import("@astrale-os/sdk/schema").ResolvedProperty<import("@astrale-os/sdk/schema").Value, true> & {
|
|
189
|
-
readonly name: "iss";
|
|
190
|
-
readonly key: "kernel.astrale.ai:class.Identity.property.iss";
|
|
191
|
-
}) | (import("@astrale-os/sdk/schema").ResolvedProperty<import("@astrale-os/sdk/schema").Value, true> & {
|
|
192
|
-
readonly name: "sub";
|
|
193
|
-
readonly key: "kernel.astrale.ai:class.Identity.property.sub";
|
|
194
|
-
});
|
|
195
|
-
readonly effectiveInstanceMethods: import("@astrale-os/sdk/schema").AuthoredMethodProjection<import("@astrale-os/sdk/schema").Method<import("@astrale-os/sdk/schema").CallableProjection<Record<string, never>, {
|
|
196
|
-
readonly mode: 'value';
|
|
197
|
-
readonly value: {
|
|
198
|
-
userId: string;
|
|
199
|
-
personalSpaceId: string | null;
|
|
200
|
-
};
|
|
201
|
-
}, "authenticated", false, "default">>, "resolveHome", "self"> | (import("@astrale-os/sdk/schema").ResolvedMethod<{
|
|
202
|
-
audience: string;
|
|
203
|
-
ttlSeconds: number;
|
|
204
|
-
attenuation: unknown;
|
|
205
|
-
}, {
|
|
206
|
-
readonly mode: 'value';
|
|
207
|
-
readonly value: string;
|
|
208
|
-
}, false, "default", "authenticated", import("@astrale-os/sdk/schema").PolicyCheckExpression<import("@astrale-os/sdk/schema").PolicyRef, import("@astrale-os/sdk/schema").PolicyCheckObject>, "kernel.astrale.ai:class.Identity.method.delegate"> & {
|
|
209
|
-
readonly name: "delegate";
|
|
210
|
-
});
|
|
211
|
-
readonly effectiveStaticMethods: (import("@astrale-os/sdk/schema").ResolvedMethod<Record<string, never>, {
|
|
212
|
-
readonly mode: 'value';
|
|
213
|
-
readonly value: {
|
|
214
|
-
id: string;
|
|
215
|
-
issuer: string;
|
|
216
|
-
subject: string;
|
|
217
|
-
frozen: boolean;
|
|
218
|
-
requiredClaims: ({
|
|
219
|
-
claim: string;
|
|
220
|
-
op: "contains";
|
|
221
|
-
value: unknown;
|
|
222
|
-
} | {
|
|
223
|
-
claim: string;
|
|
224
|
-
op: "eq";
|
|
225
|
-
value: unknown;
|
|
226
|
-
} | {
|
|
227
|
-
claim: string;
|
|
228
|
-
op: "exists";
|
|
229
|
-
})[];
|
|
230
|
-
};
|
|
231
|
-
}, true, "default", "authenticated", import("@astrale-os/sdk/schema").PolicyCheckExpression<import("@astrale-os/sdk/schema").PolicyRef, import("@astrale-os/sdk/schema").PolicyCheckObject>, "kernel.astrale.ai:class.Identity.method.whoami"> & {
|
|
232
|
-
readonly name: "whoami";
|
|
233
|
-
}) | (import("@astrale-os/sdk/schema").ResolvedMethod<{
|
|
234
|
-
policy: string;
|
|
235
|
-
object: string;
|
|
236
|
-
}, {
|
|
237
|
-
readonly mode: 'value';
|
|
238
|
-
readonly value: {
|
|
239
|
-
allowed: boolean;
|
|
240
|
-
};
|
|
241
|
-
}, true, "default", "authenticated", import("@astrale-os/sdk/schema").PolicyCheckExpression<import("@astrale-os/sdk/schema").PolicyRef, import("@astrale-os/sdk/schema").PolicyCheckObject>, "kernel.astrale.ai:class.Identity.method.can"> & {
|
|
242
|
-
readonly name: "can";
|
|
243
|
-
}) | (import("@astrale-os/sdk/schema").ResolvedMethod<{
|
|
244
|
-
issuer: string;
|
|
245
|
-
subject: string;
|
|
246
|
-
}, {
|
|
247
|
-
readonly mode: 'value';
|
|
248
|
-
readonly value: {
|
|
249
|
-
id: string;
|
|
250
|
-
issuer: string;
|
|
251
|
-
subject: string;
|
|
252
|
-
frozen: boolean;
|
|
253
|
-
requiredClaims: ({
|
|
254
|
-
claim: string;
|
|
255
|
-
op: "contains";
|
|
256
|
-
value: unknown;
|
|
257
|
-
} | {
|
|
258
|
-
claim: string;
|
|
259
|
-
op: "eq";
|
|
260
|
-
value: unknown;
|
|
261
|
-
} | {
|
|
262
|
-
claim: string;
|
|
263
|
-
op: "exists";
|
|
264
|
-
})[];
|
|
265
|
-
} | null;
|
|
266
|
-
}, true, "default", "authorized", import("@astrale-os/sdk/schema").PolicyCheckExpression<import("@astrale-os/sdk/schema").PolicyRef, import("@astrale-os/sdk/schema").PolicyCheckObject>, "kernel.astrale.ai:class.Identity.method.whois"> & {
|
|
267
|
-
readonly name: "whois";
|
|
268
|
-
}) | (import("@astrale-os/sdk/schema").ResolvedMethod<{
|
|
269
|
-
audience?: string | undefined;
|
|
270
|
-
ttlSeconds: number;
|
|
271
|
-
grant?: unknown;
|
|
272
|
-
}, {
|
|
273
|
-
readonly mode: 'value';
|
|
274
|
-
readonly value: string;
|
|
275
|
-
}, true, "default", "authorized", import("@astrale-os/sdk/schema").PolicyCheckExpression<import("@astrale-os/sdk/schema").PolicyRef, import("@astrale-os/sdk/schema").PolicyCheckObject>, "kernel.astrale.ai:class.Identity.method.mint"> & {
|
|
276
|
-
readonly name: "mint";
|
|
277
|
-
});
|
|
278
|
-
}>;
|
|
16
|
+
}
|
|
17
|
+
export declare const User: ReturnType<typeof nodeClass<UserConfig>>;
|
|
18
|
+
export {};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { K, nodeClass, property } from '@astrale-os/sdk/schema';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { resolveHome } from './methods.js';
|
|
4
|
-
|
|
4
|
+
const displayName = property(z.string().min(1).max(160), { required: false });
|
|
5
|
+
const config = {
|
|
5
6
|
description: 'One externally identified person using Shell.',
|
|
6
7
|
extends: [K.classes.Identity],
|
|
7
|
-
properties: {
|
|
8
|
-
displayName: property(z.string().min(1).max(160), { required: false }),
|
|
9
|
-
},
|
|
8
|
+
properties: { displayName },
|
|
10
9
|
methods: { resolveHome },
|
|
11
|
-
}
|
|
10
|
+
};
|
|
11
|
+
export const User = nodeClass(config);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { WorkflowContext } from '@astrale-os/sdk/workflow';
|
|
2
|
+
import type { S, Shell } from '#schema';
|
|
3
|
+
type GroupCallable = typeof S.classes.Group.self.methods.assignUser | typeof S.classes.Group.self.methods.unassignUser;
|
|
4
|
+
type GroupContext = WorkflowContext<GroupCallable, Shell>;
|
|
5
|
+
export declare function changeMembership(context: GroupContext, present: boolean): Promise<Readonly<Record<never, never>>>;
|
|
6
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { InvocationError } from '@astrale-os/sdk/execution';
|
|
2
|
+
import { changeGroupMembership } from '#mutations/group';
|
|
3
|
+
import { observeUserGroups } from '#queries/user';
|
|
4
|
+
export async function changeMembership(context, present) {
|
|
5
|
+
const observed = await context.step.run('observe-membership', () => context.query(observeUserGroups, context.input.user));
|
|
6
|
+
const wasPresent = includes(observed.groups, context.self);
|
|
7
|
+
if (wasPresent === present)
|
|
8
|
+
return Object.freeze({});
|
|
9
|
+
const result = await context.step.run('change-membership', () => context.mutate(changeGroupMembership, {
|
|
10
|
+
user: context.input.user,
|
|
11
|
+
group: context.self,
|
|
12
|
+
present,
|
|
13
|
+
guard: observed.guard,
|
|
14
|
+
}));
|
|
15
|
+
if (result.ok)
|
|
16
|
+
return Object.freeze({});
|
|
17
|
+
if (result.outcomeKnown)
|
|
18
|
+
return membershipConflict(result.code);
|
|
19
|
+
const recovered = await context.step.run('recover-membership', () => context.query(observeUserGroups, context.input.user));
|
|
20
|
+
if (includes(recovered.groups, context.self) === present)
|
|
21
|
+
return Object.freeze({});
|
|
22
|
+
throw new InvocationError('BACKEND_UNAVAILABLE', 'Group membership outcome remains unknown after exact observation.', { reason: { code: result.code, details: {} } });
|
|
23
|
+
}
|
|
24
|
+
function includes(groups, group) {
|
|
25
|
+
return groups.some(({ id }) => id === group);
|
|
26
|
+
}
|
|
27
|
+
function membershipConflict(code) {
|
|
28
|
+
throw new InvocationError('CONFLICT', 'Group membership conflicted with concurrent graph state.', {
|
|
29
|
+
reason: { code, details: {} },
|
|
30
|
+
});
|
|
31
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { setupAdminWorkflow } from './admin.js';
|
|
2
|
+
export { setupMemberWorkflow } from './member.js';
|
|
3
|
+
export { planUserSetup, type SetupConflictReason, type SetupPlan, type SetupRole } from './plan.js';
|
|
4
|
+
export { provisioningRequest, provisioningResult } from './provision.js';
|
|
5
|
+
export { runSetup } from './run.js';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Node } from '@astrale-os/sdk/graph/node';
|
|
2
|
+
import type { UserRepair } from '#mutations/user';
|
|
3
|
+
import type { UserSetupObservation } from '#queries/user';
|
|
4
|
+
import type { SetupUserInput, Shell } from '#schema';
|
|
5
|
+
export type SetupRole = 'member' | 'admin';
|
|
6
|
+
export type SetupPlan = {
|
|
7
|
+
readonly kind: 'conflict';
|
|
8
|
+
readonly reason: SetupConflictReason;
|
|
9
|
+
readonly message: string;
|
|
10
|
+
} | {
|
|
11
|
+
readonly kind: 'unchanged';
|
|
12
|
+
readonly personalSpaceId: Node['id'];
|
|
13
|
+
} | {
|
|
14
|
+
readonly kind: 'repair';
|
|
15
|
+
readonly repair: UserRepair;
|
|
16
|
+
};
|
|
17
|
+
export type SetupConflictReason = 'IDENTITY_CLASS_CONFLICT' | 'IDENTITY_FACT_CONFLICT' | 'MULTIPLE_DEFAULT_SPACES' | 'DEFAULT_SPACE_CLASS_CONFLICT' | 'AMBIGUOUS_PERSONAL_SPACE';
|
|
18
|
+
export declare function planUserSetup(domain: Shell, input: SetupUserInput, role: SetupRole, observation: UserSetupObservation): SetupPlan;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
export function planUserSetup(domain, input, role, observation) {
|
|
2
|
+
const profile = observation.profile;
|
|
3
|
+
if (profile.class !== domain.classes.User.key) {
|
|
4
|
+
return conflict('IDENTITY_CLASS_CONFLICT', 'The asserted identity already belongs to a non-Shell User Class.');
|
|
5
|
+
}
|
|
6
|
+
const identityIssuer = profile.props[domain.classes.User.properties.iss.key];
|
|
7
|
+
const identitySubject = profile.props[domain.classes.User.properties.sub.key];
|
|
8
|
+
if (identityIssuer !== input.issuer || identitySubject !== input.subject) {
|
|
9
|
+
return conflict('IDENTITY_FACT_CONFLICT', 'The resolved Shell User does not retain the asserted issuer and subject.');
|
|
10
|
+
}
|
|
11
|
+
if (observation.home.spaces.length > 1) {
|
|
12
|
+
return conflict('MULTIPLE_DEFAULT_SPACES', 'The Shell User has more than one default personal Space.');
|
|
13
|
+
}
|
|
14
|
+
const currentHome = observation.home.spaces[0];
|
|
15
|
+
if (currentHome !== undefined && currentHome.class !== domain.classes.Space.key) {
|
|
16
|
+
return conflict('DEFAULT_SPACE_CLASS_CONFLICT', 'The Shell User default target is not a Shell Space.');
|
|
17
|
+
}
|
|
18
|
+
const candidates = currentHome === undefined
|
|
19
|
+
? observation.ownedSpaces.spaces.filter((space) => space.class === domain.classes.Space.key &&
|
|
20
|
+
space.props[domain.classes.Space.properties.name.key] === input.personalSpaceName)
|
|
21
|
+
: [];
|
|
22
|
+
if (candidates.length > 1) {
|
|
23
|
+
return conflict('AMBIGUOUS_PERSONAL_SPACE', 'More than one owned Space matches the requested personal Space name.');
|
|
24
|
+
}
|
|
25
|
+
const home = currentHome ?? candidates[0];
|
|
26
|
+
const currentDisplayName = profile.props[domain.classes.User.properties.displayName.key];
|
|
27
|
+
if (currentDisplayName !== undefined && typeof currentDisplayName !== 'string') {
|
|
28
|
+
throw new TypeError('Shell User displayName is not a string.');
|
|
29
|
+
}
|
|
30
|
+
const member = hasGroup(domain, observation.groups.groups, 'core.member');
|
|
31
|
+
const admin = hasGroup(domain, observation.groups.groups, 'core.admin');
|
|
32
|
+
const ownsHome = home !== undefined && observation.ownedSpaces.spaces.some((space) => space.id === home.id);
|
|
33
|
+
let homeName;
|
|
34
|
+
if (home !== undefined) {
|
|
35
|
+
const value = home.props[domain.classes.Space.properties.name.key];
|
|
36
|
+
if (typeof value !== 'string') {
|
|
37
|
+
throw new TypeError('Shell personal Space name is not a string.');
|
|
38
|
+
}
|
|
39
|
+
homeName = value;
|
|
40
|
+
}
|
|
41
|
+
const displayName = currentDisplayName === input.displayName ? undefined : input.displayName;
|
|
42
|
+
const desiredHomeName = homeName === input.personalSpaceName ? undefined : input.personalSpaceName;
|
|
43
|
+
const addDefault = currentHome === undefined;
|
|
44
|
+
const addOwnership = home === undefined || !ownsHome;
|
|
45
|
+
const addMember = !member;
|
|
46
|
+
const addAdmin = role === 'admin' && !admin;
|
|
47
|
+
if (displayName === undefined &&
|
|
48
|
+
desiredHomeName === undefined &&
|
|
49
|
+
!addDefault &&
|
|
50
|
+
!addOwnership &&
|
|
51
|
+
!addMember &&
|
|
52
|
+
!addAdmin) {
|
|
53
|
+
return Object.freeze({ kind: 'unchanged', personalSpaceId: home.id });
|
|
54
|
+
}
|
|
55
|
+
return Object.freeze({
|
|
56
|
+
kind: 'repair',
|
|
57
|
+
repair: Object.freeze({
|
|
58
|
+
userId: profile.id,
|
|
59
|
+
...(currentDisplayName === undefined ? {} : { currentDisplayName }),
|
|
60
|
+
...(displayName === undefined ? {} : { displayName }),
|
|
61
|
+
home: home === undefined
|
|
62
|
+
? Object.freeze({ kind: 'create', name: input.personalSpaceName })
|
|
63
|
+
: Object.freeze({
|
|
64
|
+
kind: 'existing',
|
|
65
|
+
id: home.id,
|
|
66
|
+
currentName: homeName,
|
|
67
|
+
...(desiredHomeName === undefined ? {} : { name: desiredHomeName }),
|
|
68
|
+
}),
|
|
69
|
+
addDefault,
|
|
70
|
+
addOwnership,
|
|
71
|
+
addMember,
|
|
72
|
+
addAdmin,
|
|
73
|
+
guards: Object.freeze({
|
|
74
|
+
home: observation.home.guard,
|
|
75
|
+
ownedSpaces: observation.ownedSpaces.guard,
|
|
76
|
+
groups: observation.groups.guard,
|
|
77
|
+
}),
|
|
78
|
+
}),
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
function hasGroup(domain, groups, subject) {
|
|
82
|
+
return groups.some((group) => group.class === domain.classes.Group.key &&
|
|
83
|
+
group.props[domain.classes.Group.properties.iss.key] === domain.origin &&
|
|
84
|
+
group.props[domain.classes.Group.properties.sub.key] === subject);
|
|
85
|
+
}
|
|
86
|
+
function conflict(reason, message) {
|
|
87
|
+
return Object.freeze({ kind: 'conflict', reason, message });
|
|
88
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ProvisionRequest, ProvisionResult } from '@astrale-os/sdk/auth';
|
|
2
|
+
import type { SetupUserInput, SetupUserResult, Shell } from '#schema';
|
|
3
|
+
import type { SetupRole } from './plan.js';
|
|
4
|
+
export declare function provisioningRequest(domain: Shell, input: SetupUserInput, role: SetupRole): ProvisionRequest;
|
|
5
|
+
export declare function provisioningResult(result: ProvisionResult): SetupUserResult;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { issuer } from '@astrale-os/sdk/auth';
|
|
2
|
+
import { LocalBinding } from '@astrale-os/sdk/graph';
|
|
3
|
+
import { Path } from '@astrale-os/sdk/graph/path';
|
|
4
|
+
import { MutationAST } from '@astrale-os/sdk/mutation';
|
|
5
|
+
const user = LocalBinding('user');
|
|
6
|
+
const personalSpace = LocalBinding('personalSpace');
|
|
7
|
+
export function provisioningRequest(domain, input, role) {
|
|
8
|
+
const mutation = MutationAST.build((change) => {
|
|
9
|
+
const createdUser = change.createNode({
|
|
10
|
+
as: user,
|
|
11
|
+
class: domain.classes.User.key,
|
|
12
|
+
props: domain.classes.User.properties.from({ displayName: input.displayName }),
|
|
13
|
+
});
|
|
14
|
+
const createdSpace = change.createNode({
|
|
15
|
+
as: personalSpace,
|
|
16
|
+
class: domain.classes.Space.key,
|
|
17
|
+
props: domain.classes.Space.properties.from({ name: input.personalSpaceName }),
|
|
18
|
+
});
|
|
19
|
+
change.createEdge({
|
|
20
|
+
class: domain.classes.owns_space.key,
|
|
21
|
+
source: createdUser,
|
|
22
|
+
target: createdSpace,
|
|
23
|
+
});
|
|
24
|
+
change.createEdge({
|
|
25
|
+
class: domain.classes.default_space.key,
|
|
26
|
+
source: createdUser,
|
|
27
|
+
target: createdSpace,
|
|
28
|
+
});
|
|
29
|
+
change.createEdge({
|
|
30
|
+
class: domain.classes.member_of_group.key,
|
|
31
|
+
source: createdUser,
|
|
32
|
+
target: Path.project(domain.core.nodes.member.ref),
|
|
33
|
+
});
|
|
34
|
+
if (role === 'admin') {
|
|
35
|
+
change.createEdge({
|
|
36
|
+
class: domain.classes.member_of_group.key,
|
|
37
|
+
source: createdUser,
|
|
38
|
+
target: Path.project(domain.core.nodes.admin.ref),
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
return Object.freeze({
|
|
43
|
+
idempotencyKey: input.operationId,
|
|
44
|
+
mutation,
|
|
45
|
+
identities: Object.freeze({
|
|
46
|
+
[user]: Object.freeze({ issuer: issuer.accept(input.issuer), subject: input.subject }),
|
|
47
|
+
}),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
export function provisioningResult(result) {
|
|
51
|
+
const userId = result.createdNodes[user];
|
|
52
|
+
const personalSpaceId = result.createdNodes[personalSpace];
|
|
53
|
+
if (userId === undefined || personalSpaceId === undefined) {
|
|
54
|
+
throw new TypeError('Shell provisioning omitted its User or personal Space identity.');
|
|
55
|
+
}
|
|
56
|
+
return Object.freeze({ userId, personalSpaceId, changed: true });
|
|
57
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { WorkflowContext } from '@astrale-os/sdk/workflow';
|
|
2
|
+
import type { S, SetupUserResult, Shell } from '#schema';
|
|
3
|
+
import { type SetupRole } from './plan.js';
|
|
4
|
+
type SetupCallable = typeof S.functions.setupAdmin | typeof S.functions.setupMember;
|
|
5
|
+
type SetupContext = WorkflowContext<SetupCallable, Shell>;
|
|
6
|
+
export declare function runSetup(context: SetupContext, role: SetupRole): Promise<SetupUserResult>;
|
|
7
|
+
export {};
|