mirror of
https://github.com/PR0M3TH3AN/bitgate.git
synced 2026-10-27 08:31:00 +00:00
feat(core): implement authority module with role and capability management
This commit is contained in:
1 parent
2c1ae75b71
commit
919d94c7a9
2 files changed
+670
No files matched your search
@@ -0,0 +1,278 @@
|
||||
// Authority handling for Nostr Governance
|
||||
//
|
||||
// This module handles role resolution, capability checking, and authority
|
||||
// validation for the governance system.
|
||||
|
||||
/**
|
||||
* @typedef {Object} RoleDefinition
|
||||
* @property {string} name - Role name
|
||||
* @property {string[]} capabilities - Array of capability names this role has
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} Actor
|
||||
* @property {string} pubkey - 64-character hex pubkey of the actor
|
||||
* @property {string[]} roles - Array of role names assigned to this actor
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} AuthorityState
|
||||
* @property {Record<string, RoleDefinition>} roles - Map of role names to definitions
|
||||
* @property {Record<string, Actor>} actors - Map of pubkeys to actors
|
||||
*/
|
||||
|
||||
/**
|
||||
* Built-in role definitions
|
||||
* @type {Record<string, RoleDefinition>}
|
||||
*/
|
||||
export const BUILTIN_ROLES = {
|
||||
"root": {
|
||||
name: "root",
|
||||
capabilities: [
|
||||
"manage-roles",
|
||||
"manage-capabilities",
|
||||
"manage-actors",
|
||||
"manage-policies",
|
||||
"manage-admin-lists",
|
||||
"manage-trust-graph",
|
||||
"manage-overrides",
|
||||
"view-reports",
|
||||
"view-trust-graph",
|
||||
"view-admin-lists",
|
||||
"view-policies"
|
||||
]
|
||||
},
|
||||
"administrator": {
|
||||
name: "administrator",
|
||||
capabilities: [
|
||||
"manage-admin-lists",
|
||||
"manage-trust-graph",
|
||||
"view-reports",
|
||||
"view-trust-graph",
|
||||
"view-admin-lists"
|
||||
]
|
||||
},
|
||||
"moderator": {
|
||||
name: "moderator",
|
||||
capabilities: [
|
||||
"submit-reports",
|
||||
"submit-trust-endorsements",
|
||||
"view-reports"
|
||||
]
|
||||
},
|
||||
"trusted-user": {
|
||||
name: "trusted-user",
|
||||
capabilities: [
|
||||
"submit-reports",
|
||||
"view-reports"
|
||||
]
|
||||
},
|
||||
"user": {
|
||||
name: "user",
|
||||
capabilities: [
|
||||
"submit-reports"
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get capabilities for a role
|
||||
* @param {string} roleName
|
||||
* @param {AuthorityState} [authorityState]
|
||||
* @returns {string[]}
|
||||
*/
|
||||
export function getRoleCapabilities(roleName, authorityState) {
|
||||
// Check custom roles first
|
||||
if (authorityState && authorityState.roles[roleName]) {
|
||||
return authorityState.roles[roleName].capabilities;
|
||||
}
|
||||
|
||||
// Check built-in roles
|
||||
if (BUILTIN_ROLES[roleName]) {
|
||||
return BUILTIN_ROLES[roleName].capabilities;
|
||||
}
|
||||
|
||||
// Unknown role has no capabilities
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an actor has a specific role
|
||||
* @param {string} pubkey - 64-character hex pubkey
|
||||
* @param {string} roleName
|
||||
* @param {AuthorityState} [authorityState]
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function hasRole(pubkey, roleName, authorityState) {
|
||||
// Normalize pubkey
|
||||
const normalizedPubkey = pubkey.toLowerCase();
|
||||
|
||||
// Check custom actors first
|
||||
if (authorityState && authorityState.actors[normalizedPubkey]) {
|
||||
return authorityState.actors[normalizedPubkey].roles.includes(roleName);
|
||||
}
|
||||
|
||||
// No actor found means no roles
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all roles for an actor
|
||||
* @param {string} pubkey - 64-character hex pubkey
|
||||
* @param {AuthorityState} [authorityState]
|
||||
* @returns {string[]}
|
||||
*/
|
||||
export function getActorRoles(pubkey, authorityState) {
|
||||
// Normalize pubkey
|
||||
const normalizedPubkey = pubkey.toLowerCase();
|
||||
|
||||
// Check custom actors first
|
||||
if (authorityState && authorityState.actors[normalizedPubkey]) {
|
||||
return authorityState.actors[normalizedPubkey].roles;
|
||||
}
|
||||
|
||||
// No actor found means no roles
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an actor has a specific capability
|
||||
* @param {string} pubkey - 64-character hex pubkey
|
||||
* @param {string} capability
|
||||
* @param {AuthorityState} [authorityState]
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function hasCapability(pubkey, capability, authorityState) {
|
||||
// Get all roles for the actor
|
||||
const roles = getActorRoles(pubkey, authorityState);
|
||||
|
||||
// Check if any role has the capability
|
||||
for (const role of roles) {
|
||||
const capabilities = getRoleCapabilities(role, authorityState);
|
||||
if (capabilities.includes(capability)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all capabilities for an actor
|
||||
* @param {string} pubkey - 64-character hex pubkey
|
||||
* @param {AuthorityState} [authorityState]
|
||||
* @returns {string[]}
|
||||
*/
|
||||
export function getActorCapabilities(pubkey, authorityState) {
|
||||
// Get all roles for the actor
|
||||
const roles = getActorRoles(pubkey, authorityState);
|
||||
|
||||
// Collect all capabilities from all roles
|
||||
const capabilities = new Set();
|
||||
for (const role of roles) {
|
||||
const roleCapabilities = getRoleCapabilities(role, authorityState);
|
||||
for (const capability of roleCapabilities) {
|
||||
capabilities.add(capability);
|
||||
}
|
||||
}
|
||||
|
||||
return Array.from(capabilities);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new role definition
|
||||
* @param {string} name - Role name
|
||||
* @param {string[]} capabilities - Array of capability names
|
||||
* @returns {RoleDefinition}
|
||||
*/
|
||||
export function createRoleDefinition(name, capabilities) {
|
||||
// Validate input
|
||||
if (typeof name !== "string" || !name.trim()) {
|
||||
throw new Error("Role name must be a non-empty string");
|
||||
}
|
||||
|
||||
if (!Array.isArray(capabilities)) {
|
||||
throw new Error("Capabilities must be an array");
|
||||
}
|
||||
|
||||
// Validate each capability
|
||||
for (const capability of capabilities) {
|
||||
if (typeof capability !== "string" || !capability.trim()) {
|
||||
throw new Error("All capabilities must be non-empty strings");
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
name: name.trim(),
|
||||
capabilities: capabilities.map(c => c.trim())
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new actor
|
||||
* @param {string} pubkey - 64-character hex pubkey
|
||||
* @param {string[]} roles - Array of role names
|
||||
* @returns {Actor}
|
||||
*/
|
||||
export function createActor(pubkey, roles) {
|
||||
// Validate pubkey
|
||||
if (typeof pubkey !== "string" || !/^[0-9a-f]{64}$/i.test(pubkey)) {
|
||||
throw new Error("Pubkey must be a 64-character hex string");
|
||||
}
|
||||
|
||||
// Validate roles
|
||||
if (!Array.isArray(roles)) {
|
||||
throw new Error("Roles must be an array");
|
||||
}
|
||||
|
||||
// Validate each role
|
||||
for (const role of roles) {
|
||||
if (typeof role !== "string" || !role.trim()) {
|
||||
throw new Error("All roles must be non-empty strings");
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
pubkey: pubkey.toLowerCase(),
|
||||
roles: roles.map(r => r.trim())
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new authority state
|
||||
* @param {Record<string, RoleDefinition>} [roles]
|
||||
* @param {Record<string, Actor>} [actors]
|
||||
* @returns {AuthorityState}
|
||||
*/
|
||||
export function createAuthorityState(roles = {}, actors = {}) {
|
||||
// Validate roles
|
||||
for (const [name, role] of Object.entries(roles)) {
|
||||
if (typeof name !== "string" || !name.trim()) {
|
||||
throw new Error("Role names must be non-empty strings");
|
||||
}
|
||||
if (!role || typeof role !== "object") {
|
||||
throw new Error("Role definitions must be objects");
|
||||
}
|
||||
if (role.name !== name) {
|
||||
throw new Error(`Role name mismatch: ${name} !== ${role.name}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Validate actors
|
||||
for (const [pubkey, actor] of Object.entries(actors)) {
|
||||
if (typeof pubkey !== "string" || !/^[0-9a-f]{64}$/i.test(pubkey)) {
|
||||
throw new Error("Actor pubkeys must be 64-character hex strings");
|
||||
}
|
||||
if (!actor || typeof actor !== "object") {
|
||||
throw new Error("Actors must be objects");
|
||||
}
|
||||
if (actor.pubkey !== pubkey.toLowerCase()) {
|
||||
throw new Error(`Actor pubkey mismatch: ${pubkey} !== ${actor.pubkey}`);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
roles,
|
||||
actors
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,392 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import {
|
||||
BUILTIN_ROLES,
|
||||
getRoleCapabilities,
|
||||
hasRole,
|
||||
getActorRoles,
|
||||
hasCapability,
|
||||
getActorCapabilities,
|
||||
createRoleDefinition,
|
||||
createActor,
|
||||
createAuthorityState
|
||||
} from "../src/authority.js";
|
||||
|
||||
describe("authority", () => {
|
||||
describe("BUILTIN_ROLES", () => {
|
||||
it("should define built-in roles with capabilities", () => {
|
||||
expect(BUILTIN_ROLES).toHaveProperty("root");
|
||||
expect(BUILTIN_ROLES).toHaveProperty("administrator");
|
||||
expect(BUILTIN_ROLES).toHaveProperty("moderator");
|
||||
expect(BUILTIN_ROLES).toHaveProperty("trusted-user");
|
||||
expect(BUILTIN_ROLES).toHaveProperty("user");
|
||||
|
||||
// Check that each role has a name and capabilities
|
||||
for (const [name, role] of Object.entries(BUILTIN_ROLES)) {
|
||||
expect(role.name).toBe(name);
|
||||
expect(Array.isArray(role.capabilities)).toBe(true);
|
||||
expect(role.capabilities.length).toBeGreaterThan(0);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("getRoleCapabilities", () => {
|
||||
it("should return capabilities for built-in roles", () => {
|
||||
const capabilities = getRoleCapabilities("root");
|
||||
expect(capabilities).toEqual(BUILTIN_ROLES.root.capabilities);
|
||||
});
|
||||
|
||||
it("should return capabilities for custom roles", () => {
|
||||
const authorityState = createAuthorityState({
|
||||
"custom-role": {
|
||||
name: "custom-role",
|
||||
capabilities: ["custom-capability"]
|
||||
}
|
||||
});
|
||||
|
||||
const capabilities = getRoleCapabilities("custom-role", authorityState);
|
||||
expect(capabilities).toEqual(["custom-capability"]);
|
||||
});
|
||||
|
||||
it("should prefer custom roles over built-in roles", () => {
|
||||
const authorityState = createAuthorityState({
|
||||
"root": {
|
||||
name: "root",
|
||||
capabilities: ["custom-root-capability"]
|
||||
}
|
||||
});
|
||||
|
||||
const capabilities = getRoleCapabilities("root", authorityState);
|
||||
expect(capabilities).toEqual(["custom-root-capability"]);
|
||||
});
|
||||
|
||||
it("should return empty array for unknown roles", () => {
|
||||
const capabilities = getRoleCapabilities("unknown-role");
|
||||
expect(capabilities).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("hasRole", () => {
|
||||
it("should return true for actors with the specified role", () => {
|
||||
const authorityState = createAuthorityState({}, {
|
||||
"abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789": {
|
||||
pubkey: "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
||||
roles: ["moderator"]
|
||||
}
|
||||
});
|
||||
|
||||
const result = hasRole(
|
||||
"abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
||||
"moderator",
|
||||
authorityState
|
||||
);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it("should return false for actors without the specified role", () => {
|
||||
const authorityState = createAuthorityState({}, {
|
||||
"abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789": {
|
||||
pubkey: "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
||||
roles: ["user"]
|
||||
}
|
||||
});
|
||||
|
||||
const result = hasRole(
|
||||
"abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
||||
"moderator",
|
||||
authorityState
|
||||
);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it("should return false for unknown actors", () => {
|
||||
const authorityState = createAuthorityState();
|
||||
const result = hasRole(
|
||||
"abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
||||
"moderator",
|
||||
authorityState
|
||||
);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it("should normalize pubkeys to lowercase", () => {
|
||||
const authorityState = createAuthorityState({}, {
|
||||
"abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789": {
|
||||
pubkey: "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
||||
roles: ["moderator"]
|
||||
}
|
||||
});
|
||||
|
||||
const result = hasRole(
|
||||
"ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789",
|
||||
"moderator",
|
||||
authorityState
|
||||
);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getActorRoles", () => {
|
||||
it("should return roles for known actors", () => {
|
||||
const authorityState = createAuthorityState({}, {
|
||||
"abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789": {
|
||||
pubkey: "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
||||
roles: ["user", "trusted-user"]
|
||||
}
|
||||
});
|
||||
|
||||
const roles = getActorRoles(
|
||||
"abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
||||
authorityState
|
||||
);
|
||||
expect(roles).toEqual(["user", "trusted-user"]);
|
||||
});
|
||||
|
||||
it("should return empty array for unknown actors", () => {
|
||||
const authorityState = createAuthorityState();
|
||||
const roles = getActorRoles(
|
||||
"abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
||||
authorityState
|
||||
);
|
||||
expect(roles).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("hasCapability", () => {
|
||||
it("should return true for actors with the specified capability", () => {
|
||||
const authorityState = createAuthorityState({}, {
|
||||
"abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789": {
|
||||
pubkey: "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
||||
roles: ["moderator"]
|
||||
}
|
||||
});
|
||||
|
||||
const result = hasCapability(
|
||||
"abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
||||
"submit-reports",
|
||||
authorityState
|
||||
);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it("should return false for actors without the specified capability", () => {
|
||||
const authorityState = createAuthorityState({}, {
|
||||
"abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789": {
|
||||
pubkey: "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
||||
roles: ["user"]
|
||||
}
|
||||
});
|
||||
|
||||
const result = hasCapability(
|
||||
"abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
||||
"manage-admin-lists",
|
||||
authorityState
|
||||
);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it("should return false for unknown actors", () => {
|
||||
const authorityState = createAuthorityState();
|
||||
const result = hasCapability(
|
||||
"abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
||||
"submit-reports",
|
||||
authorityState
|
||||
);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getActorCapabilities", () => {
|
||||
it("should return all capabilities for an actor's roles", () => {
|
||||
const authorityState = createAuthorityState({}, {
|
||||
"abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789": {
|
||||
pubkey: "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
||||
roles: ["moderator", "trusted-user"]
|
||||
}
|
||||
});
|
||||
|
||||
const capabilities = getActorCapabilities(
|
||||
"abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
||||
authorityState
|
||||
);
|
||||
|
||||
// Should have capabilities from both roles, with duplicates removed
|
||||
expect(capabilities).toContain("submit-reports");
|
||||
expect(capabilities).toContain("view-reports");
|
||||
expect(capabilities).toContain("submit-trust-endorsements");
|
||||
});
|
||||
|
||||
it("should return empty array for unknown actors", () => {
|
||||
const authorityState = createAuthorityState();
|
||||
const capabilities = getActorCapabilities(
|
||||
"abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
||||
authorityState
|
||||
);
|
||||
expect(capabilities).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("createRoleDefinition", () => {
|
||||
it("should create a valid role definition", () => {
|
||||
const role = createRoleDefinition("test-role", ["capability1", "capability2"]);
|
||||
expect(role).toEqual({
|
||||
name: "test-role",
|
||||
capabilities: ["capability1", "capability2"]
|
||||
});
|
||||
});
|
||||
|
||||
it("should trim whitespace from role name and capabilities", () => {
|
||||
const role = createRoleDefinition(" test-role ", [" capability1 ", " capability2 "]);
|
||||
expect(role).toEqual({
|
||||
name: "test-role",
|
||||
capabilities: ["capability1", "capability2"]
|
||||
});
|
||||
});
|
||||
|
||||
it("should throw error for invalid role name", () => {
|
||||
expect(() => createRoleDefinition("", ["capability"])).toThrow();
|
||||
expect(() => createRoleDefinition(/** @type {any} */ (123), ["capability"])).toThrow();
|
||||
});
|
||||
|
||||
it("should throw error for invalid capabilities", () => {
|
||||
expect(() => createRoleDefinition("test-role", /** @type {any} */ ("not-an-array"))).toThrow();
|
||||
expect(() => createRoleDefinition("test-role", [/** @type {any} */ (123)])).toThrow();
|
||||
expect(() => createRoleDefinition("test-role", [""])).toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe("createActor", () => {
|
||||
it("should create a valid actor", () => {
|
||||
const actor = createActor(
|
||||
"abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
||||
["role1", "role2"]
|
||||
);
|
||||
expect(actor).toEqual({
|
||||
pubkey: "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
||||
roles: ["role1", "role2"]
|
||||
});
|
||||
});
|
||||
|
||||
it("should normalize pubkey to lowercase", () => {
|
||||
const actor = createActor(
|
||||
"ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789",
|
||||
["role1"]
|
||||
);
|
||||
expect(actor.pubkey).toBe("abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789");
|
||||
});
|
||||
|
||||
it("should trim whitespace from roles", () => {
|
||||
const actor = createActor(
|
||||
"abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
||||
[" role1 ", " role2 "]
|
||||
);
|
||||
expect(actor.roles).toEqual(["role1", "role2"]);
|
||||
});
|
||||
|
||||
it("should throw error for invalid pubkey", () => {
|
||||
expect(() => createActor("invalid-pubkey", ["role"])).toThrow();
|
||||
expect(() => createActor(/** @type {any} */ (123), ["role"])).toThrow();
|
||||
expect(() => createActor("", ["role"])).toThrow();
|
||||
});
|
||||
|
||||
it("should throw error for invalid roles", () => {
|
||||
expect(() => createActor(
|
||||
"abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
||||
/** @type {any} */ ("not-an-array")
|
||||
)).toThrow();
|
||||
expect(() => createActor(
|
||||
"abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
||||
[/** @type {any} */ (123)]
|
||||
)).toThrow();
|
||||
expect(() => createActor(
|
||||
"abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
||||
[""]
|
||||
)).toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe("createAuthorityState", () => {
|
||||
it("should create a valid authority state", () => {
|
||||
const roles = {
|
||||
"test-role": {
|
||||
name: "test-role",
|
||||
capabilities: ["test-capability"]
|
||||
}
|
||||
};
|
||||
|
||||
const actors = {
|
||||
"abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789": {
|
||||
pubkey: "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
|
||||
roles: ["test-role"]
|
||||
}
|
||||
};
|
||||
|
||||
const state = createAuthorityState(roles, actors);
|
||||
expect(state).toEqual({ roles, actors });
|
||||
});
|
||||
|
||||
it("should create empty authority state with no arguments", () => {
|
||||
const state = createAuthorityState();
|
||||
expect(state).toEqual({ roles: {}, actors: {} });
|
||||
});
|
||||
|
||||
it("should validate role names", () => {
|
||||
const roles = {
|
||||
"": {
|
||||
name: "",
|
||||
capabilities: ["test-capability"]
|
||||
}
|
||||
};
|
||||
|
||||
expect(() => createAuthorityState(roles)).toThrow();
|
||||
});
|
||||
|
||||
it("should validate role definitions", () => {
|
||||
const roles = {
|
||||
"test-role": /** @type {any} */ (null)
|
||||
};
|
||||
|
||||
expect(() => createAuthorityState(roles)).toThrow();
|
||||
});
|
||||
|
||||
it("should validate role name consistency", () => {
|
||||
const roles = {
|
||||
"test-role": {
|
||||
name: "different-name",
|
||||
capabilities: ["test-capability"]
|
||||
}
|
||||
};
|
||||
|
||||
expect(() => createAuthorityState(roles)).toThrow();
|
||||
});
|
||||
|
||||
it("should validate actor pubkeys", () => {
|
||||
const actors = {
|
||||
"invalid-pubkey": {
|
||||
pubkey: "invalid-pubkey",
|
||||
roles: ["test-role"]
|
||||
}
|
||||
};
|
||||
|
||||
expect(() => createAuthorityState({}, actors)).toThrow();
|
||||
});
|
||||
|
||||
it("should validate actors", () => {
|
||||
const actors = {
|
||||
"abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789": /** @type {any} */ (null)
|
||||
};
|
||||
|
||||
expect(() => createAuthorityState({}, actors)).toThrow();
|
||||
});
|
||||
|
||||
it("should validate actor pubkey consistency", () => {
|
||||
const actors = {
|
||||
"abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789": {
|
||||
pubkey: "different-pubkey",
|
||||
roles: ["test-role"]
|
||||
}
|
||||
};
|
||||
|
||||
expect(() => createAuthorityState({}, actors)).toThrow();
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user