@@ -6,6 +6,78 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
66
77<!-- changelog:entries -->
88
9+ ## [0.1.111-rc.1] - 2026-07-19
10+
11+
12+ ### Added
13+
14+ - Feat(sdk/typescript): trigger system parity — dispatch, sugar, testing, demo (#510, #511, #512) (#796)
15+
16+ Implements the three remaining sub-issues of the TypeScript SDK trigger
17+ parity epic (#507):
18+
19+ #510 — Dispatch envelope unwrap + TriggerContext injection
20+ - New src/triggers/dispatch.ts: isTriggerEnvelope(), unwrapEnvelope(),
21+ applyTriggerTransform() — detects {event, _meta} envelope shape from
22+ the control plane dispatcher, constructs TriggerContext, applies the
23+ matched binding's transform
24+ - ReasonerContext gains trigger?: TriggerContext field
25+ - Agent.ts runReasoner() and local call() path wired to unwrap envelopes
26+ - Direct calls (no envelope) pass through unchanged
27+
28+ #511 — onEvent/onSchedule sugar + test helpers + fixtures
29+ - Agent.ts: app.onEvent(spec, handler) and app.onSchedule(cron, handler)
30+ sugar methods that forward to app.reasoner() with triggers
31+ - New src/triggers/testing.ts: simulateTrigger(), simulateSchedule(),
32+ loadFixture() for unit testing without a control plane
33+ - Copied 6 fixture JSONs from Python SDK (stripe, github, slack, cron,
34+ generic_hmac, generic_bearer)
35+
36+ #512 — examples/triggers-demo-ts + skill docs
37+ - New examples/triggers-demo-ts/: agent.ts (3 deterministic reasoners),
38+ Dockerfile, docker-compose.yml, README.md, fire-events.sh
39+ - New skills/agentfield-multi-reasoner-builder/references/triggers.md
40+ with Python + TypeScript scaffold reference
41+
42+ Tests: 744 pass (75 files), including 74 new trigger-specific tests.
43+ Build: tsc clean, tsup ESM+DTS success. (95fe429)
44+
45+
46+
47+ ### Fixed
48+
49+ - Fix(security): SSRF protection for approval callback_url (#435) (#790)
50+
51+ * fix(security): SSRF protection for approval callback_url (#435)
52+
53+ The approval callback_url field was accepted without SSRF validation and
54+ dispatched via a plain http.Client, allowing an attacker to use the
55+ control plane as a proxy to internal services (cloud metadata, RFC-1918,
56+ loopback).
57+
58+ Changes:
59+ - Validate callback_url at registration time using services.ValidateWebhookURL()
60+ to reject private/internal targets (localhost, 169.254.x, 10.x, 172.16.x,
61+ 192.168.x, ::1) before the URL is persisted.
62+ - Replace the plain http.Client in notifyApprovalCallback with
63+ services.NewSSRFSafeClient() which enforces DNS-rebinding-safe private-IP
64+ blocking at dial time.
65+ - Add comprehensive test coverage for both registration rejection and
66+ runtime transport enforcement.
67+
68+ Fixes #435
69+
70+ * fix(test): allowlist loopback in webhook helper test for SSRF-safe client
71+
72+ The existing TestExecuteReasonerAndWebhookHelpersCoverage test calls
73+ notifyApprovalCallback against a httptest server (127.0.0.1). After
74+ switching to NewSSRFSafeClient (#435), the SSRF transport rejects
75+ loopback as a private IP, causing the test to hang waiting for
76+ callbacks that never arrive.
77+
78+ Fix: set services.SetWebhookAllowedHosts([]string{"127.0.0.1"})
79+ before the callback calls so the httptest server is reachable. (7fb1193)
80+
981## [0.1.110] - 2026-07-18
1082
1183
0 commit comments