Blockstream Enterprise
RecipesRoles rules

Role Management

Creating a Role

const createRoleResult = await broadcastRequest({
  action: 'add',
  resource: '/roles',
  details: {
    rid: uuidv4(),
    name: 'custom-role',
    description: 'Custom role for specific operations',
  },
})

const roleId = createRoleResult.details.rid

Adding Rules to a Role

// Add multiple rules to a role
const addRulesResult = await broadcastRequest({
  action: 'edit',
  resource: `/roles/${roleId}/rules/add`,
  details: {
    rules: [ruleId1, ruleId2, ruleId3],
  },
})

Removing Rules from a Role

const removeRulesResult = await broadcastRequest({
  action: 'edit',
  resource: `/roles/${roleId}/rules/remove`,
  details: {
    rules: [ruleId1],
  },
})

Listing Roles

const rolesResult = await broadcastRequest({
  action: 'get',
  resource: '/roles',
  details: {
    filters: {
      name: 'admin', // Optional: filter by name
    },
  },
})

const roles = rolesResult.details

Getting Role Details

const roleDetails = await broadcastRequest({
  action: 'get',
  resource: `/roles/${roleId}`,
  details: {},
})

console.log('Role:', roleDetails.details.name)
console.log('Rules:', roleDetails.details.rules)

User Role Assignment

Assigning a User to a Role

const assignResult = await broadcastRequest({
  action: 'edit',
  resource: `/roles/${roleId}/users/add`,
  details: {
    users: [userId1, userId2],
  },
})

Removing a User from a Role

const removeResult = await broadcastRequest({
  action: 'edit',
  resource: `/roles/${roleId}/users/remove`,
  details: {
    users: [userId1],
  },
})

Creating User with Roles

// Create user and assign roles in one operation
const userResult = await broadcastRequest({
  action: 'add',
  resource: '/users',
  details: {
    uid: uuidv4(),
    email: 'user@example.com',
    first_name: 'John',
    last_name: 'Doe',
    ecdsa_pubkey: userKeys.ecdsa.publicKeyHex,
    rsa_pubkey: userKeys.rsa.publicKeyPem,
    type: 'api',
  },
})

// Then assign to role
await broadcastRequest({
  action: 'edit',
  resource: `/roles/${roleId}/users/add`,
  details: {
    users: [userResult.details.uid],
  },
})

Permission Examples by Role

Super Admin

Full access to everything:

const superAdminPermissions = {
  roleIdentifier: 'super-admin',
  permissions: [
    {
      permissionIdentifier: 'p1',
      description: 'View Everything & Edit everything',
      rules: [{ resource: '*', action: '*' }],
    },
  ],
}

Workspace Owner with Approval Filter

Workspace owners can approve proposals, but only for workspace-level resources:

const workspaceOwnerPermissions = {
  roleIdentifier: 'workspace-owner',
  permissions: [
    {
      permissionIdentifier: 'p1',
      description: 'View workspace resources',
      rules: [
        { resource: '/users', action: 'list' },
        { resource: '/users', action: 'get' },
        { resource: '/signers', action: 'list' },
        { resource: '/signers', action: 'get' },
        { resource: '/wallets', action: 'list' },
        { resource: '/wallets', action: 'get' },
        { resource: '/policies', action: 'list' },
        { resource: '/policies', action: 'get' },
        { resource: '/roles', action: 'list' },
        { resource: '/roles', action: 'get' },
        { resource: '/rules', action: 'list' },
        { resource: '/rules', action: 'get' },
        { resource: '/groups', action: 'list' },
        { resource: '/groups', action: 'get' },
        { resource: '/recipients', action: 'list' },
        { resource: '/recipients', action: 'get' },
        { resource: '/recipient-groups', action: 'list' },
        { resource: '/recipient-groups', action: 'get' },
      ],
    },
    {
      permissionIdentifier: 'p2',
      description: 'Approve workspace proposals',
      rules: [
        {
          resource: '/proposals',
          action: 'approve',
          // Filter: only proposals affecting workspace resources
          filter: `proposal.resource IN ['/users', '/signers', '/roles', '/policies', '/wallets', '/groups', '/recipients', '/recipient-groups', '/assets']`,
        },
      ],
    },
  ],
}

Workspace Maintainer

Manage workspace resources:

