Skip to content

Shared chat-channel foundations - #404

Open
alex-clickhouse wants to merge 4 commits into
mainfrom
alex/slack-channel-foundations
Open

Shared chat-channel foundations#404
alex-clickhouse wants to merge 4 commits into
mainfrom
alex/slack-channel-foundations

Conversation

@alex-clickhouse

@alex-clickhousealex-clickhouse commented Aug 23, 2026

Copy link
Copy Markdown
Collaborator

Part 1 of the Slack channel stack. This PR stands on its own: it adds the
channel-neutral session, notification, access, and attachment pieces that the
Slack adapter in #403 builds on. Nothing here names Slack.

Stack

  1. Shared chat-channel foundations #404: shared chat-channel foundations (this PR)
  2. Slack channel with coherent runtime and access guardrails #403: Slack channel, access guardrails, and runtime ownership
  3. Deliver notifications through Slack #405: Slack notification delivery
  4. Add retry-safe live Slack contract tests #406: real-Slack contract tests and diagnostics

What changes

  • Access matching that no transport owns. Allow and deny lists of
    case-insensitive globs, deny winning over allow, and a refusal when an
    identity could not be resolved well enough to check a deny list against.
    Aliases are split by who controls them: a deny rule may match any alias, an
    allow rule only the ones the subject cannot set for itself. A grant resting
    on a self-set name would let the subject pick its own access. Each transport
    decides which of its aliases fall on which side.
  • Bounded ZIP extraction moved into a shared helper, keeping Telegram's
    text, image, and PDF behavior. The caps come from what a prompt can carry
    once base64 adds its third, and the ratio check applies only above a size
    floor so ordinary repetitive files still arrive.
  • ChannelRouter completed as the session boundary for stop, star,
    switch, unregister, and conversation-scoped lookup, so a channel never
    reaches through to the engine or the database.
  • Conversation lookup is delimiter-bounded.chat:1 and chat:12 cannot
    see each other's rows, and SQL wildcards in a conversation id are escaped
    rather than matched.
  • Generic notification_deliveries records keyed by transport and exact
    target, with existing Telegram delivery references migrated across.
  • Scoped notification answer APIs that keep the transport actor in row
    metadata, in broadcasts, and in approval audit records, so one transport
    cannot answer another's notification.
  • Telegram moved onto those boundaries rather than reaching past them.

Access matching has no caller yet. The Slack channel composes its user,
channel, and direct-message rules on top of it in #403.

@alex-clickhouse
alex-clickhouse marked this pull request as ready for review August 24, 2026 06:44
@alex-clickhousealex-clickhouse changed the title Bound archive extraction shared by chat channelsBounded archive extraction shared by chat channelsAug 24, 2026
@alex-clickhousealex-clickhouse changed the title Bounded archive extraction shared by chat channelsShared chat-channel foundationsAug 25, 2026
Extract Telegram's ZIP handling into a channel-neutral helper with limits on entry count, expanded size, per-entry size, and compression ratio. This both closes decompression amplification and gives the Slack channel a safe implementation to build on.
MAX_TOTAL_SIZE was above the compressed download cap, so a 703 KB upload
of 100 padded PDF entries passed every check and produced 66.7 MB of
base64 in one prompt. Set the entry and archive caps from what the prompt
can carry once base64 adds its third.
The compression ratio check refused small files that repeat for ordinary
reasons: a 103 KB generated .py and a 105 KB log of one repeated line
both scored above the ratio and were dropped, where Telegram inlined them
before. Apply the ratio only above RATIO_FLOOR, where the size caps have
not already bounded the entry.
Check the text budget before the archive budget so a refusal names the
limit the entry reached.
A channel needs to decide whether a sender and a conversation may reach the
agent, and the matching rules do not depend on the transport: allow and deny
lists of case-insensitive globs, deny winning over allow, and a refusal when
an identity could not be resolved well enough to check a deny list against.
Aliases are split by who controls them. A deny rule may match any alias. An
allow rule may match only the aliases the subject cannot set for itself,
because a grant resting on a self-set name lets the subject pick its own
access. Each transport decides which of its aliases fall on which side.
No transport uses this yet. The Slack channel composes its user, channel,
and direct-message rules on top of it.
@alex-clickhouse
alex-clickhouseforce-pushed the alex/slack-channel-foundations branch from c9119ba to 6ac958dCompareAugust 26, 2026 11:59
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@alex-clickhouse