Phase 719: read state and webhook execute JSON mesh parity (v0.8.695)

Add dedicated signed-export modals for read receipts and webhook execute
exports, populate view rows and meta, partition-heal mixins with dedicated
spans, agentctl journeys, and CI smokes following the Phase 718 pattern.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Raven Scott
2026-06-03 08:07:59 -04:00
co-authored by Cursor
parent 4d185d7898
commit 6a7ae68bbd
4 changed files with 279 additions and 11 deletions
+145 -11
View File
@@ -1851,6 +1851,12 @@ class PearcordPlatform extends EventEmitter {
const guildWidgetJsonHeal = await this._healGuildWidgetJsonExportCursorOnPartition(gid).catch(() => ({
relisted: 0
}))
const readStateJsonHeal = await this._healReadStateJsonExportCursorOnPartition(gid).catch(() => ({
relisted: 0
}))
const webhookJsonHeal = await this._healWebhookJsonExportCursorOnPartition(gid).catch(() => ({
relisted: 0
}))
return {
voiceApplied,
emojiSlots,
@@ -1921,7 +1927,9 @@ class PearcordPlatform extends EventEmitter {
multiGuildSyncJsonHeal,
partitionHealDiagnosticsJsonHeal,
channelFollowJsonHeal,
guildWidgetJsonHeal
guildWidgetJsonHeal,
readStateJsonHeal,
webhookJsonHeal
}
}
@@ -14255,10 +14263,40 @@ class PearcordPlatform extends EventEmitter {
}
}
async getWebhookExecuteExportJsonExport () {
const gid = this.guild?.guild?.id || null
const span = this.log.time('webhook.json', { spanKind: 'webhook.json', guildId: gid, context: 'read' })
try {
if (!this.guild?.guild) { span.end({ guildWebhookExecuteJsonCount: 0, skipped: true }); return null }
await this._initDeliveryReceipts(this.guild.guild.id)
const row = await this.deliveryReceipts.getWebhookExecuteExportJsonExport()
if (!row?.signature) {
span.end({ guildWebhookExecuteJsonCount: row ? 1 : 0, hasSignature: false, bridgeKind: 'webhook.json' })
return row
}
const verified = verifyWebhookExecuteExportJson(exportBodyFromSlice(row) || row.jsonBody, row.signature, { guildId: this.guild.guild.id, relaySecret: this.guild.guild.id })
const out = { ...row, signatureValid: verified.ok, webhookCount: row.webhookCount || 0 }
span.end({ guildWebhookExecuteJsonCount: 1, hasSignature: true, signatureValid: verified.ok, bridgeKind: 'webhook.json' })
return out
} catch (err) {
this.log.error('webhook.json error', { guildId: gid, context: 'read', error: err?.message || String(err) })
span.fail(err); throw err
}
}
async clearWebhookExecuteExportJsonExports () {
if (!this.guild?.guild) throw new Error('no guild')
if (!(await this._hasPerm(PERMISSION.MANAGE_GUILD))) throw new Error('no permission to clear webhook execute JSON exports')
await this._initDeliveryReceipts(this.guild.guild.id)
const removed = await this.deliveryReceipts.clearWebhookExecuteExportJsonExports()
this.emit('webhook-execute-export-json-cleared', { removed })
return { removed }
}
async pushWebhookExecuteExportToMesh () {
const gid = this.guild?.guild?.id || null
const span = this.log.time('bot.json', {
spanKind: 'bot.json',
const span = this.log.time('webhook.json', {
spanKind: 'webhook.json',
guildId: gid,
context: 'mesh.execute'
})
@@ -14290,13 +14328,13 @@ class PearcordPlatform extends EventEmitter {
meshPushed: true
}
span.end({
guildBotRegistryCount: exported.webhookCount || 0,
guildWebhookExecuteJsonCount: exported.webhookCount || 0,
meshPushed: true,
bridgeKind: 'bot.json'
bridgeKind: 'webhook.json'
})
return exported
} catch (err) {
this.log.error('bot.json error', {
this.log.error('webhook.json error', {
guildId: gid,
context: 'mesh.execute',
error: err?.message || String(err)
@@ -26052,10 +26090,40 @@ class PearcordPlatform extends EventEmitter {
return { format: 'json', body: signed.json, signature: signed.signature, signatureAlg: signed.signatureAlg, exportedAt, readStateCount: entries.length, meta }
}
async getReadStateExportJsonExport () {
const gid = this.guild?.guild?.id || null
const span = this.log.time('read-state.json', { spanKind: 'read-state.json', guildId: gid, context: 'read' })
try {
if (!this.guild?.guild) { span.end({ guildReadStateJsonCount: 0, skipped: true }); return null }
await this._initDeliveryReceipts(this.guild.guild.id)
const row = await this.deliveryReceipts.getReadStateExportJsonExport()
if (!row?.signature) {
span.end({ guildReadStateJsonCount: row ? 1 : 0, hasSignature: false, bridgeKind: 'read-state.json' })
return row
}
const verified = verifyReadStateExportJson(exportBodyFromSlice(row) || row.jsonBody, row.signature, { guildId: this.guild.guild.id, relaySecret: this.guild.guild.id })
const out = { ...row, signatureValid: verified.ok, readStateCount: row.readStateCount || 0 }
span.end({ guildReadStateJsonCount: 1, hasSignature: true, signatureValid: verified.ok, bridgeKind: 'read-state.json' })
return out
} catch (err) {
this.log.error('read-state.json error', { guildId: gid, context: 'read', error: err?.message || String(err) })
span.fail(err); throw err
}
}
async clearReadStateExportJsonExports () {
if (!this.guild?.guild) throw new Error('no guild')
if (!(await this._hasPerm(PERMISSION.MANAGE_GUILD))) throw new Error('no permission to clear read state JSON exports')
await this._initDeliveryReceipts(this.guild.guild.id)
const removed = await this.deliveryReceipts.clearReadStateExportJsonExports()
this.emit('read-state-export-json-cleared', { removed })
return { removed }
}
async pushReadStateExportToMesh () {
const gid = this.guild?.guild?.id || null
const span = this.log.time('presence.json', {
spanKind: 'presence.json',
const span = this.log.time('read-state.json', {
spanKind: 'read-state.json',
guildId: gid,
context: 'mesh.read-state'
})
@@ -26087,13 +26155,13 @@ class PearcordPlatform extends EventEmitter {
meshPushed: true
}
span.end({
guildPresenceJsonCount: exported.readStateCount || 0,
guildReadStateJsonCount: exported.readStateCount || 0,
meshPushed: true,
bridgeKind: 'presence.json'
bridgeKind: 'read-state.json'
})
return exported
} catch (err) {
this.log.error('presence.json error', {
this.log.error('read-state.json error', {
guildId: gid,
context: 'mesh.read-state',
error: err?.message || String(err)
@@ -27382,6 +27450,34 @@ class PearcordPlatform extends EventEmitter {
return row
}
async _readStateJsonRegistryEntries () {
if (!this.guild?.guild) return []
const rows = await this._readReceiptSyncRowsForView(this.guild.guild.id, 64).catch(() => [])
if (!rows.length) {
return [{ channelId: '', channelName: 'none', readStateLabel: 'unread', exportedAt: Date.now() }]
}
return rows.slice(0, 32).map((row) => ({
channelId: row.channelId || '',
channelName: row.channelName || '',
readStateLabel: row.lastReadAt ? 'read' : 'unread',
exportedAt: Date.now()
}))
}
async _webhookJsonRegistryEntries () {
if (!this.guild?.guild) return []
const hooks = await this.listChannelWebhooks().catch(() => [])
if (!hooks.length) {
return [{ id: 'stub', webhookName: 'none', executeState: 'idle', exportedAt: Date.now() }]
}
return hooks.slice(0, 32).map((h) => ({
id: h.id,
webhookName: h.name || 'webhook',
executeState: 'registered',
exportedAt: h.createdAt || Date.now()
}))
}
async _channelFollowJsonRegistryEntries () {
if (!this.guild?.guild) return []
const follows = this.announcements
@@ -32490,6 +32586,8 @@ class PearcordPlatform extends EventEmitter {
let botRegistryJsonMeta = null
let botRegistryJsonRows = []
let webhookExecuteExportJsonRows = []
let webhookExecuteExportJsonMeta = null
let guildWebhookExecuteEntries = []
let lastWebhookExecuteExport = null
let slashRegistryJsonMeta = null
let slashRegistryJsonRows = []
@@ -32554,7 +32652,9 @@ class PearcordPlatform extends EventEmitter {
let presenceActivityJsonMeta = null
let presenceActivityJsonRows = []
let readStateExportJsonRows = []
let readStateExportJsonMeta = null
let lastReadStateExport = null
let guildReadStateEntries = []
let guildPresenceActivities = []
let notificationOverrideJsonMeta = null
let notificationOverrideJsonRows = []
@@ -32702,6 +32802,14 @@ class PearcordPlatform extends EventEmitter {
return { ...row, signatureValid: verified.ok }
})
lastWebhookExecuteExport = await this.getLastWebhookExecuteExport()
webhookExecuteExportJsonMeta = await this.getWebhookExecuteExportJsonExport().catch(() => null)
const webhookEntries = await this._webhookJsonRegistryEntries().catch(() => [])
guildWebhookExecuteEntries = webhookEntries.slice(0, 16).map((r) => ({
id: r.id || 'webhook',
name: r.webhookName || 'Webhook',
role: r.executeState || 'registered',
updatedAt: r.exportedAt || Date.now()
}))
slashRegistryJsonMeta = await this.getSlashRegistryJsonExport().catch(() => null)
const slashJsonHistory = await this.deliveryReceipts.listSlashRegistryJsonExports(32)
slashRegistryJsonRows = slashJsonHistory.map((row) => {
@@ -32940,6 +33048,20 @@ class PearcordPlatform extends EventEmitter {
role: r.widgetState || 'private',
updatedAt: r.exportedAt || Date.now()
}))
readStateExportJsonMeta = await this.getReadStateExportJsonExport().catch(() => null)
readStateExportJsonRows = (await this.deliveryReceipts.listReadStateExportJsonExports(32)).map((row) => {
if (!row?.signature || !guild?.id) return row
const verified = verifyReadStateExportJson(exportBodyFromSlice(row) || row.jsonBody, row.signature, { guildId: guild.id, relaySecret: guild.id })
return { ...row, signatureValid: verified.ok }
})
lastReadStateExport = await this.getLastReadStateExport().catch(() => null)
const readEntries = await this._readStateJsonRegistryEntries().catch(() => [])
guildReadStateEntries = readEntries.slice(0, 16).map((r) => ({
id: r.channelId || 'read',
name: r.channelName || 'Channel',
role: r.readStateLabel || 'read',
updatedAt: r.exportedAt || Date.now()
}))
const multiEntries = await this._multiGuildSyncJsonRegistryEntries().catch(() => [])
guildMultiGuildSyncEntries = multiEntries.slice(0, 16).map((r) => ({
id: r.guildId || guild.id,
@@ -33527,6 +33649,10 @@ class PearcordPlatform extends EventEmitter {
botRegistryJsonMeta,
botRegistryJsonRows,
webhookExecuteExportJsonRows,
webhookExecuteExportJsonMeta,
guildWebhookExecuteEntries,
guildWebhookExecuteJsonCount:
(webhookExecuteExportJsonRows || []).length + (guildWebhookExecuteEntries || []).length,
lastWebhookExecuteExport,
slashRegistryJsonMeta,
slashRegistryJsonRows,
@@ -33613,6 +33739,10 @@ class PearcordPlatform extends EventEmitter {
presenceActivityJsonMeta,
presenceActivityJsonRows,
readStateExportJsonRows,
readStateExportJsonMeta,
guildReadStateEntries,
guildReadStateJsonCount:
(readStateExportJsonRows || []).length + (guildReadStateEntries || []).length,
lastReadStateExport,
guildPresenceActivities,
guildPresenceJsonCount:
@@ -34318,6 +34448,8 @@ const { multiGuildJsonMixin } = require('./multi-guild-json-mixin')
const { partitionHealJsonMixin } = require('./partition-heal-json-mixin')
const { channelFollowJsonMixin } = require('./channel-follow-json-mixin')
const { guildWidgetJsonMixin } = require('./guild-widget-json-mixin')
const { readStateJsonMixin } = require('./read-state-json-mixin')
const { webhookJsonMixin } = require('./webhook-json-mixin')
Object.assign(PearcordPlatform.prototype, pollSchedulingMixin)
Object.assign(PearcordPlatform.prototype, notificationsActivityMixin)
Object.assign(PearcordPlatform.prototype, userSettingsMixin)
@@ -34365,3 +34497,5 @@ Object.assign(PearcordPlatform.prototype, multiGuildJsonMixin)
Object.assign(PearcordPlatform.prototype, partitionHealJsonMixin)
Object.assign(PearcordPlatform.prototype, channelFollowJsonMixin)
Object.assign(PearcordPlatform.prototype, guildWidgetJsonMixin)
Object.assign(PearcordPlatform.prototype, readStateJsonMixin)
Object.assign(PearcordPlatform.prototype, webhookJsonMixin)