const workspaceMaintainerPermissions = {
  roleIdentifier: 'workspace-maintainer',
  permissions: [
    {
      permissionIdentifier: 'p1',
      description: 'View workspace resources',
      rules: [
        { resource: '/users', action: 'list' },
        { resource: '/users', action: 'get' },
        { resource: '/signers', action: 'list' },
        { resource: '/signers', action: 'get' },
        { resource: '/wallets', action: 'list' },
        { resource: '/wallets', action: 'get' },
        { resource: '/policies', action: 'list' },
        { resource: '/policies', action: 'get' },
        { resource: '/roles', action: 'list' },
        { resource: '/roles', action: 'get' },
        { resource: '/rules', action: 'list' },
        { resource: '/rules', action: 'get' },
        { resource: '/groups', action: 'list' },
        { resource: '/groups', action: 'get' },
        { resource: '/recipients', action: 'list' },
        { resource: '/recipients', action: 'get' },
        { resource: '/recipient-groups', action: 'list' },
        { resource: '/recipient-groups', action: 'get' },
        { resource: '/assets', action: 'list' },
        { resource: '/assets', action: 'get' },
      ],
    },
    {
      permissionIdentifier: 'p2',
      description: 'Propose changes to workspace resources',
      rules: [
        // Users
        { resource: '/users', action: 'invite' },
        { resource: '/users', action: 'create' },
        { resource: '/users', action: 'edit' },
        { resource: '/users', action: 'delete' },
        // Rules
        { resource: '/rules', action: 'create' },
        // Roles
        { resource: '/roles', action: 'create' },
        { resource: '/roles', action: 'addRules' },
        { resource: '/roles', action: 'removeRules' },
        { resource: '/roles', action: 'addUsers' },
        { resource: '/roles', action: 'removeUsers' },
        { resource: '/roles', action: 'delete' },
        // Groups
        { resource: '/groups', action: 'create' },
        { resource: '/groups', action: 'edit' },
        { resource: '/groups', action: 'delete' },
        { resource: '/groups', action: 'addUsers' },
        { resource: '/groups', action: 'removeUsers' },
        // Recipients
        { resource: '/recipients', action: 'create' },
        { resource: '/recipients', action: 'edit' },
        { resource: '/recipients', action: 'delete' },
        // Recipient Groups
        { resource: '/recipient-groups', action: 'create' },
        { resource: '/recipient-groups', action: 'edit' },
        { resource: '/recipient-groups', action: 'delete' },
        { resource: '/recipient-groups', action: 'addRecipients' },
        { resource: '/recipient-groups', action: 'removeRecipients' },
        // Assets
        { resource: '/assets', action: 'edit' },
        // Signers
        { resource: '/signers', action: 'create' },
        { resource: '/signers', action: 'edit' },
        { resource: '/signers', action: 'delete' },
        // Wallets
        { resource: '/wallets', action: 'create' },
        { resource: '/wallets', action: 'edit' },
        { resource: '/wallets', action: 'delete' },
        // Policies
        { resource: '/policies', action: 'create' },
        { resource: '/policies', action: 'edit' },
        { resource: '/policies', action: 'delete' },
      ],
    },
  ],
}

Wallet Maintainer (Per-Wallet Access)

Dynamic rules based on assigned wallets:

function getWalletMaintainerRules(walletId: string) {
  return {
    roleIdentifier: 'wallet-maintainer',
    permissions: [
      {
        permissionIdentifier: 'p1',
        description: 'View wallet resources',
        rules: [
          { resource: `/wallets/${walletId}`, action: 'get' },
          { resource: `/wallets/${walletId}/balances`, action: 'get' },
          { resource: `/wallets/${walletId}/addresses`, action: 'get' },
          { resource: `/wallets/${walletId}/addresses`, action: 'list' },
          { resource: `/wallets/${walletId}/transactions`, action: 'get' },
          { resource: `/wallets/${walletId}/transactions`, action: 'list' },
          { resource: `/wallets/${walletId}/spend-requests`, action: 'list' },
          { resource: `/wallets/${walletId}/spend-requests`, action: 'get' },
        ],
      },
      {
        permissionIdentifier: 'p2',
        description: 'Create spend requests',
        rules: [{ resource: `/wallets/${walletId}/spend-requests`, action: 'add' }],
      },
      {
        permissionIdentifier: 'p3',
        description: 'Review and approve proposals',
        rules: [
          {
            resource: '/proposals',
            action: 'review',
            filter: `proposal.wallet_id == '${walletId}'`,
          },
          {
            resource: '/proposals',
            action: 'approve',
            filter: `proposal.wallet_id == '${walletId}'`,
          },
        ],
      },
      {
        permissionIdentifier: 'p4',
        description: 'Manage wallet settings',
        rules: [
          { resource: `/wallets/${walletId}`, action: 'edit' },
          { resource: `/wallets/${walletId}/policies`, action: 'create' },
          { resource: `/wallets/${walletId}/policies`, action: 'edit' },
          { resource: `/wallets/${walletId}/policies`, action: 'delete' },
        ],
      },
    ],
  }
}

