parse-stack-next 5.5.5 → 5.5.6
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +113 -0
- data/lib/parse/agent/mcp_rack_app.rb +29 -11
- data/lib/parse/stack/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b8f26110cea78b4a3fc393dce2ac3aada7d73442f7d1e970e2aa71d88d3ecba2
|
|
4
|
+
data.tar.gz: 753ead47dcc377ba89e5eca4d2e93a3f7767f5e71a168124f6f180fe7549b5a1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c1261b7e8db1b2d61e69fe70a1327829afd8d4c1b0960cb1ca1b3d5b418fcbc81b21dc05921a59865d7c226108392f0c3968a982277410872585b5cc4f42760a
|
|
7
|
+
data.tar.gz: 64f53a649209415edf4c3cecaab383f5ea01e0f106711ae867bfc7ac6d506dde592bd09b628a7956ccb621428ff4cea9c6f5970660d40465581496092b3d18ee
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,118 @@
|
|
|
1
1
|
## parse-stack-next Changelog
|
|
2
2
|
|
|
3
|
+
### 5.5.6
|
|
4
|
+
|
|
5
|
+
#### MCP clients now receive the SSE response instead of hanging
|
|
6
|
+
|
|
7
|
+
- **FIXED**: The Streamable HTTP SSE transport framed its events with custom
|
|
8
|
+
event names — `event: progress` for `notifications/progress` and
|
|
9
|
+
`event: response` for the final JSON-RPC response. MCP defines a single SSE
|
|
10
|
+
event type for JSON-RPC traffic, and clients match only the default
|
|
11
|
+
`message` type, so every frame the SDK emitted was silently discarded: tool
|
|
12
|
+
progress never surfaced, and, critically, the terminating response never
|
|
13
|
+
arrived, leaving the client blocked until its own timeout on any streaming
|
|
14
|
+
`tools/call`. All frames on both the request-scoped POST stream and the
|
|
15
|
+
server-to-client GET notification stream now carry `event: message`, and
|
|
16
|
+
clients discriminate from the JSON-RPC envelope (`method` present for a
|
|
17
|
+
notification, `id` plus `result`/`error` for a response) as the protocol
|
|
18
|
+
intends. Deployments that worked around this with a middleware rewriting
|
|
19
|
+
the event name can drop it.
|
|
20
|
+
|
|
21
|
+
### 5.5.5
|
|
22
|
+
|
|
23
|
+
#### Agent `call_method` runs under the caller's scope, not the master key
|
|
24
|
+
|
|
25
|
+
- **FIXED**: Instance `call_method` resolved its receiver with a bare
|
|
26
|
+
`klass.find` on the master-backed default client, so a scoped agent could
|
|
27
|
+
read — and through a write method, mutate — any object by id. The receiver
|
|
28
|
+
(both the real call and the dry-run existence check) is now fetched through
|
|
29
|
+
the requesting agent's scope: a session scope fetches with the session token
|
|
30
|
+
(Parse Server enforces ACL/CLP), an `acl_user` / `acl_role` scope routes
|
|
31
|
+
mongo-direct (ACL simulation), and a row the scope cannot read fails closed
|
|
32
|
+
to "not found". The method body runs inside the caller's session so its own
|
|
33
|
+
writes inherit the same principal, and an instance write/admin method under
|
|
34
|
+
an `acl_user` / `acl_role` scope — which has no session token to bind — is
|
|
35
|
+
refused rather than run with master authority.
|
|
36
|
+
- **FIXED**: Aggregation pipelines now default-deny joins under an active
|
|
37
|
+
tenant scope. A `$lookup` / `$graphLookup` / `$unionWith` sub-pipeline runs
|
|
38
|
+
in the joined collection's context with no tenant predicate injected, so any
|
|
39
|
+
such join could surface rows from other tenants; all are refused while a
|
|
40
|
+
tenant scope is active. The `$unionWith` bare-string shorthand
|
|
41
|
+
(`{ "$unionWith" => "Class" }`) is now covered by that guard as well as the
|
|
42
|
+
class-allowlist, hidden/underscore, and CLP-`find` gates, which previously
|
|
43
|
+
inspected only the Hash form.
|
|
44
|
+
- **IMPROVED**: Unimplemented agent tools now raise a typed
|
|
45
|
+
`Parse::Agent::NotImplemented` error, and tools without a handler are omitted
|
|
46
|
+
from tool listings.
|
|
47
|
+
|
|
48
|
+
#### Blank or injected credentials no longer escalate to the master key
|
|
49
|
+
|
|
50
|
+
- **FIXED**: An explicitly-supplied blank or whitespace `session_token:` no
|
|
51
|
+
longer falls through to the master key. It now fails closed to an anonymous
|
|
52
|
+
request (master suppressed, no session header) and does not fall back to a
|
|
53
|
+
bound or ambient token. `Parse.with_session` likewise rejects a blank token
|
|
54
|
+
at the source instead of storing a whitespace ambient that the request layer
|
|
55
|
+
would then drop.
|
|
56
|
+
- **FIXED**: The control options `use_master_key` and `session` can no longer
|
|
57
|
+
be set from a string-keyed conditions hash — the "forward a request params
|
|
58
|
+
hash straight into `Query.new` / `where`" pattern. `{"use_master_key" =>
|
|
59
|
+
true}` from untrusted params was an ACL/CLP-bypass mass-assignment; these two
|
|
60
|
+
keys are now honored only when passed as symbols (code-authored), and a
|
|
61
|
+
string form is treated as an ordinary field constraint with a warning.
|
|
62
|
+
|
|
63
|
+
#### Atlas Search and aggregation stay ACL-scoped
|
|
64
|
+
|
|
65
|
+
- **FIXED**: Atlas Search keeps `$search` at pipeline stage 0 while running the
|
|
66
|
+
scoped ACL/CLP enforcement chain (ACL `$match` folded after `$search`,
|
|
67
|
+
protectedFields strip, pointerFields filter, and a protected-field `$expr`
|
|
68
|
+
oracle guard). Query-derived constraints on the builder-block, options, and
|
|
69
|
+
autocomplete paths are converted to MongoDB storage form before the
|
|
70
|
+
post-`$search` `$match`, so a pointer/date/objectId constraint targets the
|
|
71
|
+
correct storage column and no longer fails BSON serialization.
|
|
72
|
+
- **FIXED**: `search_with_stage` rejects a non-`$search` stage and any
|
|
73
|
+
`returnStoredSource`, which could otherwise return only index-stored fields
|
|
74
|
+
(without `_rperm`), be read as public by the ACL match, and leak restricted
|
|
75
|
+
rows.
|
|
76
|
+
- **FIXED**: A scoped `$geoNear` folds the ACL predicate into `$geoNear.query`
|
|
77
|
+
rather than prepending a `$match`, keeping `$geoNear` at stage 0 so the query
|
|
78
|
+
no longer fails under ACL scoping. The fold embeds a copy of the caller's
|
|
79
|
+
existing query so the caller's pipeline is not mutated.
|
|
80
|
+
|
|
81
|
+
#### Outbound fetches and the shipped CLI are hardened
|
|
82
|
+
|
|
83
|
+
- **FIXED**: `parse-console --url` now parses and scheme-validates its argument
|
|
84
|
+
(HTTP(S) only) before fetching, instead of passing it to `Kernel#open` —
|
|
85
|
+
closing a path where a `|command` argument would be executed as a subprocess.
|
|
86
|
+
- **IMPROVED**: The Cohere reranker `base_url` is validated to reject
|
|
87
|
+
credentials embedded in the URL and plaintext HTTP to non-loopback hosts.
|
|
88
|
+
- **IMPROVED**: Remote file/image fetches enforce a streaming size cap that
|
|
89
|
+
aborts mid-download; the per-call `max_bytes:` ceiling is validated as a
|
|
90
|
+
positive integer, so a zero, negative, or non-numeric value is refused up
|
|
91
|
+
front rather than silently rejecting every response.
|
|
92
|
+
|
|
93
|
+
#### Redaction, locking, and API ergonomics
|
|
94
|
+
|
|
95
|
+
- **IMPROVED**: Query-string credential redaction for logging and request
|
|
96
|
+
profiling is now a single shared implementation, so the two cannot drift. It
|
|
97
|
+
redacts the value of any credential-bearing parameter name (matched by a
|
|
98
|
+
generic rule with a safe-list, and aware of percent-encoded names) and uses
|
|
99
|
+
possessive-quantifier matching so it stays linear on pathological URLs.
|
|
100
|
+
- **FIXED**: The in-process fallback mutex registry (used when no shared lock
|
|
101
|
+
store is configured) is bounded, and its eviction can no longer reclaim a
|
|
102
|
+
mutex a caller is about to lock — a pending-acquirer reservation prevents two
|
|
103
|
+
callers from getting distinct mutexes for the same key.
|
|
104
|
+
- **IMPROVED**: `call_function` and `trigger_job` accept request options as
|
|
105
|
+
bare keyword arguments (for example `call_function("f", {}, session_token:
|
|
106
|
+
t)`), merged with the explicit `opts:` hash for back-compat.
|
|
107
|
+
|
|
108
|
+
#### Packaging, CI, and docs
|
|
109
|
+
|
|
110
|
+
- **CHANGED**: The shipped-gem file list was narrowed to an allowlist of the
|
|
111
|
+
library, binaries, docs, examples, and standard metadata.
|
|
112
|
+
- **CHANGED**: The SHA-pinned `ruby/setup-ruby` GitHub action was bumped to
|
|
113
|
+
`v1.318.0` across the CI, docs, and release workflows.
|
|
114
|
+
- **IMPROVED**: README, test-server, and guide updates, plus YARD styling.
|
|
115
|
+
|
|
3
116
|
### 5.5.4
|
|
4
117
|
|
|
5
118
|
#### Dependency updates
|
|
@@ -1183,10 +1183,21 @@ module Parse
|
|
|
1183
1183
|
# Wire format for each SSE event (note: trailing blank line is required
|
|
1184
1184
|
# by the SSE spec):
|
|
1185
1185
|
#
|
|
1186
|
-
# event:
|
|
1186
|
+
# event: message\n
|
|
1187
1187
|
# data: <json>\n
|
|
1188
1188
|
# \n
|
|
1189
1189
|
#
|
|
1190
|
+
# EVERY frame — progress notifications, list-changed notifications,
|
|
1191
|
+
# and the final JSON-RPC response alike — carries the event name
|
|
1192
|
+
# `message`. MCP Streamable HTTP defines exactly one SSE event type
|
|
1193
|
+
# for JSON-RPC traffic; clients discriminate by inspecting the
|
|
1194
|
+
# envelope (`method` present => notification, `id` + `result`/`error`
|
|
1195
|
+
# => response), NOT by the SSE event name. Earlier releases emitted
|
|
1196
|
+
# `event: progress` and `event: response`, which real MCP clients
|
|
1197
|
+
# silently discard — they match only the default `message` type — so
|
|
1198
|
+
# the final response never arrived and the call appeared to hang.
|
|
1199
|
+
# Do not reintroduce custom event names.
|
|
1200
|
+
#
|
|
1190
1201
|
# @api private
|
|
1191
1202
|
class SSEBody
|
|
1192
1203
|
# Sentinel pushed to the queue when the worker is done.
|
|
@@ -1546,6 +1557,9 @@ module Parse
|
|
|
1546
1557
|
# The `total` field is omitted (rather than nil) so the wire
|
|
1547
1558
|
# shape matches the spec's optional-field convention.
|
|
1548
1559
|
#
|
|
1560
|
+
# Emitted as `event: message` — see the SSEBody class docs. The
|
|
1561
|
+
# payload's `method` is what marks it as progress.
|
|
1562
|
+
#
|
|
1549
1563
|
# @param elapsed [Float] seconds elapsed since the stream started.
|
|
1550
1564
|
# @return [String] SSE event string (includes trailing blank line).
|
|
1551
1565
|
def build_progress_event(elapsed)
|
|
@@ -1557,15 +1571,14 @@ module Parse
|
|
|
1557
1571
|
"progress" => elapsed,
|
|
1558
1572
|
},
|
|
1559
1573
|
})
|
|
1560
|
-
"event:
|
|
1574
|
+
"event: message\ndata: #{data}\n\n"
|
|
1561
1575
|
end
|
|
1562
1576
|
|
|
1563
1577
|
# Format a `notifications/tools/list_changed` or
|
|
1564
1578
|
# `notifications/prompts/list_changed` SSE event. Both
|
|
1565
1579
|
# notifications have no `params` — the wire shape is just the
|
|
1566
|
-
# JSON-RPC envelope with `method` set.
|
|
1567
|
-
#
|
|
1568
|
-
# progress event name is reserved for progress notifications).
|
|
1580
|
+
# JSON-RPC envelope with `method` set. Emitted as `event: message`,
|
|
1581
|
+
# like every other frame on this stream.
|
|
1569
1582
|
#
|
|
1570
1583
|
# @param method [String] full MCP method string.
|
|
1571
1584
|
# @return [String] SSE event string (includes trailing blank line).
|
|
@@ -1599,7 +1612,7 @@ module Parse
|
|
|
1599
1612
|
"method" => "notifications/progress",
|
|
1600
1613
|
"params" => params,
|
|
1601
1614
|
})
|
|
1602
|
-
"event:
|
|
1615
|
+
"event: message\ndata: #{data}\n\n"
|
|
1603
1616
|
end
|
|
1604
1617
|
|
|
1605
1618
|
# Build the callback the dispatcher block passes into
|
|
@@ -1631,12 +1644,17 @@ module Parse
|
|
|
1631
1644
|
end
|
|
1632
1645
|
end
|
|
1633
1646
|
|
|
1634
|
-
# Format the final
|
|
1647
|
+
# Format the final JSON-RPC response SSE event.
|
|
1648
|
+
#
|
|
1649
|
+
# Emitted as `event: message` (NOT `event: response`) — an MCP
|
|
1650
|
+
# client matching only the default `message` type would otherwise
|
|
1651
|
+
# discard the response and block until its own timeout. The
|
|
1652
|
+
# envelope's `id` + `result`/`error` is what marks it final.
|
|
1635
1653
|
#
|
|
1636
1654
|
# @param body [Hash] JSON-RPC response envelope.
|
|
1637
1655
|
# @return [String] SSE event string (includes trailing blank line).
|
|
1638
1656
|
def build_response_event(body)
|
|
1639
|
-
"event:
|
|
1657
|
+
"event: message\ndata: #{JSON.generate(body)}\n\n"
|
|
1640
1658
|
end
|
|
1641
1659
|
|
|
1642
1660
|
# Build an internal-error JSON-RPC envelope (id may be nil at this layer).
|
|
@@ -1755,9 +1773,9 @@ module Parse
|
|
|
1755
1773
|
end
|
|
1756
1774
|
end
|
|
1757
1775
|
|
|
1758
|
-
# SSE wire form for a server→client notification. Event name
|
|
1759
|
-
#
|
|
1760
|
-
# SSE path
|
|
1776
|
+
# SSE wire form for a server→client notification. Event name
|
|
1777
|
+
# "message" — the single event type MCP Streamable HTTP defines for
|
|
1778
|
+
# JSON-RPC traffic, matching the request-scoped SSE path.
|
|
1761
1779
|
def format_event(notification)
|
|
1762
1780
|
"event: message\ndata: #{JSON.generate(notification)}\n\n"
|
|
1763
1781
|
end
|
data/lib/parse/stack/version.rb
CHANGED