@helyx/core 0.1.17 → 0.1.19

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 CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.19
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+ - @helyx/sdk@0.7.0
9
+
10
+ ## 0.1.18
11
+
12
+ ### Patch Changes
13
+
14
+ - Add the private testing-stage Forms module contracts and runtime integration,
15
+ and introduce server-configurable Helyx Administrator, Moderator, dashboard
16
+ access, and command-permission policies with fresh Discord authorization.
17
+
3
18
  ## 0.1.17
4
19
 
5
20
  ### 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.17",
3
+ "version": "0.1.19",
4
4
  "description": "Module lifecycle and runtime registry for Helyx.",
5
5
  "keywords": [
6
6
  "helyx",
@@ -48,6 +48,6 @@
48
48
  },
49
49
  "dependencies": {
50
50
  "@helyx/module-manifest": ">=0.6.0 <0.7.0",
51
- "@helyx/sdk": ">=0.6.0 <0.7.0"
51
+ "@helyx/sdk": ">=0.7.0 <0.8.0"
52
52
  }
53
53
  }