Standard Wallet User (Per-Wallet Access)

function getStandardWalletUserRules(walletId: string) {
  return {
    roleIdentifier: 'standard-wallet-user',
    permissions: [
      {
        permissionIdentifier: 'p1',
        description: 'View wallet resources',
        rules: [
          { resource: `/wallets/${walletId}`, action: 'get' },
          { resource: `/wallets/${walletId}/balances`, action: 'get' },
          { resource: `/wallets/${walletId}/addresses`, action: 'get' },
          { resource: `/wallets/${walletId}/addresses`, action: 'list' },
          { resource: `/wallets/${walletId}/transactions`, action: 'get' },
          { resource: `/wallets/${walletId}/transactions`, action: 'list' },
          { resource: `/wallets/${walletId}/spend-requests`, action: 'list' },
          { resource: `/wallets/${walletId}/spend-requests`, action: 'get' },
        ],
      },
      {
        permissionIdentifier: 'p2',
        description: 'Create spend requests',
        rules: [{ resource: `/wallets/${walletId}/spend-requests`, action: 'add' }],
      },
      {
        permissionIdentifier: 'p3',
        description: 'Review proposals',
        rules: [
          {
            resource: '/proposals',
            action: 'review',
            filter: `proposal.wallet_id == '${walletId}'`,
          },
        ],
      },
    ],
  }
}

Wallet Viewer (Per-Wallet Access)

function getWalletViewerRules(walletId: string) {
  return {
    roleIdentifier: 'wallet-viewer',
    permissions: [
      {
        permissionIdentifier: 'p1',
        description: 'View wallet resources',
        rules: [
          { resource: `/wallets/${walletId}`, action: 'get' },
          { resource: `/wallets/${walletId}/balances`, action: 'get' },
          { resource: `/wallets/${walletId}/addresses`, action: 'get' },
          { resource: `/wallets/${walletId}/addresses`, action: 'list' },
          { resource: `/wallets/${walletId}/transactions`, action: 'get' },
          { resource: `/wallets/${walletId}/transactions`, action: 'list' },
          { resource: `/wallets/${walletId}/spend-requests`, action: 'list' },
          { resource: `/wallets/${walletId}/spend-requests`, action: 'get' },
        ],
      },
    ],
  }
}

Dynamic Wallet Role Assignment

Wallet-level roles (Wallet Maintainer, Standard Wallet User, Wallet Viewer) are dynamically assigned per wallet. When a user is granted a wallet role, the system generates rules specific to that wallet ID.

Role Assignment Generated Rules User R /wallets/ABC-123 : get /wallets/ABC-123/balances : get /wallets/ABC-123/spend-requests : add /proposals : approvefilter: wallet_id='ABC-123'

Assigning Wallet Roles

// 1. Create wallet-specific rules
const walletId = 'abc-123-def'
const rules = []

// Create view rule
const viewRule = await broadcastRequest({
  action: 'add',
  resource: '/rules',
  details: {
    rlid: uuidv4(),
    name: `view-wallet-${walletId}`,
    resource: `/wallets/${walletId}`,
    action: 'get',
    description: `View wallet ${walletId}`,
  },
})
rules.push(viewRule.details.rlid)

// Create balance rule
const balanceRule = await broadcastRequest({
  action: 'add',
  resource: '/rules',
  details: {
    rlid: uuidv4(),
    name: `view-wallet-${walletId}-balances`,
    resource: `/wallets/${walletId}/balances`,
    action: 'get',
    description: `View balances for wallet ${walletId}`,
  },
})
rules.push(balanceRule.details.rlid)

// Create spend-request rule
const spendRule = await broadcastRequest({
  action: 'add',
  resource: '/rules',
  details: {
    rlid: uuidv4(),
    name: `spend-wallet-${walletId}`,
    resource: `/wallets/${walletId}/spend-requests`,
    action: 'add',
    description: `Create spend requests for wallet ${walletId}`,
  },
})
rules.push(spendRule.details.rlid)

// 2. Create role for wallet access
const walletRole = await broadcastRequest({
  action: 'add',
  resource: '/roles',
  details: {
    rid: uuidv4(),
    name: `wallet-${walletId}-user`,
    description: `Standard user access to wallet ${walletId}`,
  },
})

// 3. Add rules to role
await broadcastRequest({
  action: 'edit',
  resource: `/roles/${walletRole.details.rid}/rules/add`,
  details: {
    rules: rules,
  },
})

// 4. Assign user to role
await broadcastRequest({
  action: 'edit',
  resource: `/roles/${walletRole.details.rid}/users/add`,
  details: {
    users: [userId],
  },
})

On this page