instar 1.3.48 → 1.3.50
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/dist/feedback-factory/dryrun/HttpParitySource.d.ts +82 -0
- package/dist/feedback-factory/dryrun/HttpParitySource.d.ts.map +1 -0
- package/dist/feedback-factory/dryrun/HttpParitySource.js +138 -0
- package/dist/feedback-factory/dryrun/HttpParitySource.js.map +1 -0
- package/dist/lifeline/TelegramLifeline.d.ts.map +1 -1
- package/dist/lifeline/TelegramLifeline.js +16 -0
- package/dist/lifeline/TelegramLifeline.js.map +1 -1
- package/dist/messaging/TelegramAdapter.d.ts +29 -0
- package/dist/messaging/TelegramAdapter.d.ts.map +1 -1
- package/dist/messaging/TelegramAdapter.js +53 -20
- package/dist/messaging/TelegramAdapter.js.map +1 -1
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +33 -1
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +47 -47
- package/upgrades/1.3.49.md +31 -0
- package/upgrades/1.3.50.md +70 -0
- package/upgrades/side-effects/feedback-factory-http-source.md +99 -0
- package/upgrades/side-effects/mentee-receiver-forward-dispatch.md +99 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Side-Effects Review — mentee receiver wiring fires on lifeline-forward path
|
|
2
|
+
|
|
3
|
+
**Spec:** `docs/specs/MENTOR-LIVE-READINESS-SPEC.md` §Recipient side.
|
|
4
|
+
Fast-follow to PR #462 (mentee receiver wiring) — closes the dual-path
|
|
5
|
+
ingress gap surfaced by dogfood.
|
|
6
|
+
|
|
7
|
+
**Change:** Three production files + three test files.
|
|
8
|
+
- `src/messaging/TelegramAdapter.ts` (+ ~55 LoC: `dispatchAgentMessageHook`
|
|
9
|
+
public method; polling text-dispatch now calls it instead of inlining the
|
|
10
|
+
hook logic — pure extraction, no behavior change on the polling path)
|
|
11
|
+
- `src/server/routes.ts` (+ ~20 LoC: destructure `senderIsBot` /
|
|
12
|
+
`senderChatId` / `senderBotId` from forward body; invoke
|
|
13
|
+
`dispatchAgentMessageHook` before `onTopicMessage`; short-circuit on
|
|
14
|
+
`handled:true`)
|
|
15
|
+
- `src/lifeline/TelegramLifeline.ts` (+ ~15 LoC: derive + include
|
|
16
|
+
`senderIsBot`/`senderChatId`/`senderBotId` in the forward body)
|
|
17
|
+
- `tests/unit/TelegramAdapter-dispatchAgentMessageHook.test.ts` (new, 8)
|
|
18
|
+
- `tests/integration/telegram-forward-a2a-dispatch.test.ts` (new, 3)
|
|
19
|
+
|
|
20
|
+
## What changed
|
|
21
|
+
|
|
22
|
+
1. **`dispatchAgentMessageHook` public method** on `TelegramAdapter`:
|
|
23
|
+
wraps the existing hook invocation with the FAIL-OPEN try/catch (a
|
|
24
|
+
broken hook never freezes the dispatch loop) and the senderBotId
|
|
25
|
+
derivation logic (sender_chat wins; rawFromId iff senderIsBot;
|
|
26
|
+
undefined for real users). Polling path now calls the dispatcher
|
|
27
|
+
instead of inlining the same code — pure extraction.
|
|
28
|
+
2. **`/internal/telegram-forward` handler** destructures the new spoof-
|
|
29
|
+
defense fields from the request body. Before invoking `onTopicMessage`,
|
|
30
|
+
calls `dispatchAgentMessageHook`. On `handled:true`, returns
|
|
31
|
+
`{ ok: true, forwarded: true, agentMessage: true }` (NEW response shape
|
|
32
|
+
addition — additive, doesn't change the existing `{ ok, forwarded }`
|
|
33
|
+
contract for non-a2a forwards). On hook throw, logs + falls through
|
|
34
|
+
(same fail-open semantics as the polling path).
|
|
35
|
+
3. **`TelegramLifeline.forwardToServer`** derives `senderIsBot` from
|
|
36
|
+
`rawMsg.from.is_bot === true`, `senderChatId` from
|
|
37
|
+
`rawMsg.sender_chat?.id`, `senderBotId` from `senderChatId ?? (isBot ?
|
|
38
|
+
rawMsg.from.id : undefined)`. Includes them in the buildBody output
|
|
39
|
+
only when they have values (omitted fields → server treats as falsy →
|
|
40
|
+
marker-bearing forwards drop closed for spoof defense).
|
|
41
|
+
|
|
42
|
+
## The seven questions
|
|
43
|
+
|
|
44
|
+
1. **Over-block.** N/A — additive. The forward route now invokes the hook
|
|
45
|
+
before `onTopicMessage`; if no hook is installed (or no adapter has
|
|
46
|
+
`dispatchAgentMessageHook`), the route falls through to the existing
|
|
47
|
+
behavior. Backward-compatible test (`preserves existing behavior when
|
|
48
|
+
the adapter has NO dispatchAgentMessageHook`) covers this.
|
|
49
|
+
2. **Under-block.** Spoof defense is end-to-end on the forwarded path:
|
|
50
|
+
missing `senderIsBot` from older lifelines → server treats as falsy →
|
|
51
|
+
any marker drops as `agent-marker-spoofed-by-user`. This is the
|
|
52
|
+
fail-CLOSED side, matching spec invariant.
|
|
53
|
+
3. **Level-of-abstraction fit.** Extraction-then-reuse: the hook
|
|
54
|
+
invocation logic moves from inlined to a method on the adapter, called
|
|
55
|
+
from both polling and forward paths. No new abstraction; just exposes
|
|
56
|
+
what was already there.
|
|
57
|
+
4. **Signal vs authority.** The dispatcher returns a clean boolean to the
|
|
58
|
+
caller; the caller decides whether to short-circuit. Authority lives in
|
|
59
|
+
the caller (route or polling loop), not in the dispatcher. Same as the
|
|
60
|
+
prior inline version.
|
|
61
|
+
5. **Interactions.** Reuses `agentMessageHook` set by `setAgentMessageHook`
|
|
62
|
+
— no new state. The forward route reads three new optional fields from
|
|
63
|
+
the body; older clients (lifeline pre-this-PR) omit them and get the
|
|
64
|
+
fail-CLOSED spoof defense automatically.
|
|
65
|
+
6. **External surfaces.** The `/internal/telegram-forward` response gains
|
|
66
|
+
one additive flag (`agentMessage: true`) when the hook claims the
|
|
67
|
+
message; the existing `{ ok, forwarded }` contract is preserved
|
|
68
|
+
otherwise. No new routes. No new config.
|
|
69
|
+
7. **Rollback cost.** Trivial — revert restores the inline hook call in
|
|
70
|
+
the polling path, drops the dispatcher and the forward-route call,
|
|
71
|
+
drops the lifeline body additions. The new `agentMessage:true` flag is
|
|
72
|
+
an additive response field, so any consumer relying on it would need a
|
|
73
|
+
one-line fix back to checking `forwarded:true` alone.
|
|
74
|
+
|
|
75
|
+
## Testing
|
|
76
|
+
|
|
77
|
+
11 new tests, all green (`tsc --noEmit` clean):
|
|
78
|
+
|
|
79
|
+
- **Tier 1 unit (8):** `TelegramAdapter-dispatchAgentMessageHook` covers
|
|
80
|
+
no-op safe (no hook), handled:true short-circuit, handled:false
|
|
81
|
+
fall-through, FAIL-OPEN on hook throw, three senderBotId derivation
|
|
82
|
+
modes (sender_chat / rawFromId+isBot / undefined for users), explicit
|
|
83
|
+
override.
|
|
84
|
+
- **Tier 2 integration (3):** `telegram-forward-a2a-dispatch` boots
|
|
85
|
+
`createRoutes` with a mock adapter through the real Express pipeline;
|
|
86
|
+
asserts short-circuit when hook claims, fall-through when not,
|
|
87
|
+
backward-compat when adapter lacks the method.
|
|
88
|
+
- **Tier 3 E2E:** the existing `mentee-receiver-lifecycle.test.ts` from
|
|
89
|
+
PR #462 (which installs the hook end-to-end on server boot) plus the
|
|
90
|
+
live dogfood loop that motivated this PR are the lifecycle proof.
|
|
91
|
+
|
|
92
|
+
## Migration parity
|
|
93
|
+
|
|
94
|
+
No config changes; no new config keys. The lifeline-side change is
|
|
95
|
+
deployed via the same npm release as the server-side change, so the
|
|
96
|
+
mixed-version state is only momentary (server upgrades alongside its
|
|
97
|
+
lifeline via the existing AutoUpdater + LifelineDriftPromoter pair).
|
|
98
|
+
Mixed-version safety is preserved either direction (server new / lifeline
|
|
99
|
+
old: spoof-fail-closed; server old / lifeline new: unknown fields ignored).
|