@excitedjs/feishu-channel 6.3.0-beta.264 → 6.3.0-beta.271
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -26
- package/dist/access/gate.d.ts +52 -0
- package/dist/access/gate.d.ts.map +1 -0
- package/dist/{feishu-gate.js → access/gate.js} +36 -135
- package/dist/access/gate.js.map +1 -0
- package/dist/access/index.d.ts +100 -0
- package/dist/access/index.d.ts.map +1 -0
- package/dist/access/index.js +350 -0
- package/dist/access/index.js.map +1 -0
- package/dist/access/state.d.ts +43 -0
- package/dist/access/state.d.ts.map +1 -0
- package/dist/access/state.js +41 -0
- package/dist/access/state.js.map +1 -0
- package/dist/{feishu-ask-user.d.ts → ask-user/registry.d.ts} +34 -27
- package/dist/ask-user/registry.d.ts.map +1 -0
- package/dist/{feishu-ask-user.js → ask-user/registry.js} +43 -49
- package/dist/ask-user/registry.js.map +1 -0
- package/dist/bot.d.ts +21 -118
- package/dist/bot.d.ts.map +1 -1
- package/dist/bot.js +35 -276
- package/dist/bot.js.map +1 -1
- package/dist/card-actions.d.ts +34 -0
- package/dist/card-actions.d.ts.map +1 -0
- package/dist/card-actions.js +42 -0
- package/dist/card-actions.js.map +1 -0
- package/dist/{feishu-ask-user-card.d.ts → cards/ask-user.d.ts} +2 -8
- package/dist/cards/ask-user.d.ts.map +1 -0
- package/dist/{feishu-ask-user-card.js → cards/ask-user.js} +5 -14
- package/dist/cards/ask-user.js.map +1 -0
- package/dist/{feishu-binding-notification-card.d.ts → cards/binding-notification.d.ts} +3 -3
- package/dist/cards/binding-notification.d.ts.map +1 -0
- package/dist/{feishu-binding-notification-card.js → cards/binding-notification.js} +94 -101
- package/dist/cards/binding-notification.js.map +1 -0
- package/dist/cards/kit.d.ts +52 -0
- package/dist/cards/kit.d.ts.map +1 -0
- package/dist/cards/kit.js +63 -0
- package/dist/cards/kit.js.map +1 -0
- package/dist/{feishu-pairing-card.d.ts → cards/pairing.d.ts} +1 -4
- package/dist/cards/pairing.d.ts.map +1 -0
- package/dist/{feishu-pairing-card.js → cards/pairing.js} +14 -16
- package/dist/cards/pairing.js.map +1 -0
- package/dist/{feishu-running-teams-card.d.ts → cards/running-teams.d.ts} +2 -2
- package/dist/cards/running-teams.d.ts.map +1 -0
- package/dist/{feishu-running-teams-card.js → cards/running-teams.js} +16 -8
- package/dist/cards/running-teams.js.map +1 -0
- package/dist/chat-bots-store.d.ts +20 -11
- package/dist/chat-bots-store.d.ts.map +1 -1
- package/dist/chat-bots-store.js +125 -102
- package/dist/chat-bots-store.js.map +1 -1
- package/dist/{feishu-cot-adapter.d.ts → cot/adapter.d.ts} +93 -30
- package/dist/cot/adapter.d.ts.map +1 -0
- package/dist/{feishu-cot-adapter.js → cot/adapter.js} +216 -133
- package/dist/cot/adapter.js.map +1 -0
- package/dist/cot/bytes.d.ts +41 -0
- package/dist/cot/bytes.d.ts.map +1 -0
- package/dist/cot/bytes.js +144 -0
- package/dist/cot/bytes.js.map +1 -0
- package/dist/{feishu-cot-events.d.ts → cot/card.d.ts} +47 -25
- package/dist/cot/card.d.ts.map +1 -0
- package/dist/cot/card.js +468 -0
- package/dist/cot/card.js.map +1 -0
- package/dist/{feishu-cot-diagnostics.d.ts → cot/diagnostics.d.ts} +5 -6
- package/dist/cot/diagnostics.d.ts.map +1 -0
- package/dist/{feishu-cot-diagnostics.js → cot/diagnostics.js} +2 -2
- package/dist/cot/diagnostics.js.map +1 -0
- package/dist/cot/inbound-correlations.d.ts +12 -0
- package/dist/cot/inbound-correlations.d.ts.map +1 -0
- package/dist/{feishu-inbound-anchor.js → cot/inbound-correlations.js} +5 -2
- package/dist/cot/inbound-correlations.js.map +1 -0
- package/dist/{feishu-cot-io.d.ts → cot/io.d.ts} +13 -7
- package/dist/cot/io.d.ts.map +1 -0
- package/dist/{feishu-cot-io.js → cot/io.js} +5 -5
- package/dist/cot/io.js.map +1 -0
- package/dist/{feishu-cot-state.d.ts → cot/recipients.d.ts} +42 -18
- package/dist/cot/recipients.d.ts.map +1 -0
- package/dist/{feishu-cot-state.js → cot/recipients.js} +93 -36
- package/dist/cot/recipients.js.map +1 -0
- package/dist/extension.d.ts +156 -0
- package/dist/extension.d.ts.map +1 -0
- package/dist/extension.js +2 -0
- package/dist/extension.js.map +1 -0
- package/dist/feishu-bounded-operation.d.ts +1 -2
- package/dist/feishu-bounded-operation.d.ts.map +1 -1
- package/dist/feishu-bounded-operation.js +5 -5
- package/dist/feishu-bounded-operation.js.map +1 -1
- package/dist/feishu-core-commands.d.ts +30 -0
- package/dist/feishu-core-commands.d.ts.map +1 -0
- package/dist/feishu-core-commands.js +81 -0
- package/dist/feishu-core-commands.js.map +1 -0
- package/dist/feishu-document-comments.d.ts +16 -14
- package/dist/feishu-document-comments.d.ts.map +1 -1
- package/dist/feishu-document-comments.js +15 -11
- package/dist/feishu-document-comments.js.map +1 -1
- package/dist/feishu-extensions.d.ts +94 -0
- package/dist/feishu-extensions.d.ts.map +1 -0
- package/dist/feishu-extensions.js +237 -0
- package/dist/feishu-extensions.js.map +1 -0
- package/dist/feishu-provisioning.d.ts +8 -13
- package/dist/feishu-provisioning.d.ts.map +1 -1
- package/dist/feishu-provisioning.js +26 -20
- package/dist/feishu-provisioning.js.map +1 -1
- package/dist/feishu-slash-commands.d.ts +10 -6
- package/dist/feishu-slash-commands.d.ts.map +1 -1
- package/dist/feishu-slash-commands.js +33 -24
- package/dist/feishu-slash-commands.js.map +1 -1
- package/dist/feishu-submit.d.ts +36 -5
- package/dist/feishu-submit.d.ts.map +1 -1
- package/dist/feishu-submit.js +19 -2
- package/dist/feishu-submit.js.map +1 -1
- package/dist/{feishu-message.d.ts → inbound/attachments.d.ts} +4 -6
- package/dist/inbound/attachments.d.ts.map +1 -0
- package/dist/{feishu-message.js → inbound/attachments.js} +13 -8
- package/dist/inbound/attachments.js.map +1 -0
- package/dist/{feishu-inbound-enrichment.d.ts → inbound/enrich.d.ts} +4 -3
- package/dist/inbound/enrich.d.ts.map +1 -0
- package/dist/{feishu-inbound-enrichment.js → inbound/enrich.js} +4 -4
- package/dist/inbound/enrich.js.map +1 -0
- package/dist/inbound/pipeline.d.ts +48 -0
- package/dist/inbound/pipeline.d.ts.map +1 -0
- package/dist/{feishu-session-inbound.js → inbound/pipeline.js} +131 -162
- package/dist/inbound/pipeline.js.map +1 -0
- package/dist/{feishu-message-render.d.ts → inbound/render.d.ts} +4 -4
- package/dist/inbound/render.d.ts.map +1 -0
- package/dist/{feishu-message-render.js → inbound/render.js} +6 -17
- package/dist/inbound/render.js.map +1 -0
- package/dist/{feishu-reply-ancestry.d.ts → inbound/reply-ancestry.d.ts} +2 -2
- package/dist/inbound/reply-ancestry.d.ts.map +1 -0
- package/dist/{feishu-reply-ancestry.js → inbound/reply-ancestry.js} +4 -2
- package/dist/inbound/reply-ancestry.js.map +1 -0
- package/dist/inbound/router.d.ts +58 -0
- package/dist/inbound/router.d.ts.map +1 -0
- package/dist/inbound/router.js +87 -0
- package/dist/inbound/router.js.map +1 -0
- package/dist/inbound/target.d.ts +79 -0
- package/dist/inbound/target.d.ts.map +1 -0
- package/dist/{feishu-target-router.js → inbound/target.js} +36 -58
- package/dist/inbound/target.js.map +1 -0
- package/dist/{feishu-inbound-work.d.ts → inbound/work.d.ts} +3 -8
- package/dist/inbound/work.d.ts.map +1 -0
- package/dist/{feishu-inbound-work.js → inbound/work.js} +10 -16
- package/dist/inbound/work.js.map +1 -0
- package/dist/index.d.ts +17 -22
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -22
- package/dist/index.js.map +1 -1
- package/dist/introduce.d.ts +1 -1
- package/dist/introduce.d.ts.map +1 -1
- package/dist/introduce.js +2 -1
- package/dist/introduce.js.map +1 -1
- package/dist/outbound/index.d.ts +172 -0
- package/dist/outbound/index.d.ts.map +1 -0
- package/dist/outbound/index.js +346 -0
- package/dist/outbound/index.js.map +1 -0
- package/dist/plugin.d.ts +20 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +20 -0
- package/dist/plugin.js.map +1 -0
- package/dist/provider.d.ts +8 -17
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +53 -58
- package/dist/provider.js.map +1 -1
- package/dist/routing/document.d.ts +11 -12
- package/dist/routing/document.d.ts.map +1 -1
- package/dist/routing/document.js.map +1 -1
- package/dist/routing/index.d.ts +50 -12
- package/dist/routing/index.d.ts.map +1 -1
- package/dist/routing/index.js +129 -54
- package/dist/routing/index.js.map +1 -1
- package/dist/routing/operations.d.ts +148 -0
- package/dist/routing/operations.d.ts.map +1 -0
- package/dist/routing/operations.js +234 -0
- package/dist/routing/operations.js.map +1 -0
- package/dist/routing/store.d.ts +28 -31
- package/dist/routing/store.d.ts.map +1 -1
- package/dist/routing/store.js +124 -81
- package/dist/routing/store.js.map +1 -1
- package/dist/routing/target.d.ts.map +1 -1
- package/dist/routing/target.js.map +1 -1
- package/dist/session/card-actions.d.ts +147 -0
- package/dist/session/card-actions.d.ts.map +1 -0
- package/dist/session/card-actions.js +440 -0
- package/dist/session/card-actions.js.map +1 -0
- package/dist/session/lifecycle.d.ts +20 -0
- package/dist/session/lifecycle.d.ts.map +1 -0
- package/dist/session/lifecycle.js +48 -0
- package/dist/session/lifecycle.js.map +1 -0
- package/dist/session/session.d.ts +88 -0
- package/dist/session/session.d.ts.map +1 -0
- package/dist/session/session.js +342 -0
- package/dist/session/session.js.map +1 -0
- package/dist/session/submitter.d.ts +29 -0
- package/dist/session/submitter.d.ts.map +1 -0
- package/dist/session/submitter.js +46 -0
- package/dist/session/submitter.js.map +1 -0
- package/dist/tools/ask-user-question.d.ts +1 -1
- package/dist/tools/ask-user-question.d.ts.map +1 -1
- package/dist/tools/ask-user-question.js +4 -2
- package/dist/tools/ask-user-question.js.map +1 -1
- package/dist/tools/document-tools.d.ts.map +1 -1
- package/dist/tools/document-tools.js +14 -10
- package/dist/tools/document-tools.js.map +1 -1
- package/dist/tools/messaging-tools.d.ts +0 -7
- package/dist/tools/messaging-tools.d.ts.map +1 -1
- package/dist/tools/messaging-tools.js +19 -7
- package/dist/tools/messaging-tools.js.map +1 -1
- package/dist/tools/registry.d.ts +5 -0
- package/dist/tools/registry.d.ts.map +1 -1
- package/dist/tools/registry.js +10 -3
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/routing-tools.d.ts.map +1 -1
- package/dist/tools/routing-tools.js +12 -12
- package/dist/tools/routing-tools.js.map +1 -1
- package/dist/{feishu-session-mcp.d.ts → tools/session-mcp.d.ts} +5 -3
- package/dist/tools/session-mcp.d.ts.map +1 -0
- package/dist/tools/session-mcp.js +66 -0
- package/dist/tools/session-mcp.js.map +1 -0
- package/dist/tools/space-tools.d.ts.map +1 -1
- package/dist/tools/space-tools.js +5 -8
- package/dist/tools/space-tools.js.map +1 -1
- package/dist/tools/types.d.ts +18 -84
- package/dist/tools/types.d.ts.map +1 -1
- package/package.json +7 -6
- package/dist/feishu-ask-user-card.d.ts.map +0 -1
- package/dist/feishu-ask-user-card.js.map +0 -1
- package/dist/feishu-ask-user.d.ts.map +0 -1
- package/dist/feishu-ask-user.js.map +0 -1
- package/dist/feishu-binding-notification-card.d.ts.map +0 -1
- package/dist/feishu-binding-notification-card.js.map +0 -1
- package/dist/feishu-card.d.ts +0 -22
- package/dist/feishu-card.d.ts.map +0 -1
- package/dist/feishu-card.js +0 -44
- package/dist/feishu-card.js.map +0 -1
- package/dist/feishu-channel.d.ts +0 -139
- package/dist/feishu-channel.d.ts.map +0 -1
- package/dist/feishu-channel.js +0 -506
- package/dist/feishu-channel.js.map +0 -1
- package/dist/feishu-cot-activity.d.ts +0 -65
- package/dist/feishu-cot-activity.d.ts.map +0 -1
- package/dist/feishu-cot-activity.js +0 -127
- package/dist/feishu-cot-activity.js.map +0 -1
- package/dist/feishu-cot-adapter.d.ts.map +0 -1
- package/dist/feishu-cot-adapter.js.map +0 -1
- package/dist/feishu-cot-diagnostics.d.ts.map +0 -1
- package/dist/feishu-cot-diagnostics.js.map +0 -1
- package/dist/feishu-cot-events.d.ts.map +0 -1
- package/dist/feishu-cot-events.js +0 -323
- package/dist/feishu-cot-events.js.map +0 -1
- package/dist/feishu-cot-io.d.ts.map +0 -1
- package/dist/feishu-cot-io.js.map +0 -1
- package/dist/feishu-cot-outbox.d.ts +0 -18
- package/dist/feishu-cot-outbox.d.ts.map +0 -1
- package/dist/feishu-cot-outbox.js +0 -65
- package/dist/feishu-cot-outbox.js.map +0 -1
- package/dist/feishu-cot-presentation.d.ts +0 -82
- package/dist/feishu-cot-presentation.d.ts.map +0 -1
- package/dist/feishu-cot-presentation.js +0 -208
- package/dist/feishu-cot-presentation.js.map +0 -1
- package/dist/feishu-cot-session.d.ts +0 -52
- package/dist/feishu-cot-session.d.ts.map +0 -1
- package/dist/feishu-cot-session.js +0 -132
- package/dist/feishu-cot-session.js.map +0 -1
- package/dist/feishu-cot-state.d.ts.map +0 -1
- package/dist/feishu-cot-state.js.map +0 -1
- package/dist/feishu-gate-io.d.ts +0 -39
- package/dist/feishu-gate-io.d.ts.map +0 -1
- package/dist/feishu-gate-io.js +0 -111
- package/dist/feishu-gate-io.js.map +0 -1
- package/dist/feishu-gate.d.ts +0 -106
- package/dist/feishu-gate.d.ts.map +0 -1
- package/dist/feishu-gate.js.map +0 -1
- package/dist/feishu-inbound-anchor.d.ts +0 -21
- package/dist/feishu-inbound-anchor.d.ts.map +0 -1
- package/dist/feishu-inbound-anchor.js.map +0 -1
- package/dist/feishu-inbound-enrichment.d.ts.map +0 -1
- package/dist/feishu-inbound-enrichment.js.map +0 -1
- package/dist/feishu-inbound-work.d.ts.map +0 -1
- package/dist/feishu-inbound-work.js.map +0 -1
- package/dist/feishu-message-render.d.ts.map +0 -1
- package/dist/feishu-message-render.js.map +0 -1
- package/dist/feishu-message.d.ts.map +0 -1
- package/dist/feishu-message.js.map +0 -1
- package/dist/feishu-pairing-card.d.ts.map +0 -1
- package/dist/feishu-pairing-card.js.map +0 -1
- package/dist/feishu-reply-ancestry.d.ts.map +0 -1
- package/dist/feishu-reply-ancestry.js.map +0 -1
- package/dist/feishu-route-reconciliation.d.ts +0 -55
- package/dist/feishu-route-reconciliation.d.ts.map +0 -1
- package/dist/feishu-route-reconciliation.js +0 -66
- package/dist/feishu-route-reconciliation.js.map +0 -1
- package/dist/feishu-running-teams-card.d.ts.map +0 -1
- package/dist/feishu-running-teams-card.js.map +0 -1
- package/dist/feishu-session-bindings.d.ts +0 -66
- package/dist/feishu-session-bindings.d.ts.map +0 -1
- package/dist/feishu-session-bindings.js +0 -117
- package/dist/feishu-session-bindings.js.map +0 -1
- package/dist/feishu-session-inbound.d.ts +0 -16
- package/dist/feishu-session-inbound.d.ts.map +0 -1
- package/dist/feishu-session-inbound.js.map +0 -1
- package/dist/feishu-session-mcp.d.ts.map +0 -1
- package/dist/feishu-session-mcp.js +0 -50
- package/dist/feishu-session-mcp.js.map +0 -1
- package/dist/feishu-session-ops.d.ts +0 -130
- package/dist/feishu-session-ops.d.ts.map +0 -1
- package/dist/feishu-session-ops.js +0 -483
- package/dist/feishu-session-ops.js.map +0 -1
- package/dist/feishu-target-router.d.ts +0 -84
- package/dist/feishu-target-router.d.ts.map +0 -1
- package/dist/feishu-target-router.js.map +0 -1
- package/dist/lib/mutex.d.ts +0 -9
- package/dist/lib/mutex.d.ts.map +0 -1
- package/dist/lib/mutex.js +0 -13
- package/dist/lib/mutex.js.map +0 -1
- package/dist/provider-ref.d.ts +0 -8
- package/dist/provider-ref.d.ts.map +0 -1
- package/dist/provider-ref.js +0 -8
- package/dist/provider-ref.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
# @excitedjs/feishu-channel
|
|
2
2
|
|
|
3
|
-
The built-in Feishu
|
|
4
|
-
|
|
3
|
+
The built-in Feishu **plugin** for [Dreamux](../../dreamux): it contributes the
|
|
4
|
+
Feishu `ChannelProvider` behind the `builtin:feishu` provider reference and
|
|
5
|
+
publishes an extension api for other plugins. The provider implements the
|
|
5
6
|
neutral `@excitedjs/dreamux-types` channel contract on top of
|
|
6
7
|
[`@excitedjs/feishu-transport`](../feishu-transport), which stays the sole owner
|
|
7
8
|
of the Lark SDK.
|
|
8
9
|
|
|
9
|
-
`@excitedjs/dreamux` depends on this package
|
|
10
|
-
|
|
10
|
+
`@excitedjs/dreamux` depends on this package and always loads its plugin, so
|
|
11
|
+
the Feishu channel ships out of the box.
|
|
11
12
|
|
|
12
13
|
## What it owns
|
|
13
14
|
|
|
@@ -17,7 +18,7 @@ of the Lark SDK.
|
|
|
17
18
|
store, read and written under a host-supplied state directory.
|
|
18
19
|
- **Inbound normalization**: turning Feishu events into agent-facing channel
|
|
19
20
|
results, including the Channel-owned inner body and inline `<attachment>`
|
|
20
|
-
blocks.
|
|
21
|
+
blocks. Core owns the outer `<channel source="feishu" …>` envelope.
|
|
21
22
|
- **Topic routing**: verifying `chat_mode=topic`, projecting `thread_id` as a
|
|
22
23
|
neutral collaboration target, and recording exact per-message targets for
|
|
23
24
|
scoped TeamLeader replies.
|
|
@@ -32,34 +33,46 @@ of the Lark SDK.
|
|
|
32
33
|
## What it does not own
|
|
33
34
|
|
|
34
35
|
- It never imports `@excitedjs/dreamux` core, and never imports the Lark SDK
|
|
35
|
-
directly — platform calls go through `@excitedjs/feishu-transport`.
|
|
36
|
-
|
|
37
|
-
- Dispatcher lifecycle, agent
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
directly — platform calls go through `@excitedjs/feishu-transport`. The Core
|
|
37
|
+
import boundary is enforced by the shared lint configuration.
|
|
38
|
+
- Dispatcher lifecycle, agent process supervision, Team lifecycle, the neutral
|
|
39
|
+
command port, and MCP lease/shim routing stay in `@excitedjs/dreamux`.
|
|
40
|
+
Feishu routing, binding state, access policy, and tool definitions belong to
|
|
41
|
+
this package. The host supplies the bot
|
|
40
42
|
secret / app id and the state / cache directories; the package reconstructs no
|
|
41
43
|
Dreamux host layout or path contract.
|
|
42
44
|
|
|
43
45
|
## Public API
|
|
44
46
|
|
|
45
|
-
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
`
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
47
|
+
- The default export is the neutral provider factory for
|
|
48
|
+
`npm:@excitedjs/feishu-channel`. `createFeishuPlugin()` is the named plugin
|
|
49
|
+
factory. The plugin
|
|
50
|
+
contributes the `feishu` channel provider (`builtin:feishu`) and publishes
|
|
51
|
+
`FeishuApi`, through which another plugin registers Feishu extensions: extra
|
|
52
|
+
MCP tools, card actions, and a per-channel-instance lifecycle with an
|
|
53
|
+
instance api (`FeishuExtension`, `FeishuInstanceApi`).
|
|
54
|
+
- `createFeishuChannelProvider()` — the same provider with no extensions. Its
|
|
55
|
+
`createSession` returns a `ChannelInstance`: a `session` with
|
|
56
|
+
`initialize` / `start` / `close`, plus the optional `mcp` capability beside it.
|
|
57
|
+
- The public extension contracts and inbound message formatter support plugin
|
|
58
|
+
authors and cross-package callers. Session, gate, stores, tool parsers, and
|
|
59
|
+
bot adapter implementations remain package-internal.
|
|
60
|
+
|
|
61
|
+
Successful submission receipts can carry a Dreamux Turn identifier. The
|
|
62
|
+
channel distinguishes admitted, duplicate, stopped, failed, ambiguous, and
|
|
63
|
+
proven Team-rejection outcomes. A proven pre-admission Team rejection permits
|
|
64
|
+
the bound-route fallback; ambiguous delivery is never replayed. The read-only
|
|
65
|
+
core event stream projects
|
|
59
66
|
sanitized submitted, activity, and settled lifecycle facts for dispatcher and
|
|
60
67
|
TeamLeader conversations; Feishu anchors each presentation to the turn's
|
|
61
68
|
inbound message.
|
|
62
69
|
|
|
70
|
+
Binding a topic retires the displaced Team's presentation even when that Team
|
|
71
|
+
served the topic through its parent group. Removing an exact topic binding
|
|
72
|
+
retires that route's presentation and permits fresh submissions through a
|
|
73
|
+
remaining parent binding, including one to the same Team. A standing anchor
|
|
74
|
+
keeps the serving-route provenance captured when it was created.
|
|
75
|
+
|
|
63
76
|
Test doubles are deliberately test-local and are not part of the published
|
|
64
77
|
package API.
|
|
65
78
|
|
|
@@ -72,7 +85,7 @@ non-empty sender id. Other chat types fail with `unsupported_chat_type`, and
|
|
|
72
85
|
other sender shapes fail with `sender_unknown`, before bot observation,
|
|
73
86
|
`/introduce`, pairing, or delivery.
|
|
74
87
|
|
|
75
|
-
The
|
|
88
|
+
The `dreamuxFeishuGate` input is unchanged: it still has `chat_type` and
|
|
76
89
|
`is_bot_sender` and has no `sender_kind`. Callers must perform the exact
|
|
77
90
|
classification above first. Passing `is_bot_sender: false` asserts a known
|
|
78
91
|
human; negating `isBotSenderType(...)` alone is not sufficient because unknown
|
|
@@ -98,7 +111,7 @@ takes effect when the new server starts.
|
|
|
98
111
|
may deliver ordinary text in a trusted chat but cannot mutate peer-bot trust;
|
|
99
112
|
the command is diagnosed as `sender_not_followed` and writes no trust.
|
|
100
113
|
|
|
101
|
-
## Feishu
|
|
114
|
+
## Feishu chat information permission
|
|
102
115
|
|
|
103
116
|
Topic collaboration routing reads the enclosing chat through Feishu's
|
|
104
117
|
`im.v1.chat.get` API. The bot must have a group information read permission
|
|
@@ -111,6 +124,21 @@ display attributes, so runtimes render it in the model-visible `<channel>`
|
|
|
111
124
|
envelope. Displaying that identifier does not classify an ordinary group
|
|
112
125
|
thread as a collaboration topic.
|
|
113
126
|
|
|
127
|
+
The same read can decide who may answer a card, as a last resort. A click on
|
|
128
|
+
an ask-user or extension card names its chat but not whether that chat is
|
|
129
|
+
direct or a group, so the channel applies the inbound access policy for both
|
|
130
|
+
kinds and establishes the kind only when the two answers differ. It takes the
|
|
131
|
+
kind from the chat itself, never from the access lists it is judging: the kind
|
|
132
|
+
reported by the last admitted inbound message this session routed in that chat
|
|
133
|
+
(a group message dropped for lacking a mention, an untrusted bot's message, or
|
|
134
|
+
a consumed `/introduce` teaches nothing). Only then does it ask the platform. A person the policy
|
|
135
|
+
admits in a direct chat and in a group alike, or in neither, never triggers the
|
|
136
|
+
read. When the answer does depend on the kind and it cannot be established, the
|
|
137
|
+
click is refused with an error toast rather than degrading to an ordinary group
|
|
138
|
+
as topic detection does, which on an install whose bot lacks the group
|
|
139
|
+
information read permission affects only a click in a chat this session has not
|
|
140
|
+
yet routed an admitted message from.
|
|
141
|
+
|
|
114
142
|
A confirmed topic target declares its enclosing group as a less-specific
|
|
115
143
|
binding fallback. An exact topic binding wins first; a bound collaboration
|
|
116
144
|
space then provisions or reuses the exact topic Team; only a topic group that
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feishu access gate v3 — the pure decision function.
|
|
3
|
+
*
|
|
4
|
+
* `dreamuxFeishuGate` decides `deliver | drop | pair` against a snapshot of
|
|
5
|
+
* `DispatcherAccessStateV3` (`./state.js`) and returns the next state plus
|
|
6
|
+
* logs. It touches no disk and sends nothing; the session owns IO, the access
|
|
7
|
+
* store's serialized queue, and send-before-save for pairing prompts (see
|
|
8
|
+
* `./index.js`'s `FeishuAccess`).
|
|
9
|
+
*/
|
|
10
|
+
import { type DispatcherAccessStateV3, type PendingPairingKind } from './state.js';
|
|
11
|
+
export declare function generatePairingToken(): string;
|
|
12
|
+
export declare function generateUniquePairingToken(existing: Record<string, unknown>): string;
|
|
13
|
+
export interface GateInbound {
|
|
14
|
+
chat_type: 'p2p' | 'group';
|
|
15
|
+
sender_id: string;
|
|
16
|
+
chat_id: string;
|
|
17
|
+
/**
|
|
18
|
+
* The session must classify the sender exactly before calling the gate:
|
|
19
|
+
* `false` means sender_type=user with a non-empty sender id, not merely
|
|
20
|
+
* "isBotSenderType returned false" for an unknown sender type.
|
|
21
|
+
*/
|
|
22
|
+
is_bot_sender: boolean;
|
|
23
|
+
trusted_bot: boolean;
|
|
24
|
+
bot_mentioned: boolean;
|
|
25
|
+
}
|
|
26
|
+
export type DropReason = 'dm_disabled' | 'dm_not_on_allowlist' | 'dm_pairing_slot_cap' | 'group_policy_block' | 'group_bot_not_mentioned' | 'group_not_on_allowlist_and_not_mentioned' | 'group_follow_user_stranger_not_mentioned' | 'group_pairing_slot_cap' | 'group_not_on_allowlist' | 'group_user_not_on_allowlist' | 'group_pairing_stranger_not_mentioned' | 'bot_untrusted' | 'unsupported_chat_type' | 'internal';
|
|
27
|
+
export type GateAction = {
|
|
28
|
+
action: 'deliver';
|
|
29
|
+
} | {
|
|
30
|
+
action: 'drop';
|
|
31
|
+
reason: DropReason;
|
|
32
|
+
context?: Record<string, unknown>;
|
|
33
|
+
} | {
|
|
34
|
+
action: 'pair';
|
|
35
|
+
kind: PendingPairingKind;
|
|
36
|
+
token: string;
|
|
37
|
+
is_resend: boolean;
|
|
38
|
+
ttl_left_ms: number;
|
|
39
|
+
prompt_message_id?: string;
|
|
40
|
+
};
|
|
41
|
+
export interface GateResult {
|
|
42
|
+
action: GateAction;
|
|
43
|
+
nextState: DispatcherAccessStateV3;
|
|
44
|
+
logs: Array<{
|
|
45
|
+
level: 'debug' | 'info' | 'warn' | 'error';
|
|
46
|
+
msg: string;
|
|
47
|
+
ctx?: Record<string, unknown>;
|
|
48
|
+
}>;
|
|
49
|
+
}
|
|
50
|
+
export declare function pruneExpiredPending(state: DispatcherAccessStateV3, now: number): DispatcherAccessStateV3;
|
|
51
|
+
export declare function dreamuxFeishuGate(state: DispatcherAccessStateV3, input: GateInbound, now?: number): GateResult;
|
|
52
|
+
//# sourceMappingURL=gate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../../src/access/gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,EAIL,KAAK,uBAAuB,EAE5B,KAAK,kBAAkB,EACxB,MAAM,YAAY,CAAC;AAMpB,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,MAAM,CAOR;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,KAAK,GAAG,OAAO,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,aAAa,EAAE,OAAO,CAAC;IACvB,WAAW,EAAE,OAAO,CAAC;IACrB,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,MAAM,UAAU,GAClB,aAAa,GACb,qBAAqB,GACrB,qBAAqB,GACrB,oBAAoB,GACpB,yBAAyB,GAKzB,0CAA0C,GAC1C,0CAA0C,GAC1C,wBAAwB,GAExB,wBAAwB,GACxB,6BAA6B,GAC7B,sCAAsC,GACtC,eAAe,GACf,uBAAuB,GACvB,UAAU,CAAC;AAEf,MAAM,MAAM,UAAU,GAClB;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,GACrB;IACE,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC,GACD;IACE,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,kBAAkB,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEN,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,UAAU,CAAC;IACnB,SAAS,EAAE,uBAAuB,CAAC;IACnC,IAAI,EAAE,KAAK,CAAC;QACV,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;QAC3C,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAC/B,CAAC,CAAC;CACJ;AAQD,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,uBAAuB,EAC9B,GAAG,EAAE,MAAM,GACV,uBAAuB,CAWzB;AAmJD,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,uBAAuB,EAC9B,KAAK,EAAE,WAAW,EAClB,GAAG,GAAE,MAAmB,GACvB,UAAU,CA4IZ"}
|
|
@@ -1,55 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Feishu access gate v3 —
|
|
2
|
+
* Feishu access gate v3 — the pure decision function.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* pairing slots. An operator (human admin out-of-band) approves a 6-hex token
|
|
10
|
-
* to add a sender to `allow_users`. `group.allow_chats` is the operator-owned
|
|
11
|
-
* list of trusted human group memberships, not something pairing approval
|
|
12
|
-
* mutates.
|
|
4
|
+
* `dreamuxFeishuGate` decides `deliver | drop | pair` against a snapshot of
|
|
5
|
+
* `DispatcherAccessStateV3` (`./state.js`) and returns the next state plus
|
|
6
|
+
* logs. It touches no disk and sends nothing; the session owns IO, the access
|
|
7
|
+
* store's serialized queue, and send-before-save for pairing prompts (see
|
|
8
|
+
* `./index.js`'s `FeishuAccess`).
|
|
13
9
|
*/
|
|
14
10
|
import { randomBytes } from 'node:crypto';
|
|
11
|
+
import { MAX_PENDING, PAIRING_TOKEN_BYTES, PAIRING_TTL_MS, } from './state.js';
|
|
15
12
|
// ─────────────────────────────────────────────────────────────────────────
|
|
16
|
-
//
|
|
17
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
18
|
-
export const ACCESS_STATE_VERSION = 3;
|
|
19
|
-
// Ten active dm-kind onboarding slots keeps one dispatcher useful in a busy
|
|
20
|
-
// chat while bounding spam from many unknown senders.
|
|
21
|
-
export const MAX_PENDING_PER_KIND = 10;
|
|
22
|
-
export const PAIRING_TTL_MS = 60 * 60 * 1000;
|
|
23
|
-
export const PAIRING_TOKEN_BYTES = 3;
|
|
24
|
-
export const PAIRING_TOKEN_REGEX = /^[0-9a-fA-F]{6}$/;
|
|
25
|
-
const MAX_WARNINGS = 200;
|
|
26
|
-
/**
|
|
27
|
-
* Flag emitted into `state.warnings` when a single dispatcher observes traffic
|
|
28
|
-
* from more than one chat — the channel multiplexes chats over one runtime
|
|
29
|
-
* context, which is supported but worth surfacing to an operator once.
|
|
30
|
-
*/
|
|
31
|
-
export const TRUST_DOMAIN_WARNING = 'dispatcher shares one runtime context across multiple Feishu chats';
|
|
32
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
33
|
-
// Defaults
|
|
34
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
35
|
-
export function defaultDispatcherAccessState() {
|
|
36
|
-
return {
|
|
37
|
-
version: ACCESS_STATE_VERSION,
|
|
38
|
-
dm_policy: 'pairing',
|
|
39
|
-
group: {
|
|
40
|
-
policy: 'follow-user',
|
|
41
|
-
allow_chats: [],
|
|
42
|
-
require_mention: true,
|
|
43
|
-
},
|
|
44
|
-
allow_users: [],
|
|
45
|
-
pending: {},
|
|
46
|
-
observed_chats: [],
|
|
47
|
-
warnings: [],
|
|
48
|
-
last_gate: { at: 0 },
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
52
|
-
// Pairing token generators
|
|
13
|
+
// Pairing token generators — the token-minting half of the `pair` transition
|
|
53
14
|
// ─────────────────────────────────────────────────────────────────────────
|
|
54
15
|
export function generatePairingToken() {
|
|
55
16
|
return randomBytes(PAIRING_TOKEN_BYTES).toString('hex');
|
|
@@ -62,7 +23,7 @@ export function generateUniquePairingToken(existing) {
|
|
|
62
23
|
}
|
|
63
24
|
return token;
|
|
64
25
|
}
|
|
65
|
-
function pruneExpiredPending(state, now) {
|
|
26
|
+
export function pruneExpiredPending(state, now) {
|
|
66
27
|
const kept = {};
|
|
67
28
|
let anyRemoved = false;
|
|
68
29
|
for (const [token, entry] of Object.entries(state.pending)) {
|
|
@@ -75,54 +36,26 @@ function pruneExpiredPending(state, now) {
|
|
|
75
36
|
}
|
|
76
37
|
return anyRemoved ? { ...state, pending: kept } : state;
|
|
77
38
|
}
|
|
78
|
-
|
|
39
|
+
// Every live pending entry is dm-kind (the C3 semantic rewrite removed group
|
|
40
|
+
// pairing below), so an existing slot is found by sender alone.
|
|
41
|
+
function findExistingPendingByKey(pending, sender_id, now) {
|
|
79
42
|
for (const [token, entry] of Object.entries(pending)) {
|
|
80
43
|
if (entry.expires_at <= now)
|
|
81
44
|
continue;
|
|
82
|
-
if (entry.
|
|
83
|
-
continue;
|
|
84
|
-
if (kind === 'dm' && entry.sender_id === sender_id) {
|
|
85
|
-
return { token, entry };
|
|
86
|
-
}
|
|
87
|
-
if (kind === 'group' && entry.chat_id === chat_id) {
|
|
45
|
+
if (entry.sender_id === sender_id) {
|
|
88
46
|
return { token, entry };
|
|
89
47
|
}
|
|
90
48
|
}
|
|
91
49
|
return null;
|
|
92
50
|
}
|
|
93
|
-
function
|
|
94
|
-
|
|
51
|
+
function countActivePending(pending, now) {
|
|
52
|
+
let count = 0;
|
|
95
53
|
for (const entry of Object.values(pending)) {
|
|
96
54
|
if (entry.expires_at <= now)
|
|
97
55
|
continue;
|
|
98
|
-
|
|
56
|
+
count += 1;
|
|
99
57
|
}
|
|
100
|
-
return
|
|
101
|
-
}
|
|
102
|
-
function pushWarn(warnings, at, msg, ctx) {
|
|
103
|
-
const next = [...warnings, { at, msg, ...(ctx ? { ctx } : {}) }];
|
|
104
|
-
// cap at MAX_WARNINGS FIFO
|
|
105
|
-
if (next.length > MAX_WARNINGS) {
|
|
106
|
-
return next.slice(next.length - MAX_WARNINGS);
|
|
107
|
-
}
|
|
108
|
-
return next;
|
|
109
|
-
}
|
|
110
|
-
function pushObserved(observed, chat_id) {
|
|
111
|
-
if (observed.includes(chat_id))
|
|
112
|
-
return observed;
|
|
113
|
-
return [...observed, chat_id];
|
|
114
|
-
}
|
|
115
|
-
function withLastGate(state, input, now, action, reason) {
|
|
116
|
-
return {
|
|
117
|
-
...state,
|
|
118
|
-
last_gate: {
|
|
119
|
-
at: now,
|
|
120
|
-
sender_id: input.sender_id,
|
|
121
|
-
chat_id: input.chat_id,
|
|
122
|
-
action,
|
|
123
|
-
...(reason !== undefined ? { reason } : {}),
|
|
124
|
-
},
|
|
125
|
-
};
|
|
58
|
+
return count;
|
|
126
59
|
}
|
|
127
60
|
// NOTE: groupPairPath was removed as part of the C3 semantic rewrite.
|
|
128
61
|
// group.allow_chats is operator-maintained; there is no pairing mechanism to
|
|
@@ -130,28 +63,25 @@ function withLastGate(state, input, now, action, reason) {
|
|
|
130
63
|
// dmPairPath and end up as dm-kind entries on allow_users.
|
|
131
64
|
function dmPairPath(opts) {
|
|
132
65
|
const { state, input, now, logs } = opts;
|
|
133
|
-
const existing = findExistingPendingByKey(state.pending,
|
|
66
|
+
const existing = findExistingPendingByKey(state.pending, input.sender_id, now);
|
|
134
67
|
if (existing !== null) {
|
|
135
68
|
const { token, entry } = existing;
|
|
136
69
|
const newEntry = {
|
|
137
70
|
...entry,
|
|
138
71
|
expires_at: now + PAIRING_TTL_MS,
|
|
139
72
|
};
|
|
140
|
-
|
|
73
|
+
const nextState = {
|
|
141
74
|
...state,
|
|
142
75
|
pending: { ...state.pending, [token]: newEntry },
|
|
143
76
|
};
|
|
144
|
-
nextState = withLastGate(nextState, input, now, 'pair');
|
|
145
|
-
nextState = { ...nextState, observed_chats: pushObserved(nextState.observed_chats, input.chat_id) };
|
|
146
77
|
logs.push({
|
|
147
78
|
level: 'info',
|
|
148
79
|
msg: 'dm pairing: existing prompt',
|
|
149
80
|
ctx: {
|
|
150
|
-
token,
|
|
81
|
+
pairing_token_len: token.length,
|
|
151
82
|
sender_id: input.sender_id,
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
: {}),
|
|
83
|
+
chat_id: input.chat_id,
|
|
84
|
+
prompt_message_id: entry.prompt_message_id,
|
|
155
85
|
},
|
|
156
86
|
});
|
|
157
87
|
return {
|
|
@@ -169,50 +99,42 @@ function dmPairPath(opts) {
|
|
|
169
99
|
logs,
|
|
170
100
|
};
|
|
171
101
|
}
|
|
172
|
-
const
|
|
173
|
-
if (
|
|
174
|
-
const msg = 'dm pairing: slot cap reached';
|
|
175
|
-
const warnings = pushWarn(state.warnings, now, msg, {
|
|
176
|
-
count: counts.dm,
|
|
177
|
-
sender_id: input.sender_id,
|
|
178
|
-
});
|
|
102
|
+
const count = countActivePending(state.pending, now);
|
|
103
|
+
if (count >= MAX_PENDING) {
|
|
179
104
|
logs.push({
|
|
180
105
|
level: 'warn',
|
|
181
|
-
msg,
|
|
182
|
-
ctx: { count:
|
|
106
|
+
msg: 'dm pairing: slot cap reached',
|
|
107
|
+
ctx: { count, sender_id: input.sender_id, chat_id: input.chat_id },
|
|
183
108
|
});
|
|
184
|
-
let nextState = { ...state, warnings };
|
|
185
|
-
nextState = withLastGate(nextState, input, now, 'drop', 'dm_pairing_slot_cap');
|
|
186
|
-
nextState = { ...nextState, observed_chats: pushObserved(nextState.observed_chats, input.chat_id) };
|
|
187
109
|
return {
|
|
188
110
|
action: {
|
|
189
111
|
action: 'drop',
|
|
190
112
|
reason: 'dm_pairing_slot_cap',
|
|
191
|
-
context: { pending:
|
|
113
|
+
context: { pending: count, max: MAX_PENDING },
|
|
192
114
|
},
|
|
193
|
-
nextState,
|
|
115
|
+
nextState: state,
|
|
194
116
|
logs,
|
|
195
117
|
};
|
|
196
118
|
}
|
|
197
119
|
const token = generateUniquePairingToken(state.pending);
|
|
198
120
|
const entry = {
|
|
199
|
-
kind: 'dm',
|
|
200
121
|
sender_id: input.sender_id,
|
|
201
122
|
chat_id: input.chat_id,
|
|
202
123
|
created_at: now,
|
|
203
124
|
expires_at: now + PAIRING_TTL_MS,
|
|
204
|
-
replies: 1,
|
|
205
125
|
};
|
|
206
|
-
|
|
126
|
+
const nextState = {
|
|
207
127
|
...state,
|
|
208
128
|
pending: { ...state.pending, [token]: entry },
|
|
209
129
|
};
|
|
210
|
-
nextState = withLastGate(nextState, input, now, 'pair');
|
|
211
|
-
nextState = { ...nextState, observed_chats: pushObserved(nextState.observed_chats, input.chat_id) };
|
|
212
130
|
logs.push({
|
|
213
131
|
level: 'info',
|
|
214
132
|
msg: 'dm pairing: new slot',
|
|
215
|
-
ctx: {
|
|
133
|
+
ctx: {
|
|
134
|
+
pairing_token_len: token.length,
|
|
135
|
+
sender_id: input.sender_id,
|
|
136
|
+
chat_id: input.chat_id,
|
|
137
|
+
},
|
|
216
138
|
});
|
|
217
139
|
return {
|
|
218
140
|
action: {
|
|
@@ -234,25 +156,7 @@ export function dreamuxFeishuGate(state, input, now = Date.now()) {
|
|
|
234
156
|
// Double-guard TTL — prune first, then helpers also check expires_at > now.
|
|
235
157
|
let working = pruneExpiredPending(state, now);
|
|
236
158
|
const finish = (action, mutate = (s) => s) => {
|
|
237
|
-
|
|
238
|
-
s = { ...s, observed_chats: pushObserved(s.observed_chats, input.chat_id) };
|
|
239
|
-
// Attach trust-domain warning if we observe multiple chats.
|
|
240
|
-
if (s.observed_chats.length > 1 &&
|
|
241
|
-
!s.warnings.some((w) => w.msg === TRUST_DOMAIN_WARNING)) {
|
|
242
|
-
s = {
|
|
243
|
-
...s,
|
|
244
|
-
warnings: pushWarn(s.warnings, now, TRUST_DOMAIN_WARNING),
|
|
245
|
-
};
|
|
246
|
-
logs.push({ level: 'warn', msg: TRUST_DOMAIN_WARNING });
|
|
247
|
-
}
|
|
248
|
-
const actionStr = action.action === 'drop'
|
|
249
|
-
? `drop:${action.reason}`
|
|
250
|
-
: action.action === 'pair'
|
|
251
|
-
? `pair:${action.kind}`
|
|
252
|
-
: 'deliver';
|
|
253
|
-
const reason = action.action === 'drop' ? action.reason : undefined;
|
|
254
|
-
s = withLastGate(s, input, now, actionStr, reason);
|
|
255
|
-
return { action, nextState: s, logs };
|
|
159
|
+
return { action, nextState: mutate(working), logs };
|
|
256
160
|
};
|
|
257
161
|
// ── DM ────────────────────────────────────────────────────────────────
|
|
258
162
|
if (input.chat_type === 'p2p') {
|
|
@@ -372,7 +276,4 @@ export function dreamuxFeishuGate(state, input, now = Date.now()) {
|
|
|
372
276
|
// Unsupported
|
|
373
277
|
return finish({ action: 'drop', reason: 'unsupported_chat_type' });
|
|
374
278
|
}
|
|
375
|
-
|
|
376
|
-
// public surface so callers (feishu-channel.ts, tests) need no change.
|
|
377
|
-
export { loadDispatcherAccess, readDispatcherAccess, saveDispatcherAccess, } from './feishu-gate-io.js';
|
|
378
|
-
//# sourceMappingURL=feishu-gate.js.map
|
|
279
|
+
//# sourceMappingURL=gate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate.js","sourceRoot":"","sources":["../../src/access/gate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Owns the session's access state and every gate, pairing, and approval
|
|
3
|
+
* transition. Inbound owns message IO: it asks for a gate decision, sends the
|
|
4
|
+
* card or reference outside the store queue, then records successful delivery.
|
|
5
|
+
* Access is loaded lazily, so a malformed file fails the operation that reads it.
|
|
6
|
+
*/
|
|
7
|
+
import type { DreamuxLogger } from '@excitedjs/dreamux-types';
|
|
8
|
+
import { type GateAction, type GateInbound } from './gate.js';
|
|
9
|
+
type PairingAction = Extract<GateAction, {
|
|
10
|
+
action: 'pair';
|
|
11
|
+
}>;
|
|
12
|
+
export interface PairingApprovalResult {
|
|
13
|
+
status: 'ok' | 'not_found' | 'error';
|
|
14
|
+
message: string;
|
|
15
|
+
details?: Record<string, unknown>;
|
|
16
|
+
}
|
|
17
|
+
export interface FeishuAccessOptions {
|
|
18
|
+
/** The dispatcher's durable state directory; `access.json` sits under it. */
|
|
19
|
+
stateDir: string;
|
|
20
|
+
dispatcherId: string;
|
|
21
|
+
log: DreamuxLogger;
|
|
22
|
+
}
|
|
23
|
+
export declare class FeishuAccess {
|
|
24
|
+
private readonly store;
|
|
25
|
+
private readonly dispatcherId;
|
|
26
|
+
private readonly log;
|
|
27
|
+
constructor(opts: FeishuAccessOptions);
|
|
28
|
+
/** Snapshot the policy used before bot observation or /introduce. */
|
|
29
|
+
inboundPolicy(input: {
|
|
30
|
+
chatType: 'p2p' | 'group';
|
|
31
|
+
chatId: string;
|
|
32
|
+
senderId: string;
|
|
33
|
+
}): Promise<{
|
|
34
|
+
observeBots: boolean;
|
|
35
|
+
introduceDenyReason: import("../introduce.js").IntroduceDenyReason | null;
|
|
36
|
+
}>;
|
|
37
|
+
/**
|
|
38
|
+
* What the gate would decide for this person, against the held state,
|
|
39
|
+
* committing nothing. For a caller that is not answering a message and so has
|
|
40
|
+
* no conversation to send a pairing card into: a `pair` outcome here mints a
|
|
41
|
+
* token nobody stores, and it means "not admitted" like a drop does.
|
|
42
|
+
*/
|
|
43
|
+
decide(inbound: GateInbound): Promise<GateAction>;
|
|
44
|
+
/** Commit deliver/drop; pairing waits until its message has been sent. */
|
|
45
|
+
gate(inbound: GateInbound): Promise<GateAction>;
|
|
46
|
+
/** Refresh an existing prompt only after inbound successfully references it. */
|
|
47
|
+
refreshPairing(action: PairingAction): Promise<void>;
|
|
48
|
+
/** Merge a sent card into the latest state, including any concurrent approval. */
|
|
49
|
+
recordPairingPrompt(inbound: GateInbound, action: PairingAction, messageId: string | undefined): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Load access.json from `stateDir`. Fails LOUDLY if the file exists but the
|
|
52
|
+
* shape is not v3, or a `pending` entry is missing/mistyped on `sender_id`,
|
|
53
|
+
* `chat_id`, `expires_at`, or `created_at`. A missing file returns the
|
|
54
|
+
* secure default (pairing DM default, empty allowlists).
|
|
55
|
+
*
|
|
56
|
+
* Reconstructs the returned value field by field rather than casting
|
|
57
|
+
* `parsed` as-is, so an old file's now-dropped ledger fields (`last_gate`,
|
|
58
|
+
* `observed_chats`, `warnings`) or per-entry fields (`kind`, `replies`) are
|
|
59
|
+
* read and discarded, never round-tripped into memory or back to disk.
|
|
60
|
+
*/
|
|
61
|
+
private readFromDisk;
|
|
62
|
+
/**
|
|
63
|
+
* Approve a pending pairing by its internal 6-hex token.
|
|
64
|
+
*
|
|
65
|
+
* Behavior:
|
|
66
|
+
* - Normalizes `token` to lowercase (the gate stores lowercased tokens).
|
|
67
|
+
* - Returns `not_found` when the token is unknown or expired (we reject
|
|
68
|
+
* expired entries explicitly, not just "not found", so the operator
|
|
69
|
+
* gets the right diagnostic).
|
|
70
|
+
* - Adds the DM sender to `allow_users`. Idempotent on allowlist
|
|
71
|
+
* membership (we detect duplicates via allowlist presence, not by
|
|
72
|
+
* whether the pending entry still has the slot), and always removes
|
|
73
|
+
* the pending key after a successful approval — the
|
|
74
|
+
* allowlist IS the source of truth, a pending entry is just a
|
|
75
|
+
* temporary token.
|
|
76
|
+
* - Details include `duplicate` flag, `ttl_left_ms`, `sender_id`,
|
|
77
|
+
* `chat_id`, `kind` for audit logging.
|
|
78
|
+
*
|
|
79
|
+
* The whole decide-and-write runs inside one `store.update()`, so it is
|
|
80
|
+
* serialized against every other access-state change this class makes.
|
|
81
|
+
* `not_found` and the duplicate-but-still-consumes-the-slot case are decided
|
|
82
|
+
* inside the `update` and returned unchanged (no write); the decide logic
|
|
83
|
+
* itself cannot throw. But `update()` also self-loads the store on its
|
|
84
|
+
* first call (never loaded at session start), and that load can throw on a
|
|
85
|
+
* malformed `access.json` — the `catch` below answers that case too, as
|
|
86
|
+
* `status: 'error'`.
|
|
87
|
+
*/
|
|
88
|
+
approvePairingByToken(token: string): Promise<PairingApprovalResult>;
|
|
89
|
+
/**
|
|
90
|
+
* Whether this sender is one of the Dispatcher's trusted humans.
|
|
91
|
+
*
|
|
92
|
+
* Reads this class's own held access store — the same store every gate
|
|
93
|
+
* decision and pairing write goes through — rather than a fresh disk read,
|
|
94
|
+
* so this always sees the value the running session actually committed
|
|
95
|
+
* last.
|
|
96
|
+
*/
|
|
97
|
+
isTrustedDispatcherUser(openId: string): Promise<boolean>;
|
|
98
|
+
}
|
|
99
|
+
export {};
|
|
100
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/access/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAY9D,OAAO,EAGL,KAAK,UAAU,EACf,KAAK,WAAW,EAEjB,MAAM,WAAW,CAAC;AAGnB,KAAK,aAAa,GAAG,OAAO,CAAC,UAAU,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AA6C7D,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,IAAI,GAAG,WAAW,GAAG,OAAO,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,mBAAmB;IAClC,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,aAAa,CAAC;CACpB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA4C;IAClE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAgB;gBAExB,IAAI,EAAE,mBAAmB;IAarC,qEAAqE;IAC/D,aAAa,CAAC,KAAK,EAAE;QACzB,QAAQ,EAAE,KAAK,GAAG,OAAO,CAAC;QAC1B,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;KAClB;;;;IASD;;;;;OAKG;IACG,MAAM,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAKvD,0EAA0E;IACpE,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAgBrD,gFAAgF;IAC1E,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB1D,kFAAkF;IAC5E,mBAAmB,CACvB,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,aAAa,EACrB,SAAS,EAAE,MAAM,GAAG,SAAS,GAC5B,OAAO,CAAC,IAAI,CAAC;IAoDhB;;;;;;;;;;OAUG;YACW,YAAY;IAwC1B;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACG,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAoF1E;;;;;;;OAOG;IACG,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAIhE"}
|