From c79e65eb22777ce237c29bcb8bf380ffa2d0f665 Mon Sep 17 00:00:00 2001 From: Bretton Date: Fri, 11 Sep 2026 21:36:31 -0700 Subject: [PATCH] fix(jetstream): raise postv2 consumer content cap to 500k bytes Commit 9a06ffe raised the postv2 lexicon and the write-API cap from 100,000 to 500,000 bytes but left the firehose consumer's mirror at 100,000. A post between those sizes passed the write API and landed on the PDS, then came back through Jetstream as ErrPermanentEvent: the create was dead-lettered and never indexed, and an update that size left the old content in place. This is the kagi-news failure the lexicon raise was meant to fix, one hop downstream. Changes: - MaxPostContentBytes in authorpost.go: 100000 -> 500000 - postv2_content_cap_test.go: create-over-cap, update-over-cap and at-cap cases now use 500,001 / 500,001 / 500,000 bytes Verified: T1 TestPostV2Consumer_ContentAndTitleCapsApplyToCreateAndUpdate passes (all five subtests), go vet and package T0 clean. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_016UfGV6NJToB7NdtTxCsBih --- internal/atproto/jetstream/authorpost.go | 2 +- .../atproto/jetstream/postv2_content_cap_test.go | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/internal/atproto/jetstream/authorpost.go b/internal/atproto/jetstream/authorpost.go index e122c7a..e5d20ad 100644 --- a/internal/atproto/jetstream/authorpost.go +++ b/internal/atproto/jetstream/authorpost.go @@ -62,7 +62,7 @@ const PostV2Collection = posts.PostV2Collection // local write API caps in internal/core/posts/service.go. const ( MaxPostTitleBytes = 3000 - MaxPostContentBytes = 100000 + MaxPostContentBytes = 500000 ) // DeletedAccountLookup reports whether a DID names an account this AppView was diff --git a/internal/atproto/jetstream/postv2_content_cap_test.go b/internal/atproto/jetstream/postv2_content_cap_test.go index 6dbadf9..9ed43b1 100644 --- a/internal/atproto/jetstream/postv2_content_cap_test.go +++ b/internal/atproto/jetstream/postv2_content_cap_test.go @@ -28,10 +28,10 @@ func TestPostV2Consumer_ContentAndTitleCapsApplyToCreateAndUpdate(t *testing.T) content string }{ { - name: "content over 100000 bytes", + name: "content over 500000 bytes", rkey: "pv2contentovercap", title: "oversized content", - content: strings.Repeat("c", 100_001), + content: strings.Repeat("c", 500_001), }, { name: "title over 3000 bytes", @@ -57,7 +57,7 @@ func TestPostV2Consumer_ContentAndTitleCapsApplyToCreateAndUpdate(t *testing.T) }) } - t.Run("update/content over 100000 bytes", func(t *testing.T) { + t.Run("update/content over 500000 bytes", func(t *testing.T) { const ( rkey = "pv2updatecontentovercap" originalContent = "content before the oversized update" @@ -72,11 +72,11 @@ func TestPostV2Consumer_ContentAndTitleCapsApplyToCreateAndUpdate(t *testing.T) err := f.consumer.HandleEvent(ctx, pv2Event( pv2Author, "update", rkey, revs[1], "bafyreicapupdatev2", base+1_000_000, - pv2Record(pv2Community, "updated title", strings.Repeat("u", 100_001)), + pv2Record(pv2Community, "updated title", strings.Repeat("u", 500_001)), )) assert.Truef(t, errors.Is(err, ErrPermanentEvent), - "a postv2 update with content over 100,000 bytes must return ErrPermanentEvent; got %v", err) + "a postv2 update with content over 500,000 bytes must return ErrPermanentEvent; got %v", err) assert.ErrorContains(t, err, "exceeds maximum length", "the oversized update rejection must name the content cap") var contentUnchanged bool @@ -96,12 +96,12 @@ func TestPostV2Consumer_ContentAndTitleCapsApplyToCreateAndUpdate(t *testing.T) wantContent int }{ { - name: "content at 100000 bytes", + name: "content at 500000 bytes", rkey: "pv2contentatcap", title: "content boundary", - content: strings.Repeat("c", 100_000), + content: strings.Repeat("c", 500_000), wantTitle: len("content boundary"), - wantContent: 100_000, + wantContent: 500_000, }, { name: "title at 3000 bytes", -- 2.51.2