Barazo AppView backend barazo.forum

fix(firehose): align indexers and tests with richtext content schema (#162)

The lexicon source updated content from plain string to
{ $type, value } richtext object and renamed topic createdAt to
publishedAt, but the firehose indexers and tests still used the
old format. Docker builds from source, causing type errors that
blocked staging deploys.

- Extract content.value for sanitizeHtml calls in topic/reply indexers
- Use 'markdown' literal for contentFormat (derived from $type)
- Use record.publishedAt for topic timestamps
- Update all unit and integration test fixtures to match new schema

authored by

Guido X Jansen and committed by
GitHub
0a2621a0 860ae40d

+125 -94
+4 -4
src/firehose/indexers/reply.ts
··· 65 65 uri, 66 66 rkey, 67 67 authorDid: did, 68 - content: sanitizeHtml(record.content), 69 - contentFormat: record.contentFormat ?? null, 68 + content: sanitizeHtml(record.content.value), 69 + contentFormat: 'markdown', 70 70 rootUri: root.uri, 71 71 rootCid: root.cid, 72 72 parentUri: parent.uri, ··· 99 99 await this.db 100 100 .update(replies) 101 101 .set({ 102 - content: sanitizeHtml(record.content), 103 - contentFormat: record.contentFormat ?? null, 102 + content: sanitizeHtml(record.content.value), 103 + contentFormat: 'markdown', 104 104 cid, 105 105 labels: record.labels ?? null, 106 106 indexedAt: new Date(),
+7 -7
src/firehose/indexers/topic.ts
··· 31 31 32 32 async handleCreate(params: CreateParams): Promise<void> { 33 33 const { uri, rkey, did, cid, record, live, trustStatus } = params 34 - const clientCreatedAt = new Date(record.createdAt) 34 + const clientCreatedAt = new Date(record.publishedAt) 35 35 const createdAt = live ? clampCreatedAt(clientCreatedAt) : clientCreatedAt 36 36 37 37 await this.db ··· 41 41 rkey, 42 42 authorDid: did, 43 43 title: sanitizeText(record.title), 44 - content: sanitizeHtml(record.content), 45 - contentFormat: record.contentFormat ?? null, 44 + content: sanitizeHtml(record.content.value), 45 + contentFormat: 'markdown', 46 46 category: record.category, 47 47 tags: record.tags ?? null, 48 48 communityDid: record.community, ··· 56 56 target: topics.uri, 57 57 set: { 58 58 title: sanitizeText(record.title), 59 - content: sanitizeHtml(record.content), 60 - contentFormat: record.contentFormat ?? null, 59 + content: sanitizeHtml(record.content.value), 60 + contentFormat: 'markdown', 61 61 category: record.category, 62 62 tags: record.tags ?? null, 63 63 cid, ··· 76 76 .update(topics) 77 77 .set({ 78 78 title: sanitizeText(record.title), 79 - content: sanitizeHtml(record.content), 80 - contentFormat: record.contentFormat ?? null, 79 + content: sanitizeHtml(record.content.value), 80 + contentFormat: 'markdown', 81 81 category: record.category, 82 82 tags: record.tags ?? null, 83 83 cid,
+7 -7
tests/integration/firehose/account-deletion.test.ts
··· 96 96 rkey: 'del-topic1', 97 97 record: { 98 98 title: 'Deleted user topic', 99 - content: 'This will be purged', 99 + content: { $type: 'forum.barazo.richtext#markdown', value: 'This will be purged' }, 100 100 community: 'did:plc:community', 101 101 category: 'general', 102 - createdAt: '2026-01-15T10:00:00.000Z', 102 + publishedAt: '2026-01-15T10:00:00.000Z', 103 103 }, 104 104 cid: 'bafydeltopic1', 105 105 live: true, ··· 115 115 collection: 'forum.barazo.topic.reply', 116 116 rkey: 'del-reply1', 117 117 record: { 118 - content: 'Deleted user reply', 118 + content: { $type: 'forum.barazo.richtext#markdown', value: 'Deleted user reply' }, 119 119 root: { uri: deletedTopicUri, cid: 'bafydeltopic1' }, 120 120 parent: { uri: deletedTopicUri, cid: 'bafydeltopic1' }, 121 121 community: 'did:plc:community', ··· 135 135 rkey: 'surv-topic1', 136 136 record: { 137 137 title: 'Surviving user topic', 138 - content: 'This should remain', 138 + content: { $type: 'forum.barazo.richtext#markdown', value: 'This should remain' }, 139 139 community: 'did:plc:community', 140 140 category: 'general', 141 - createdAt: '2026-01-15T10:00:00.000Z', 141 + publishedAt: '2026-01-15T10:00:00.000Z', 142 142 }, 143 143 cid: 'bafysurvtopic1', 144 144 live: true, ··· 293 293 rkey: 'ht-topic1', 294 294 record: { 295 295 title: 'Handle test', 296 - content: 'Testing handle update', 296 + content: { $type: 'forum.barazo.richtext#markdown', value: 'Testing handle update' }, 297 297 community: 'did:plc:community', 298 298 category: 'general', 299 - createdAt: '2026-01-15T10:00:00.000Z', 299 + publishedAt: '2026-01-15T10:00:00.000Z', 300 300 }, 301 301 cid: 'bafyht1', 302 302 live: true,
+37 -25
tests/integration/firehose/record-processing.test.ts
··· 90 90 rkey: 'topic1', 91 91 record: { 92 92 title: 'Integration Test Topic', 93 - content: 'This is a test topic for integration testing.', 93 + content: { 94 + $type: 'forum.barazo.richtext#markdown', 95 + value: 'This is a test topic for integration testing.', 96 + }, 94 97 community: 'did:plc:community', 95 98 category: 'general', 96 - createdAt: '2026-01-15T10:00:00.000Z', 99 + publishedAt: '2026-01-15T10:00:00.000Z', 97 100 }, 98 101 cid: 'bafytopic1', 99 102 live: true, ··· 134 137 rkey: 'topic1', 135 138 record: { 136 139 title: 'Updated Topic Title', 137 - content: 'Updated content for the topic.', 140 + content: { 141 + $type: 'forum.barazo.richtext#markdown', 142 + value: 'Updated content for the topic.', 143 + }, 138 144 community: 'did:plc:community', 139 145 category: 'discussion', 140 - createdAt: '2026-01-15T10:00:00.000Z', 146 + publishedAt: '2026-01-15T10:00:00.000Z', 141 147 }, 142 148 cid: 'bafytopic1v2', 143 149 live: true, ··· 198 204 rkey: 'topic1', 199 205 record: { 200 206 title: 'Parent Topic', 201 - content: 'Topic for reply tests', 207 + content: { $type: 'forum.barazo.richtext#markdown', value: 'Topic for reply tests' }, 202 208 community: 'did:plc:community', 203 209 category: 'general', 204 - createdAt: '2026-01-15T10:00:00.000Z', 210 + publishedAt: '2026-01-15T10:00:00.000Z', 205 211 }, 206 212 cid: 'bafytopic1', 207 213 live: true, ··· 217 223 collection: 'forum.barazo.topic.reply', 218 224 rkey: 'reply1', 219 225 record: { 220 - content: 'This is a reply', 226 + content: { $type: 'forum.barazo.richtext#markdown', value: 'This is a reply' }, 221 227 root: { uri: topicUri, cid: 'bafytopic1' }, 222 228 parent: { uri: topicUri, cid: 'bafytopic1' }, 223 229 community: 'did:plc:community', ··· 255 261 collection: 'forum.barazo.topic.reply', 256 262 rkey: `reply${String(i)}`, 257 263 record: { 258 - content: `Reply ${String(i)}`, 264 + content: { $type: 'forum.barazo.richtext#markdown', value: `Reply ${String(i)}` }, 259 265 root: { uri: topicUri, cid: 'bafytopic1' }, 260 266 parent: { uri: topicUri, cid: 'bafytopic1' }, 261 267 community: 'did:plc:community', ··· 285 291 rkey: 'topic1', 286 292 record: { 287 293 title: 'Reactable Topic', 288 - content: 'Topic for reaction tests', 294 + content: { $type: 'forum.barazo.richtext#markdown', value: 'Topic for reaction tests' }, 289 295 community: 'did:plc:community', 290 296 category: 'general', 291 - createdAt: '2026-01-15T10:00:00.000Z', 297 + publishedAt: '2026-01-15T10:00:00.000Z', 292 298 }, 293 299 cid: 'bafytopic1', 294 300 live: true, ··· 344 350 rkey: 'idem-topic1', 345 351 record: { 346 352 title: 'Idempotent Topic', 347 - content: 'Original content', 353 + content: { $type: 'forum.barazo.richtext#markdown', value: 'Original content' }, 348 354 community: 'did:plc:community', 349 355 category: 'general', 350 - createdAt: '2026-01-15T10:00:00.000Z', 356 + publishedAt: '2026-01-15T10:00:00.000Z', 351 357 }, 352 358 cid: 'bafyidem1', 353 359 live: false, ··· 381 387 rkey: 'idem-topic2', 382 388 record: { 383 389 title: 'Topic for replay test', 384 - content: 'Content', 390 + content: { $type: 'forum.barazo.richtext#markdown', value: 'Content' }, 385 391 community: 'did:plc:community', 386 392 category: 'general', 387 - createdAt: '2026-01-15T10:00:00.000Z', 393 + publishedAt: '2026-01-15T10:00:00.000Z', 388 394 }, 389 395 cid: 'bafyidem2', 390 396 live: false, ··· 398 404 collection: 'forum.barazo.topic.reply', 399 405 rkey: 'idem-reply1', 400 406 record: { 401 - content: 'Replay test reply', 407 + content: { $type: 'forum.barazo.richtext#markdown', value: 'Replay test reply' }, 402 408 root: { uri: topicUri, cid: 'bafyidem2' }, 403 409 parent: { uri: topicUri, cid: 'bafyidem2' }, 404 410 community: 'did:plc:community', ··· 439 445 rkey: 'edit-del-topic', 440 446 record: { 441 447 title: 'Original Title', 442 - content: 'Original content', 448 + content: { $type: 'forum.barazo.richtext#markdown', value: 'Original content' }, 443 449 community: 'did:plc:community', 444 450 category: 'general', 445 - createdAt: '2026-01-15T10:00:00.000Z', 451 + publishedAt: '2026-01-15T10:00:00.000Z', 446 452 }, 447 453 cid: originalCid, 448 454 live: true, ··· 457 463 collection: 'forum.barazo.topic.reply', 458 464 rkey: 'edit-del-reply', 459 465 record: { 460 - content: 'Reply referencing original CID', 466 + content: { 467 + $type: 'forum.barazo.richtext#markdown', 468 + value: 'Reply referencing original CID', 469 + }, 461 470 root: { uri: topicUri, cid: originalCid }, 462 471 parent: { uri: topicUri, cid: originalCid }, 463 472 community: 'did:plc:community', ··· 477 486 rkey: 'edit-del-topic', 478 487 record: { 479 488 title: 'Updated Title', 480 - content: 'Updated content', 489 + content: { $type: 'forum.barazo.richtext#markdown', value: 'Updated content' }, 481 490 community: 'did:plc:community', 482 491 category: 'general', 483 - createdAt: '2026-01-15T10:00:00.000Z', 492 + publishedAt: '2026-01-15T10:00:00.000Z', 484 493 }, 485 494 cid: updatedCid, 486 495 live: true, ··· 526 535 rkey: 'rapid-topic', 527 536 record: { 528 537 title: 'Ephemeral Topic', 529 - content: 'Gone before you know it', 538 + content: { $type: 'forum.barazo.richtext#markdown', value: 'Gone before you know it' }, 530 539 community: 'did:plc:community', 531 540 category: 'general', 532 - createdAt: '2026-01-15T10:00:00.000Z', 541 + publishedAt: '2026-01-15T10:00:00.000Z', 533 542 }, 534 543 cid: 'bafyrapid1', 535 544 live: true, ··· 563 572 rkey: 'rapid-topic2', 564 573 record: { 565 574 title: 'Another Ephemeral Topic', 566 - content: 'Will be deleted quickly', 575 + content: { $type: 'forum.barazo.richtext#markdown', value: 'Will be deleted quickly' }, 567 576 community: 'did:plc:community', 568 577 category: 'general', 569 - createdAt: '2026-01-15T10:00:00.000Z', 578 + publishedAt: '2026-01-15T10:00:00.000Z', 570 579 }, 571 580 cid: 'bafyrapid2', 572 581 live: true, ··· 581 590 collection: 'forum.barazo.topic.reply', 582 591 rkey: 'rapid-reply1', 583 592 record: { 584 - content: 'Quick reply before deletion', 593 + content: { 594 + $type: 'forum.barazo.richtext#markdown', 595 + value: 'Quick reply before deletion', 596 + }, 585 597 root: { uri: topicUri, cid: 'bafyrapid2' }, 586 598 parent: { uri: topicUri, cid: 'bafyrapid2' }, 587 599 community: 'did:plc:community',
+23 -23
tests/unit/firehose/handlers/record.test.ts
··· 85 85 rkey: 'abc123', 86 86 record: { 87 87 title: 'Test', 88 - content: 'Content', 88 + content: { $type: 'forum.barazo.richtext#markdown', value: 'Content' }, 89 89 community: 'did:plc:community', 90 90 category: 'general', 91 - createdAt: '2026-01-01T00:00:00.000Z', 91 + publishedAt: '2026-01-01T00:00:00.000Z', 92 92 }, 93 93 cid: 'bafyabc', 94 94 live: true, ··· 109 109 collection: 'forum.barazo.topic.reply', 110 110 rkey: 'reply1', 111 111 record: { 112 - content: 'Reply', 112 + content: { $type: 'forum.barazo.richtext#markdown', value: 'Reply' }, 113 113 root: { uri: 'at://did:plc:test/forum.barazo.topic.post/t1', cid: 'bafyt' }, 114 114 parent: { uri: 'at://did:plc:test/forum.barazo.topic.post/t1', cid: 'bafyt' }, 115 115 community: 'did:plc:community', ··· 157 157 rkey: 'abc123', 158 158 record: { 159 159 title: 'Updated', 160 - content: 'Updated content', 160 + content: { $type: 'forum.barazo.richtext#markdown', value: 'Updated content' }, 161 161 community: 'did:plc:community', 162 162 category: 'general', 163 - createdAt: '2026-01-01T00:00:00.000Z', 163 + publishedAt: '2026-01-01T00:00:00.000Z', 164 164 }, 165 165 cid: 'bafynew', 166 166 live: true, ··· 241 241 rkey: 'abc123', 242 242 record: { 243 243 title: 'Test', 244 - content: 'Content', 244 + content: { $type: 'forum.barazo.richtext#markdown', value: 'Content' }, 245 245 community: 'did:plc:community', 246 246 category: 'general', 247 - createdAt: '2026-01-01T00:00:00.000Z', 247 + publishedAt: '2026-01-01T00:00:00.000Z', 248 248 }, 249 249 cid: 'bafyabc', 250 250 live: true, ··· 267 267 rkey: 'abc123', 268 268 record: { 269 269 title: 'Test', 270 - content: 'Content', 270 + content: { $type: 'forum.barazo.richtext#markdown', value: 'Content' }, 271 271 community: 'did:plc:community', 272 272 category: 'general', 273 - createdAt: '2026-01-01T00:00:00.000Z', 273 + publishedAt: '2026-01-01T00:00:00.000Z', 274 274 }, 275 275 cid: 'bafyabc', 276 276 live: true, ··· 295 295 rkey: 'abc123', 296 296 record: { 297 297 title: 'Test', 298 - content: 'Content', 298 + content: { $type: 'forum.barazo.richtext#markdown', value: 'Content' }, 299 299 community: 'did:plc:community', 300 300 category: 'general', 301 - createdAt: '2026-01-01T00:00:00.000Z', 301 + publishedAt: '2026-01-01T00:00:00.000Z', 302 302 }, 303 303 cid: 'bafyabc', 304 304 live: true, ··· 322 322 rkey: 'abc123', 323 323 record: { 324 324 title: 'Test', 325 - content: 'Content', 325 + content: { $type: 'forum.barazo.richtext#markdown', value: 'Content' }, 326 326 community: 'did:plc:community', 327 327 category: 'general', 328 - createdAt: '2026-01-01T00:00:00.000Z', 328 + publishedAt: '2026-01-01T00:00:00.000Z', 329 329 }, 330 330 cid: 'bafyabc', 331 331 live: true, ··· 357 357 rkey: 'abc123', 358 358 record: { 359 359 title: 'Test', 360 - content: 'Content', 360 + content: { $type: 'forum.barazo.richtext#markdown', value: 'Content' }, 361 361 community: 'did:plc:community', 362 362 category: 'general', 363 - createdAt: '2026-01-01T00:00:00.000Z', 363 + publishedAt: '2026-01-01T00:00:00.000Z', 364 364 }, 365 365 cid: 'bafyabc', 366 366 live: true, ··· 391 391 rkey: 'abc123', 392 392 record: { 393 393 title: 'Test', 394 - content: 'Content', 394 + content: { $type: 'forum.barazo.richtext#markdown', value: 'Content' }, 395 395 community: 'did:plc:community', 396 396 category: 'general', 397 - createdAt: '2026-01-01T00:00:00.000Z', 397 + publishedAt: '2026-01-01T00:00:00.000Z', 398 398 }, 399 399 cid: 'bafyabc', 400 400 live: true, ··· 416 416 rkey: 'abc123', 417 417 record: { 418 418 title: 'Updated', 419 - content: 'Updated content', 419 + content: { $type: 'forum.barazo.richtext#markdown', value: 'Updated content' }, 420 420 community: 'did:plc:community', 421 421 category: 'general', 422 - createdAt: '2026-01-01T00:00:00.000Z', 422 + publishedAt: '2026-01-01T00:00:00.000Z', 423 423 }, 424 424 cid: 'bafynew', 425 425 live: true, ··· 446 446 rkey: 'abc123', 447 447 record: { 448 448 title: 'Test', 449 - content: 'Content', 449 + content: { $type: 'forum.barazo.richtext#markdown', value: 'Content' }, 450 450 community: 'did:plc:community', 451 451 category: 'general', 452 - createdAt: '2026-01-01T00:00:00.000Z', 452 + publishedAt: '2026-01-01T00:00:00.000Z', 453 453 }, 454 454 cid: 'bafyabc', 455 455 live: true, ··· 580 580 rkey: 'abc123', 581 581 record: { 582 582 title: 'Test', 583 - content: 'Content', 583 + content: { $type: 'forum.barazo.richtext#markdown', value: 'Content' }, 584 584 community: 'did:plc:community', 585 585 category: 'general', 586 - createdAt: '2026-01-01T00:00:00.000Z', 586 + publishedAt: '2026-01-01T00:00:00.000Z', 587 587 }, 588 588 cid: 'bafyabc', 589 589 live: false,
+20 -8
tests/unit/firehose/indexers/reply.test.ts
··· 66 66 await indexer.handleCreate({ 67 67 ...baseParams, 68 68 record: { 69 - content: 'A reply', 69 + content: { $type: 'forum.barazo.richtext#markdown' as const, value: 'A reply' }, 70 70 root: { uri: 'at://did:plc:test/forum.barazo.topic.post/topic1', cid: 'bafytopic' }, 71 71 parent: { uri: 'at://did:plc:test/forum.barazo.topic.post/topic1', cid: 'bafytopic' }, 72 72 community: 'did:plc:community', ··· 107 107 await indexer.handleCreate({ 108 108 ...baseParams, 109 109 record: { 110 - content: 'Direct reply', 110 + content: { $type: 'forum.barazo.richtext#markdown' as const, value: 'Direct reply' }, 111 111 root: { uri: topicUri, cid: 'bafytopic' }, 112 112 parent: { uri: topicUri, cid: 'bafytopic' }, 113 113 community: 'did:plc:community', ··· 148 148 await indexer.handleCreate({ 149 149 ...baseParams, 150 150 record: { 151 - content: 'Nested reply', 151 + content: { $type: 'forum.barazo.richtext#markdown' as const, value: 'Nested reply' }, 152 152 root: { uri: 'at://did:plc:test/forum.barazo.topic.post/topic1', cid: 'bafytopic' }, 153 153 parent: { uri: 'at://did:plc:test/forum.barazo.topic.reply/reply2', cid: 'bafyreply2' }, 154 154 community: 'did:plc:community', ··· 189 189 await indexer.handleCreate({ 190 190 ...baseParams, 191 191 record: { 192 - content: 'Orphaned nested reply', 192 + content: { 193 + $type: 'forum.barazo.richtext#markdown' as const, 194 + value: 'Orphaned nested reply', 195 + }, 193 196 root: { uri: 'at://did:plc:test/forum.barazo.topic.post/topic1', cid: 'bafytopic' }, 194 197 parent: { 195 198 uri: 'at://did:plc:test/forum.barazo.topic.reply/missing', ··· 214 217 await indexer.handleUpdate({ 215 218 ...baseParams, 216 219 record: { 217 - content: 'Updated reply', 220 + content: { $type: 'forum.barazo.richtext#markdown' as const, value: 'Updated reply' }, 218 221 root: { uri: 'at://did:plc:test/forum.barazo.topic.post/topic1', cid: 'bafytopic' }, 219 222 parent: { uri: 'at://did:plc:test/forum.barazo.topic.post/topic1', cid: 'bafytopic' }, 220 223 community: 'did:plc:community', ··· 251 254 await indexer.handleCreate({ 252 255 ...baseParams, 253 256 record: { 254 - content: '<p>Reply</p><script>evil()</script>', 257 + content: { 258 + $type: 'forum.barazo.richtext#markdown' as const, 259 + value: '<p>Reply</p><script>evil()</script>', 260 + }, 255 261 root: { uri: 'at://did:plc:test/forum.barazo.topic.post/topic1', cid: 'bafytopic' }, 256 262 parent: { uri: 'at://did:plc:test/forum.barazo.topic.post/topic1', cid: 'bafytopic' }, 257 263 community: 'did:plc:community', ··· 278 284 await indexer.handleUpdate({ 279 285 ...baseParams, 280 286 record: { 281 - content: '<p>Safe</p><iframe src="evil.com"></iframe>', 287 + content: { 288 + $type: 'forum.barazo.richtext#markdown' as const, 289 + value: '<p>Safe</p><iframe src="evil.com"></iframe>', 290 + }, 282 291 root: { uri: 'at://did:plc:test/forum.barazo.topic.post/topic1', cid: 'bafytopic' }, 283 292 parent: { uri: 'at://did:plc:test/forum.barazo.topic.post/topic1', cid: 'bafytopic' }, 284 293 community: 'did:plc:community', ··· 315 324 await indexer.handleCreate({ 316 325 ...baseParams, 317 326 record: { 318 - content: '<p>\u202AHello\u202E World\u200F</p>', 327 + content: { 328 + $type: 'forum.barazo.richtext#markdown' as const, 329 + value: '<p>\u202AHello\u202E World\u200F</p>', 330 + }, 319 331 root: { uri: 'at://did:plc:test/forum.barazo.topic.post/topic1', cid: 'bafytopic' }, 320 332 parent: { uri: 'at://did:plc:test/forum.barazo.topic.post/topic1', cid: 'bafytopic' }, 321 333 community: 'did:plc:community',
+21 -13
tests/unit/firehose/indexers/topic.test.ts
··· 47 47 ...baseParams, 48 48 record: { 49 49 title: 'Test Topic', 50 - content: 'Content here', 51 - contentFormat: 'markdown', 50 + content: { $type: 'forum.barazo.richtext#markdown' as const, value: 'Content here' }, 52 51 community: 'did:plc:community', 53 52 category: 'general', 54 53 tags: ['test'], 55 - createdAt: '2026-01-01T00:00:00.000Z', 54 + publishedAt: '2026-01-01T00:00:00.000Z', 56 55 }, 57 56 }) 58 57 ··· 68 67 ...baseParams, 69 68 record: { 70 69 title: 'Test', 71 - content: 'Content', 70 + content: { $type: 'forum.barazo.richtext#markdown' as const, value: 'Content' }, 72 71 community: 'did:plc:community', 73 72 category: 'general', 74 73 labels: { values: [{ val: 'nsfw' }] }, 75 - createdAt: '2026-01-01T00:00:00.000Z', 74 + publishedAt: '2026-01-01T00:00:00.000Z', 76 75 }, 77 76 }) 78 77 ··· 90 89 ...baseParams, 91 90 record: { 92 91 title: 'Updated Title', 93 - content: 'Updated content', 92 + content: { $type: 'forum.barazo.richtext#markdown' as const, value: 'Updated content' }, 94 93 community: 'did:plc:community', 95 94 category: 'updated', 96 95 tags: ['updated'], 97 - createdAt: '2026-01-01T00:00:00.000Z', 96 + publishedAt: '2026-01-01T00:00:00.000Z', 98 97 }, 99 98 }) 100 99 ··· 118 117 ...baseParams, 119 118 record: { 120 119 title: '<b>Bold</b> Title<script>alert("xss")</script>', 121 - content: '<p>Good</p><script>alert("xss")</script>', 120 + content: { 121 + $type: 'forum.barazo.richtext#markdown' as const, 122 + value: '<p>Good</p><script>alert("xss")</script>', 123 + }, 122 124 community: 'did:plc:community', 123 125 category: 'general', 124 - createdAt: '2026-01-01T00:00:00.000Z', 126 + publishedAt: '2026-01-01T00:00:00.000Z', 125 127 }, 126 128 }) 127 129 ··· 150 152 ...baseParams, 151 153 record: { 152 154 title: 'Clean <img src=x onerror=alert(1)>', 153 - content: '<p>Safe</p><iframe src="evil.com"></iframe>', 155 + content: { 156 + $type: 'forum.barazo.richtext#markdown' as const, 157 + value: '<p>Safe</p><iframe src="evil.com"></iframe>', 158 + }, 154 159 community: 'did:plc:community', 155 160 category: 'general', 156 - createdAt: '2026-01-01T00:00:00.000Z', 161 + publishedAt: '2026-01-01T00:00:00.000Z', 157 162 }, 158 163 }) 159 164 ··· 179 184 ...baseParams, 180 185 record: { 181 186 title: '\u202AHello\u202E World', 182 - content: '<p>\u2066Content\u2069</p>', 187 + content: { 188 + $type: 'forum.barazo.richtext#markdown' as const, 189 + value: '<p>\u2066Content\u2069</p>', 190 + }, 183 191 community: 'did:plc:community', 184 192 category: 'general', 185 - createdAt: '2026-01-01T00:00:00.000Z', 193 + publishedAt: '2026-01-01T00:00:00.000Z', 186 194 }, 187 195 }) 188 196
+6 -7
tests/unit/firehose/validation.test.ts
··· 5 5 describe('topic post validation', () => { 6 6 const validTopic = { 7 7 title: 'Test Topic', 8 - content: 'Some content here', 9 - contentFormat: 'markdown', 8 + content: { $type: 'forum.barazo.richtext#markdown', value: 'Some content here' }, 10 9 community: 'did:plc:abc123', 11 10 category: 'general', 12 11 tags: ['test'], 13 - createdAt: '2026-01-01T00:00:00.000Z', 12 + publishedAt: '2026-01-01T00:00:00.000Z', 14 13 } 15 14 16 15 it('accepts a valid topic post', () => { ··· 27 26 it('rejects a topic post with empty content', () => { 28 27 const result = validateRecord('forum.barazo.topic.post', { 29 28 ...validTopic, 30 - content: '', 29 + content: { $type: 'forum.barazo.richtext#markdown', value: '' }, 31 30 }) 32 31 expect(result.success).toBe(false) 33 32 }) ··· 35 34 36 35 describe('topic reply validation', () => { 37 36 const validReply = { 38 - content: 'A reply', 37 + content: { $type: 'forum.barazo.richtext#markdown', value: 'A reply' }, 39 38 root: { uri: 'at://did:plc:abc/forum.barazo.topic.post/123', cid: 'bafyabc' }, 40 39 parent: { uri: 'at://did:plc:abc/forum.barazo.topic.post/123', cid: 'bafyabc' }, 41 40 community: 'did:plc:abc123', ··· 120 119 it('rejects records exceeding 64KB', () => { 121 120 const oversized = { 122 121 title: 'Test', 123 - content: 'x'.repeat(65_537), 122 + content: { $type: 'forum.barazo.richtext#markdown', value: 'x'.repeat(65_537) }, 124 123 community: 'did:plc:abc123', 125 124 category: 'general', 126 - createdAt: '2026-01-01T00:00:00.000Z', 125 + publishedAt: '2026-01-01T00:00:00.000Z', 127 126 } 128 127 const result = validateRecord('forum.barazo.topic.post', oversized) 129 128 expect(result.success).toBe(false)