@helyx/core 0.1.16 → 0.1.18
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 +32 -0
- package/dist/index.d.ts +23 -2
- package/dist/index.js +104 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.18
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Add the private testing-stage Forms module contracts and runtime integration,
|
|
8
|
+
and introduce server-configurable Helyx Administrator, Moderator, dashboard
|
|
9
|
+
access, and command-permission policies with fresh Discord authorization.
|
|
10
|
+
|
|
11
|
+
## 0.1.17
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- Accept compatible internal Helyx releases within explicit minor-safe pre-1.0 or major-safe stable ranges, preventing dependency-only patch cascades.---
|
|
16
|
+
"@helyx/bot": patch
|
|
17
|
+
"@helyx/cli": patch
|
|
18
|
+
"@helyx/core": patch
|
|
19
|
+
"@helyx/framework": patch
|
|
20
|
+
"@helyx/platform": patch
|
|
21
|
+
"@helyx/sdk": patch
|
|
22
|
+
"@helyx/module-account-gate": patch
|
|
23
|
+
"@helyx/module-feedback": patch
|
|
24
|
+
"@helyx/module-giveaways": patch
|
|
25
|
+
"@helyx/module-levels": patch
|
|
26
|
+
"@helyx/module-logging": patch
|
|
27
|
+
"@helyx/module-polls": patch
|
|
28
|
+
"@helyx/module-reactionroles": patch
|
|
29
|
+
"@helyx/module-suggestions": patch
|
|
30
|
+
"@helyx/module-welcome": patch
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
Accept compatible internal Helyx releases within explicit minor-safe pre-1.0 or major-safe stable ranges, preventing dependency-only patch cascades.
|
|
34
|
+
|
|
3
35
|
## 0.1.16
|
|
4
36
|
|
|
5
37
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { HealthResult, Logger, ModuleDefinition, ModulePermissionConfiguration, PermissionActor, PermissionPolicy, ServiceAccess } from "@helyx/sdk";
|
|
1
|
+
import type { HealthResult, Logger, ModuleDefinition, ModulePermissionConfiguration, PermissionActor, GuildAccessPolicy, HelyxAccessLevel, PermissionPolicy, ServiceAccess } from "@helyx/sdk";
|
|
2
2
|
export type RuntimeState = "created" | "starting" | "running" | "stopping" | "stopped" | "failed";
|
|
3
3
|
export interface ModuleHealth {
|
|
4
4
|
id: string;
|
|
@@ -25,5 +25,26 @@ export declare class HelyxRuntime {
|
|
|
25
25
|
}
|
|
26
26
|
export declare function safeError(error: unknown): Record<string, unknown>;
|
|
27
27
|
export declare function resolveCommandPermissionPolicy(configuration: ModulePermissionConfiguration, commandName: string): PermissionPolicy;
|
|
28
|
-
export declare function canUseCommand(actor: PermissionActor, policy: PermissionPolicy): boolean;
|
|
28
|
+
export declare function canUseCommand(actor: PermissionActor, policy: PermissionPolicy, guildAccess?: GuildAccessPolicy): boolean;
|
|
29
|
+
export type HelyxAuthority = "owner" | "administrator" | "moderator" | "member";
|
|
30
|
+
export declare function resolveHelyxAuthority(actor: PermissionActor, policy: GuildAccessPolicy): HelyxAuthority;
|
|
31
|
+
export declare function hasHelyxAccessLevel(actor: PermissionActor, level: HelyxAccessLevel, policy?: GuildAccessPolicy): boolean;
|
|
32
|
+
export declare function canAccessGuildDashboard(actor: PermissionActor, policy: GuildAccessPolicy): boolean;
|
|
33
|
+
export type PermissionTargetLevel = HelyxAccessLevel | "everyone";
|
|
34
|
+
export type PermissionTargetDecision = {
|
|
35
|
+
allowed: true;
|
|
36
|
+
} | {
|
|
37
|
+
allowed: false;
|
|
38
|
+
reason: "administrator_required" | "moderator_required";
|
|
39
|
+
};
|
|
40
|
+
export declare function canAssignPermissionTarget(actor: PermissionActor, target: PermissionTargetLevel, policy: GuildAccessPolicy): PermissionTargetDecision;
|
|
41
|
+
export type PermissionMutationDenialReason = "current_policy_required" | "administrator_required" | "moderator_required" | "selected_role_too_high" | "policy_would_broaden";
|
|
42
|
+
export type PermissionMutationDecision = {
|
|
43
|
+
allowed: true;
|
|
44
|
+
} | {
|
|
45
|
+
allowed: false;
|
|
46
|
+
reason: PermissionMutationDenialReason;
|
|
47
|
+
};
|
|
48
|
+
export declare function permissionMutationDenialMessage(reason: PermissionMutationDenialReason): string;
|
|
49
|
+
export declare function canMutatePermissionPolicy(actor: PermissionActor, current: PermissionPolicy, target: PermissionPolicy, guildAccess: GuildAccessPolicy, rolePositions?: Readonly<Record<string, number>>): PermissionMutationDecision;
|
|
29
50
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -155,7 +155,7 @@ function toError(error) {
|
|
|
155
155
|
export function resolveCommandPermissionPolicy(configuration, commandName) {
|
|
156
156
|
return configuration.commands[commandName] ?? configuration.module;
|
|
157
157
|
}
|
|
158
|
-
export function canUseCommand(actor, policy) {
|
|
158
|
+
export function canUseCommand(actor, policy, guildAccess) {
|
|
159
159
|
if (actor.isServerOwner || actor.isAdministrator)
|
|
160
160
|
return true;
|
|
161
161
|
if (policy.deniedUserIds.includes(actor.userId))
|
|
@@ -166,9 +166,112 @@ export function canUseCommand(actor, policy) {
|
|
|
166
166
|
return false;
|
|
167
167
|
if (actor.roleIds.some((roleId) => policy.allowedRoleIds.includes(roleId)))
|
|
168
168
|
return true;
|
|
169
|
+
if (policy.accessLevel &&
|
|
170
|
+
hasHelyxAccessLevel(actor, policy.accessLevel, guildAccess))
|
|
171
|
+
return true;
|
|
169
172
|
if (policy.requiredPermissions.length > 0 &&
|
|
170
173
|
policy.requiredPermissions.every((permission) => actor.permissions.includes(permission)))
|
|
171
174
|
return true;
|
|
172
175
|
return policy.everyone;
|
|
173
176
|
}
|
|
177
|
+
export function resolveHelyxAuthority(actor, policy) {
|
|
178
|
+
if (actor.isServerOwner)
|
|
179
|
+
return "owner";
|
|
180
|
+
if (actor.isAdministrator ||
|
|
181
|
+
actor.roleIds.some((roleId) => policy.administratorRoleIds.includes(roleId)))
|
|
182
|
+
return "administrator";
|
|
183
|
+
if (actor.permissions.includes("MANAGE_GUILD") ||
|
|
184
|
+
actor.roleIds.some((roleId) => policy.moderatorRoleIds.includes(roleId)))
|
|
185
|
+
return "moderator";
|
|
186
|
+
return "member";
|
|
187
|
+
}
|
|
188
|
+
export function hasHelyxAccessLevel(actor, level, policy) {
|
|
189
|
+
if (actor.isServerOwner || actor.isAdministrator)
|
|
190
|
+
return true;
|
|
191
|
+
if (level === "moderator" && actor.permissions.includes("MANAGE_GUILD"))
|
|
192
|
+
return true;
|
|
193
|
+
if (!policy)
|
|
194
|
+
return false;
|
|
195
|
+
const authority = resolveHelyxAuthority(actor, policy);
|
|
196
|
+
return level === "administrator"
|
|
197
|
+
? authority === "owner" || authority === "administrator"
|
|
198
|
+
: authority !== "member";
|
|
199
|
+
}
|
|
200
|
+
export function canAccessGuildDashboard(actor, policy) {
|
|
201
|
+
if (actor.isServerOwner || actor.isAdministrator)
|
|
202
|
+
return true;
|
|
203
|
+
if (actor.roleIds.some((roleId) => policy.dashboardDeniedRoleIds.includes(roleId)))
|
|
204
|
+
return false;
|
|
205
|
+
if (actor.roleIds.some((roleId) => policy.administratorRoleIds.includes(roleId)))
|
|
206
|
+
return true;
|
|
207
|
+
if (policy.dashboardModeratorsEnabled &&
|
|
208
|
+
hasHelyxAccessLevel(actor, "moderator", policy))
|
|
209
|
+
return true;
|
|
210
|
+
return actor.roleIds.some((roleId) => policy.dashboardAllowedRoleIds.includes(roleId));
|
|
211
|
+
}
|
|
212
|
+
export function canAssignPermissionTarget(actor, target, policy) {
|
|
213
|
+
const authority = resolveHelyxAuthority(actor, policy);
|
|
214
|
+
if (authority === "owner" || authority === "administrator")
|
|
215
|
+
return { allowed: true };
|
|
216
|
+
if (authority === "moderator")
|
|
217
|
+
return target === "everyone"
|
|
218
|
+
? { allowed: false, reason: "administrator_required" }
|
|
219
|
+
: { allowed: true };
|
|
220
|
+
return { allowed: false, reason: "moderator_required" };
|
|
221
|
+
}
|
|
222
|
+
export function permissionMutationDenialMessage(reason) {
|
|
223
|
+
return {
|
|
224
|
+
current_policy_required: "You cannot edit a permission policy you are not authorised to use.",
|
|
225
|
+
administrator_required: "Only a Helyx Administrator can grant access to everyone.",
|
|
226
|
+
moderator_required: "Helyx Moderator access is required for this permission target.",
|
|
227
|
+
selected_role_too_high: "Selected roles must be below your highest Discord role.",
|
|
228
|
+
policy_would_broaden: "This change would broaden the policy beyond your authority.",
|
|
229
|
+
}[reason];
|
|
230
|
+
}
|
|
231
|
+
export function canMutatePermissionPolicy(actor, current, target, guildAccess, rolePositions = {}) {
|
|
232
|
+
const authority = resolveHelyxAuthority(actor, guildAccess);
|
|
233
|
+
const administrator = authority === "owner" || authority === "administrator";
|
|
234
|
+
const moderator = authority === "moderator";
|
|
235
|
+
const qualifiesForCurrent = canUseCommand(actor, current, guildAccess);
|
|
236
|
+
if (!administrator && !moderator && !qualifiesForCurrent)
|
|
237
|
+
return { allowed: false, reason: "current_policy_required" };
|
|
238
|
+
if (!administrator && moderator && !current.everyone && !qualifiesForCurrent)
|
|
239
|
+
return { allowed: false, reason: "current_policy_required" };
|
|
240
|
+
const targetLevel = permissionPolicyTarget(target);
|
|
241
|
+
if (!administrator && targetLevel === "everyone")
|
|
242
|
+
return { allowed: false, reason: "administrator_required" };
|
|
243
|
+
if (!administrator && !moderator && targetLevel !== "custom")
|
|
244
|
+
return { allowed: false, reason: "moderator_required" };
|
|
245
|
+
const currentAllowed = new Set(current.allowedRoleIds);
|
|
246
|
+
const currentDenied = new Set(current.deniedRoleIds);
|
|
247
|
+
const selectedRoleIds = [
|
|
248
|
+
...target.allowedRoleIds.filter((roleId) => !currentAllowed.has(roleId)),
|
|
249
|
+
...target.deniedRoleIds.filter((roleId) => !currentDenied.has(roleId)),
|
|
250
|
+
];
|
|
251
|
+
if (selectedRoleIds.some((roleId) => {
|
|
252
|
+
const position = rolePositions[roleId];
|
|
253
|
+
return (position === undefined ||
|
|
254
|
+
actor.highestRolePosition === undefined ||
|
|
255
|
+
position >= actor.highestRolePosition);
|
|
256
|
+
}))
|
|
257
|
+
return { allowed: false, reason: "selected_role_too_high" };
|
|
258
|
+
if (!administrator && !moderator) {
|
|
259
|
+
const targetDenied = new Set(target.deniedRoleIds);
|
|
260
|
+
if (target.allowedRoleIds.some((roleId) => !currentAllowed.has(roleId)) ||
|
|
261
|
+
current.deniedRoleIds.some((roleId) => !targetDenied.has(roleId)))
|
|
262
|
+
return { allowed: false, reason: "policy_would_broaden" };
|
|
263
|
+
}
|
|
264
|
+
return { allowed: true };
|
|
265
|
+
}
|
|
266
|
+
function permissionPolicyTarget(policy) {
|
|
267
|
+
if (policy.everyone)
|
|
268
|
+
return "everyone";
|
|
269
|
+
if (policy.accessLevel)
|
|
270
|
+
return policy.accessLevel;
|
|
271
|
+
if (policy.requiredPermissions.includes("ADMINISTRATOR"))
|
|
272
|
+
return "administrator";
|
|
273
|
+
if (policy.requiredPermissions.includes("MANAGE_GUILD"))
|
|
274
|
+
return "moderator";
|
|
275
|
+
return "custom";
|
|
276
|
+
}
|
|
174
277
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@helyx/core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.18",
|
|
4
4
|
"description": "Module lifecycle and runtime registry for Helyx.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"helyx",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"test": "vitest run"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@helyx/module-manifest": "0.6.0",
|
|
51
|
-
"@helyx/sdk": "0.6.
|
|
50
|
+
"@helyx/module-manifest": ">=0.6.0 <0.7.0",
|
|
51
|
+
"@helyx/sdk": ">=0.6.0 <0.7.0"
|
|
52
52
|
}
|
|
53
53
|
}
|