Phase 438: structured role and permission overwrite error logging (v0.8.401).

Wrap createGuildCustomRole, updateGuildCustomRole, deleteGuildCustomRole,
reorderGuildCustomRoles, setMemberCustomRoles, upsertChannelPermissionOverwrite,
and deleteChannelPermissionOverwrite with timed spans and structured error logs.
This commit is contained in:
Raven Scott
2026-05-23 18:45:47 -04:00
parent 2fa3ab097e
commit 1d00c2311c
2 changed files with 204 additions and 120 deletions
+2
View File
@@ -143,6 +143,8 @@ Primary consumer: `apps/pearcord/index.js` sidecar reading pear-pipe JSON.
**v0.8.400:** `createChannelWebhook`/`deleteChannelWebhook`/`executeChannelWebhook` log `webhook.*` spans and errors; `registerSlashCommands`/`deleteSlashCommand`/`executeSlashCommand` log `slash.*` spans and errors.
**v0.8.401:** `createGuildCustomRole`/`updateGuildCustomRole`/`deleteGuildCustomRole`/`reorderGuildCustomRoles`/`setMemberCustomRoles` log `role.*` spans and errors; `upsertChannelPermissionOverwrite`/`deleteChannelPermissionOverwrite` log `permission.overwrite*` spans and errors.
**v0.8.252:** Guild search mesh skipped when `guildOpenNoViewableChannels`; emoji batch prefetch skips negative miss TTL; sticker gossip prefetch gated on `attachments`; `session.startup` logs INFO when initial guild mesh flush was bounded. Smoke: `test:guild-search-no-viewable-skip`, `test:sticker-prefetch-attachments-ready`.
**v0.8.248:** Guild open filters unread/last picks with `_canViewChannel`; sets `guildOpenNoViewableChannels` when none accessible; defers `_ensureGuildModules` via `setTimeout(0)` after channel pick; emoji mesh prefetch clears miss cache on success. Smokes: `test:guild-viewable-channel-pick`, `test:guild-open-no-viewable`, `test:guild-plain-beats-dual-combo`.
+82
View File
@@ -4896,6 +4896,8 @@ class PearcordPlatform extends EventEmitter {
}
async createGuildCustomRole ({ name, color, permissions } = {}) {
const span = this.log.time('role.create', { name: String(name || '').slice(0, 32) })
try {
if (!this.guild?.guild) throw new Error('no guild')
if (!(await this._hasPerm(PERMISSION.MANAGE_GUILD))) {
throw new Error('no permission to manage roles')
@@ -4912,10 +4914,21 @@ class PearcordPlatform extends EventEmitter {
targetId: row.id
})
this.emit('guild-role', row)
span.end({ roleId: row.id })
return row
} catch (err) {
this.log.error('role.create error', {
name: String(name || '').slice(0, 32),
error: err?.message || String(err)
})
span.fail(err)
throw err
}
}
async updateGuildCustomRole (roleId, patch = {}) {
const span = this.log.time('role.update', { roleId })
try {
if (!this.guild?.guild) throw new Error('no guild')
if (!(await this._hasPerm(PERMISSION.MANAGE_GUILD))) {
throw new Error('no permission to manage roles')
@@ -4924,10 +4937,21 @@ class PearcordPlatform extends EventEmitter {
const row = await this.guildRoles.updateRole(this.guild.guild.id, roleId, patch)
this.guild.gossipRoleUpsert(row)
this.emit('guild-role', row)
span.end({ roleId: row?.id || roleId })
return row
} catch (err) {
this.log.error('role.update error', {
roleId,
error: err?.message || String(err)
})
span.fail(err)
throw err
}
}
async deleteGuildCustomRole (roleId) {
const span = this.log.time('role.delete', { roleId })
try {
if (!this.guild?.guild) throw new Error('no guild')
if (!(await this._hasPerm(PERMISSION.MANAGE_GUILD))) {
throw new Error('no permission to manage roles')
@@ -4938,10 +4962,21 @@ class PearcordPlatform extends EventEmitter {
this.guild.gossipRoleDelete({ guildId: this.guild.guild.id, id: roleId })
this.emit('guild-role-delete', { guildId: this.guild.guild.id, id: roleId })
}
span.end({ roleId })
return prev
} catch (err) {
this.log.error('role.delete error', {
roleId,
error: err?.message || String(err)
})
span.fail(err)
throw err
}
}
async reorderGuildCustomRoles (roleIds = []) {
const span = this.log.time('role.reorder', { count: (roleIds || []).length })
try {
if (!this.guild?.guild) throw new Error('no guild')
if (!(await this._hasPerm(PERMISSION.MANAGE_GUILD))) {
throw new Error('no permission to manage roles')
@@ -4952,10 +4987,21 @@ class PearcordPlatform extends EventEmitter {
if (row.updatedAt) this.guild.gossipRoleUpsert(row)
}
this.emit('guild-role-reorder', { guildId: this.guild.guild.id, roleIds })
span.end({ count: rows.length })
return rows
} catch (err) {
this.log.error('role.reorder error', {
count: (roleIds || []).length,
error: err?.message || String(err)
})
span.fail(err)
throw err
}
}
async setMemberCustomRoles (userId, roleIds = []) {
const span = this.log.time('role.member', { userId })
try {
if (!this.guild?.guild) throw new Error('no guild')
if (!(await this._hasPerm(PERMISSION.MANAGE_GUILD))) {
throw new Error('no permission to manage roles')
@@ -4976,7 +5022,16 @@ class PearcordPlatform extends EventEmitter {
guildId: this.guild.guild.id,
userId
}))
span.end({ userId, roleCount: (roleIds || []).length })
return link
} catch (err) {
this.log.error('role.member error', {
userId,
error: err?.message || String(err)
})
span.fail(err)
throw err
}
}
async getChannelSettings (channelId, guildId) {
@@ -5132,6 +5187,11 @@ class PearcordPlatform extends EventEmitter {
}
async upsertChannelPermissionOverwrite (channelId, payload = {}) {
const span = this.log.time('permission.overwrite', {
channelId: channelId || this.activeChannelId,
targetType: payload.targetType
})
try {
if (!this.guild?.guild) throw new Error('no guild')
if (!(await this._hasPerm(PERMISSION.MANAGE_CHANNELS))) {
throw new Error('no permission to edit channel permissions')
@@ -5166,10 +5226,21 @@ class PearcordPlatform extends EventEmitter {
await this._audit('channel.overwrite', { guildId: this.guild.guild.id, targetId: chId })
this.emit('channel-overwrite', row)
await this._fanoutAppEvent(APP_EVENTS.CHANNEL_PERMISSION_UPDATE, { overwrite: row })
span.end({ channelId: chId, targetId: payload.targetId })
return row
} catch (err) {
this.log.error('permission.overwrite error', {
channelId: channelId || this.activeChannelId,
error: err?.message || String(err)
})
span.fail(err)
throw err
}
}
async deleteChannelPermissionOverwrite (channelId, targetType, targetId) {
const span = this.log.time('permission.overwrite.delete', { channelId, targetType, targetId })
try {
if (!this.guild?.guild) throw new Error('no guild')
if (!(await this._hasPerm(PERMISSION.MANAGE_CHANNELS))) {
throw new Error('no permission to edit channel permissions')
@@ -5194,7 +5265,18 @@ class PearcordPlatform extends EventEmitter {
await this._fanoutAppEvent(APP_EVENTS.CHANNEL_PERMISSION_DELETE, {
delete: { channelId: chId, targetType, targetId }
})
span.end({ channelId: chId, targetId })
return prev
} catch (err) {
this.log.error('permission.overwrite.delete error', {
channelId,
targetType,
targetId,
error: err?.message || String(err)
})
span.fail(err)
throw err
}
}
async _assertVoiceCapacity (channelId) {