channels: add durable attachment storage - #106
Open
XnLemon wants to merge 18 commits into
Open
Conversation
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
XnLemon
commented
Aug 31, 2026
XnLemon
commented
Sep 1, 2026
7 tasks
8 tasks
XnLemon
commented
Sep 1, 2026
XnLemon
commented
Sep 1, 2026
…-lease-fix # Conflicts: # docs/docs/index.md # docs/mkdocs.yml # migrations/history_test.go # migrations/migration_test.go # trpcservice/bootstrap/environment.go # trpcservice/gateway/dispatch.go # trpcservice/gateway/dispatch_test.go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
Updates #98. This PR now completes the native media MVP across the channel, storage, Gateway, model, and Outbox boundaries.
image,video,audio, anddocument, with tenant-scoped storage, immutable byte verification, event binding, idempotent upload behavior, expiry cleanup, and no provider URL/token exposure to Runner.message_eventrecords before loading verifiedtrpcmodel.ContentPartsfor Runner.image,file,voice, andvideocallback normalization after signature/AES/ReceiveID/AgentID verification, plus native image/file outbound delivery through temporary media upload.ReplyOutboxwith durablekind + attachment ref + fallbackfields via migration0016_runtime_reply_media.up.sql.Why
Channel-native media needs to be replay-safe, tenant-scoped, and provider-secret-safe. The Runner receives only controlled content parts and metadata; provider file IDs, WeCom media download URLs, Telegram download URLs, access tokens, and channel secrets stay inside the channel/storage boundary.
Issue #98 MVP ledger
Scope and compatibility
0014_wecom_aibot_channel.up.sql,0015_runtime_attachments.up.sql, and0016_runtime_reply_media.up.sqladd attachment storage and media reply descriptors while preserving existing text reply rows via defaults.Security and tenant isolation
media_idfetch URLs, access tokens, Bot tokens, or channel secrets.PicUrland uses only the verified binding credential context for authenticated media fetch.Testing
./scripts/format.sh --checkbash -lc 'export PATH="$(go env GOPATH)/bin:$PATH"; ./scripts/lint.sh'(go vet ./...andgolangci-lint v2.1.6passed)bash ./scripts/build.shgo test ./trpcservice/channels/telegram ./trpcservice/channels/wecom ./trpcservice/bootstrap ./trpcservice/runtime/storage ./trpcservice/runtime/storage/inmemory ./trpcservice/runtime/storage/postgres ./trpcservice/gateway ./trpcservice/attachment ./migrations -count=1go test ./... -count=1bash ./scripts/coverage.sh(total 91.6%; local patch executable-line estimate 91.9%)bash ./scripts/race.shpython -m mkdocs build --strict --config-file docs/mkdocs.ymlgit diff --checkResidual risks and follow-ups
Issue #111 Tool-driven media reply
Closes #111. This PR now closes the service-layer bridge between a revision-authorized agent tool and the existing native media Outbox transport.
send_test_imagethroughToolAuthorization; unlisted tools are not exposed and required unavailable tools fail closed during Runner construction.ReplyOutboxsegment.tool.allowedandtool.executedaudit facts are emitted without raw arguments/results; existing tool trace callbacks remain in the Runner observability path.Scope
send_test_imagewrites a fixed valid PNG and proves the complete secure transport path. It is not image generation, arbitrary file access, OCR, ASR, video understanding, or a general external-agent registry. Future tools use the same context-bound factory/reply-intent boundary.Additional validation
./scripts/format.sh --checkbash -lc 'export PATH="$(go env GOPATH)/bin:$PATH"; ./scripts/lint.sh'bash ./scripts/build.shgo test ./... -count=1bash ./scripts/race.shpython -m mkdocs build --strict --config-file docs/mkdocs.ymlgit diff --checkCurrent-base revalidation
main(including merged PR #118 and the gateway cancellation fix) was merged into this branch. The migration history and PostgreSQL reply receipt fixtures were revalidated on the current base.Current validation
go test ./... -count=1bash ./scripts/race.sh./scripts/format.sh --checkbash ./scripts/lint.sh(0 issues)bash ./scripts/build.shpython -m mkdocs build --strict --config-file docs/mkdocs.ymlgit diff --check