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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ef7d7de047cc0a3b4a21f3b080745f36f67cd2a53a81787fe53fdbb68fc3ec41
4
- data.tar.gz: 74af45b9e2f334ca13c99419fe71d1653b9a218dffcf2a02ff801088ab86850b
3
+ metadata.gz: b8f26110cea78b4a3fc393dce2ac3aada7d73442f7d1e970e2aa71d88d3ecba2
4
+ data.tar.gz: 753ead47dcc377ba89e5eca4d2e93a3f7767f5e71a168124f6f180fe7549b5a1
5
5
  SHA512:
6
- metadata.gz: e31f81f269bf874438617b00a01f1fb095fc7853f544d0a38f02aff8f58e21b14e8561650e3d3fb29bad6ff6276722992451a4f78b640481de3e5ab421cd033a
7
- data.tar.gz: 71063ac383cb393af56969a1b631885585f5863b764218d7bee65b79a34cc9b469a885e96cf5bac5239ec66c140602e2bbe8197a46fa90ff4568cb240571e80f
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: progress\n
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: progress\ndata: #{data}\n\n"
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. SSE event name is
1567
- # "message" since this is not a progress notification (the
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: progress\ndata: #{data}\n\n"
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 `response` SSE event.
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: response\ndata: #{JSON.generate(body)}\n\n"
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 "message"
1759
- # (not "progress"/"response", which are reserved for the request-scoped
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
@@ -6,6 +6,6 @@ module Parse
6
6
  # The Parse Server SDK for Ruby
7
7
  module Stack
8
8
  # The current version.
9
- VERSION = "5.5.5"
9
+ VERSION = "5.5.6"
10
10
  end
11
11
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parse-stack-next
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.5.5
4
+ version: 5.5.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adrian Curtin