parse-stack-next 5.6.0 → 5.7.1

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.
Files changed (121) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +489 -0
  3. data/README.md +378 -6
  4. data/docs/caching.md +748 -0
  5. data/examples/basic_client.rb +3 -3
  6. data/examples/basic_server.rb +3 -3
  7. data/examples/live_query_listener.rb +12 -12
  8. data/examples/rag_chatbot.rb +14 -14
  9. data/examples/transaction_example.rb +44 -45
  10. data/examples/webhook_server.rb +3 -3
  11. data/lib/parse/access.rb +493 -0
  12. data/lib/parse/acl_scope.rb +125 -52
  13. data/lib/parse/agent/approval_gate.rb +0 -0
  14. data/lib/parse/agent/cancellation_token.rb +3 -3
  15. data/lib/parse/agent/constraint_translator.rb +4 -4
  16. data/lib/parse/agent/describe.rb +34 -34
  17. data/lib/parse/agent/errors.rb +9 -9
  18. data/lib/parse/agent/mcp_client.rb +61 -59
  19. data/lib/parse/agent/mcp_dispatcher.rb +89 -101
  20. data/lib/parse/agent/mcp_rack_app.rb +92 -93
  21. data/lib/parse/agent/mcp_server.rb +1 -1
  22. data/lib/parse/agent/mcp_subscriptions.rb +22 -22
  23. data/lib/parse/agent/metadata_audit.rb +1 -2
  24. data/lib/parse/agent/metadata_dsl.rb +7 -7
  25. data/lib/parse/agent/metadata_registry.rb +12 -12
  26. data/lib/parse/agent/prompt_hardening.rb +4 -4
  27. data/lib/parse/agent/prompts.rb +10 -10
  28. data/lib/parse/agent/result_formatter.rb +4 -4
  29. data/lib/parse/agent/tools.rb +493 -400
  30. data/lib/parse/agent.rb +157 -116
  31. data/lib/parse/api/hooks.rb +1 -1
  32. data/lib/parse/api/server.rb +2 -2
  33. data/lib/parse/api/users.rb +2 -2
  34. data/lib/parse/atlas_search/index_manager.rb +1 -1
  35. data/lib/parse/atlas_search/session.rb +40 -218
  36. data/lib/parse/atlas_search.rb +181 -60
  37. data/lib/parse/authorization.rb +466 -0
  38. data/lib/parse/cache/invalidation.rb +219 -0
  39. data/lib/parse/cache/keyspace.rb +306 -0
  40. data/lib/parse/cache/moneta_surface.rb +126 -0
  41. data/lib/parse/cache/pool.rb +48 -5
  42. data/lib/parse/cache/redis.rb +425 -10
  43. data/lib/parse/cache/scoped_view.rb +443 -0
  44. data/lib/parse/cache/sub_cache.rb +264 -0
  45. data/lib/parse/cache/upstream_roles.rb +230 -0
  46. data/lib/parse/client/authentication.rb +1 -1
  47. data/lib/parse/client/body_builder.rb +1 -2
  48. data/lib/parse/client/caching.rb +84 -5
  49. data/lib/parse/client.rb +327 -189
  50. data/lib/parse/clp_scope.rb +225 -28
  51. data/lib/parse/console.rb +3 -3
  52. data/lib/parse/embeddings/batch_embedder.rb +3 -3
  53. data/lib/parse/embeddings/cache.rb +17 -17
  54. data/lib/parse/embeddings/cohere.rb +21 -22
  55. data/lib/parse/embeddings/image_fetch.rb +22 -21
  56. data/lib/parse/embeddings/jina.rb +21 -21
  57. data/lib/parse/embeddings/local_http.rb +6 -7
  58. data/lib/parse/embeddings/media_file.rb +5 -4
  59. data/lib/parse/embeddings/openai.rb +5 -5
  60. data/lib/parse/embeddings/provider.rb +1 -1
  61. data/lib/parse/embeddings/qwen.rb +10 -10
  62. data/lib/parse/embeddings/spend_cap.rb +2 -3
  63. data/lib/parse/embeddings/streaming_body.rb +11 -11
  64. data/lib/parse/embeddings/video_source.rb +7 -6
  65. data/lib/parse/embeddings/voyage.rb +59 -61
  66. data/lib/parse/embeddings.rb +28 -27
  67. data/lib/parse/graphql/type_generator.rb +1 -1
  68. data/lib/parse/graphql.rb +5 -5
  69. data/lib/parse/live_query/client.rb +1 -1
  70. data/lib/parse/live_query.rb +1 -1
  71. data/lib/parse/lock.rb +15 -18
  72. data/lib/parse/lock_backend.rb +1 -1
  73. data/lib/parse/lookup_rewriter.rb +6 -6
  74. data/lib/parse/model/associations/belongs_to.rb +4 -0
  75. data/lib/parse/model/associations/collection_proxy.rb +3 -0
  76. data/lib/parse/model/associations/has_many.rb +4 -0
  77. data/lib/parse/model/classes/role.rb +227 -28
  78. data/lib/parse/model/classes/user.rb +60 -1
  79. data/lib/parse/model/clp.rb +4 -4
  80. data/lib/parse/model/core/actions.rb +366 -113
  81. data/lib/parse/model/core/create_lock.rb +0 -2
  82. data/lib/parse/model/core/describe.rb +57 -57
  83. data/lib/parse/model/core/embed_managed.rb +21 -23
  84. data/lib/parse/model/core/fetching.rb +6 -0
  85. data/lib/parse/model/core/indexing.rb +14 -14
  86. data/lib/parse/model/core/parse_reference.rb +1 -1
  87. data/lib/parse/model/core/properties.rb +6 -2
  88. data/lib/parse/model/core/querying.rb +1 -1
  89. data/lib/parse/model/core/schema.rb +2 -2
  90. data/lib/parse/model/core/search_indexing.rb +2 -2
  91. data/lib/parse/model/core/vector_searchable.rb +4 -5
  92. data/lib/parse/model/file.rb +21 -15
  93. data/lib/parse/model/geojson.rb +2 -2
  94. data/lib/parse/model/geopoint.rb +1 -0
  95. data/lib/parse/model/object.rb +136 -66
  96. data/lib/parse/model/pointer.rb +2 -0
  97. data/lib/parse/model/polygon.rb +3 -6
  98. data/lib/parse/model/push.rb +2 -2
  99. data/lib/parse/model/vector.rb +3 -1
  100. data/lib/parse/mongodb.rb +512 -282
  101. data/lib/parse/pipeline_security.rb +3 -0
  102. data/lib/parse/query/constraints.rb +46 -46
  103. data/lib/parse/query.rb +146 -59
  104. data/lib/parse/retrieval/agent_tool.rb +34 -20
  105. data/lib/parse/retrieval/chunk.rb +1 -0
  106. data/lib/parse/retrieval/reranker/cohere.rb +11 -11
  107. data/lib/parse/retrieval/reranker.rb +3 -4
  108. data/lib/parse/retrieval/retriever.rb +4 -6
  109. data/lib/parse/schema/index_migrator.rb +26 -26
  110. data/lib/parse/schema/search_index_migrator.rb +19 -19
  111. data/lib/parse/stack/tasks.rb +6 -6
  112. data/lib/parse/stack/version.rb +1 -1
  113. data/lib/parse/stack.rb +10 -10
  114. data/lib/parse/vector_search/hybrid.rb +66 -41
  115. data/lib/parse/vector_search.rb +14 -11
  116. data/lib/parse/webhooks/payload.rb +1 -0
  117. data/lib/parse/webhooks/registration.rb +4 -4
  118. data/lib/parse/webhooks/trigger_audit.rb +50 -49
  119. data/lib/parse/webhooks.rb +120 -5
  120. data/parse-stack-next.gemspec +6 -6
  121. metadata +10 -1
@@ -51,12 +51,12 @@ module Parse
51
51
  # inside the save handler (Parse Server has no create trigger); the webhook
52
52
  # router runs the destroy chain inside the beforeDelete handler.
53
53
  CALLBACK_TRIGGER_MAP = {
54
- [:save, :before] => :before_save,
55
- [:create, :before] => :before_save,
56
- [:save, :after] => :after_save,
57
- [:create, :after] => :after_save,
54
+ [:save, :before] => :before_save,
55
+ [:create, :before] => :before_save,
56
+ [:save, :after] => :after_save,
57
+ [:create, :after] => :after_save,
58
58
  [:destroy, :before] => :before_delete,
59
- [:destroy, :after] => :after_delete,
59
+ [:destroy, :after] => :after_delete,
60
60
  }.freeze
61
61
 
62
62
  # ActiveModel callback chains + phases with NO server trigger that can run
@@ -67,10 +67,10 @@ module Parse
67
67
  # trigger registration changes that. Surfaced as an informational note, not
68
68
  # a fixable gap.
69
69
  LOCAL_ONLY_MAP = {
70
- [:update, :before] => :before_update,
71
- [:update, :after] => :after_update,
70
+ [:update, :before] => :before_update,
71
+ [:update, :after] => :after_update,
72
72
  [:validation, :before] => :before_validation,
73
- [:validation, :after] => :after_validation,
73
+ [:validation, :after] => :after_validation,
74
74
  }.freeze
75
75
 
76
76
  # The ActiveModel callback chains we introspect.
@@ -104,12 +104,12 @@ module Parse
104
104
 
105
105
  def initialize(parse_class:, callbacks:, local_routes:, server_triggers:,
106
106
  findings:, modeled:)
107
- @parse_class = parse_class
108
- @callbacks = callbacks
109
- @local_routes = local_routes
107
+ @parse_class = parse_class
108
+ @callbacks = callbacks
109
+ @local_routes = local_routes
110
110
  @server_triggers = server_triggers
111
- @findings = findings
112
- @modeled = modeled
111
+ @findings = findings
112
+ @modeled = modeled
113
113
  end
114
114
 
115
115
  # @return [Boolean] true when the class has at least one finding.
@@ -120,12 +120,12 @@ module Parse
120
120
  # @return [Hash] a JSON-safe representation of this row.
121
121
  def to_h
122
122
  {
123
- parse_class: parse_class,
124
- modeled: modeled,
125
- callbacks: callbacks,
126
- local_routes: local_routes,
123
+ parse_class: parse_class,
124
+ modeled: modeled,
125
+ callbacks: callbacks,
126
+ local_routes: local_routes,
127
127
  server_triggers: server_triggers,
128
- findings: findings,
128
+ findings: findings,
129
129
  }
130
130
  end
131
131
  end
@@ -144,11 +144,11 @@ module Parse
144
144
  # callbacks (e.g. the `_User` default-ACL callback). Off by default to keep
145
145
  # the report focused on app-defined logic.
146
146
  def initialize(network: true, client: nil, include_framework: false)
147
- @networked = network
147
+ @networked = network
148
148
  @include_framework = include_framework
149
- @client = client
150
- @server_lookup = network ? fetch_server_triggers : {}
151
- @classes = build_classes
149
+ @client = client
150
+ @server_lookup = network ? fetch_server_triggers : {}
151
+ @classes = build_classes
152
152
  end
153
153
 
154
154
  # @return [Array<Hash>] every finding across all classes, flattened, with the
@@ -164,10 +164,11 @@ module Parse
164
164
  def to_h
165
165
  {
166
166
  networked: networked,
167
- classes: @classes.map(&:to_h),
168
- summary: summary,
167
+ classes: @classes.map(&:to_h),
168
+ summary: summary,
169
169
  }
170
170
  end
171
+
171
172
  alias as_json to_h
172
173
 
173
174
  # @return [Hash] finding counts keyed by kind, plus class totals.
@@ -175,9 +176,9 @@ module Parse
175
176
  counts = Hash.new(0)
176
177
  gaps.each { |g| counts[g[:kind]] += 1 }
177
178
  {
178
- classes_audited: @classes.size,
179
+ classes_audited: @classes.size,
179
180
  classes_with_issues: @classes.count(&:issues?),
180
- findings: counts,
181
+ findings: counts,
181
182
  }
182
183
  end
183
184
 
@@ -212,6 +213,7 @@ module Parse
212
213
  s[:findings].sort.each { |kind, n| lines << " #{kind}: #{n}" }
213
214
  lines.join("\n")
214
215
  end
216
+
215
217
  alias to_s pretty
216
218
 
217
219
  private
@@ -231,7 +233,7 @@ module Parse
231
233
  lookup = Hash.new { |h, k| h[k] = {} }
232
234
  client.triggers.results.each do |t|
233
235
  next unless t["url"].present?
234
- name = t["triggerName"]
236
+ name = t["triggerName"]
235
237
  klass = t[Parse::Model::KEY_CLASS_NAME] || t["className"]
236
238
  next if name.blank? || klass.blank?
237
239
  lookup[klass.to_s][name.to_s.underscore.to_sym] = t["url"]
@@ -262,18 +264,18 @@ module Parse
262
264
  end
263
265
 
264
266
  def audit_class(name)
265
- klass = name == "*" ? nil : (Parse::Model.find_class(name) rescue nil)
267
+ klass = name == "*" ? nil : (Parse::Model.find_class(name) rescue nil)
266
268
  callbacks = klass ? collect_callbacks(klass) : {}
267
- routes = collect_local_routes(name)
268
- server = @server_lookup[name] || {}
269
- findings = analyze(name, callbacks, routes, server)
269
+ routes = collect_local_routes(name)
270
+ server = @server_lookup[name] || {}
271
+ findings = analyze(name, callbacks, routes, server)
270
272
  ClassAudit.new(
271
- parse_class: name,
272
- callbacks: callbacks,
273
- local_routes: routes,
273
+ parse_class: name,
274
+ callbacks: callbacks,
275
+ local_routes: routes,
274
276
  server_triggers: server,
275
- findings: findings,
276
- modeled: !klass.nil?,
277
+ findings: findings,
278
+ modeled: !klass.nil?,
277
279
  )
278
280
  end
279
281
 
@@ -373,7 +375,7 @@ module Parse
373
375
  end
374
376
 
375
377
  required.each do |trigger, cb_keys|
376
- has_route = routes.include?(trigger)
378
+ has_route = routes.include?(trigger)
377
379
  has_server = server.key?(trigger)
378
380
  missing = []
379
381
  missing << :route unless has_route
@@ -381,7 +383,7 @@ module Parse
381
383
  next if missing.empty?
382
384
 
383
385
  findings << {
384
- kind: :callbacks_inert,
386
+ kind: :callbacks_inert,
385
387
  trigger: trigger,
386
388
  missing: missing,
387
389
  callbacks: cb_keys.sort,
@@ -398,7 +400,7 @@ module Parse
398
400
  # Wildcard-only coverage is reported on the "*" row, not here.
399
401
  next unless Parse::Webhooks.routes[trigger]&.key?(name)
400
402
  findings << {
401
- kind: :route_not_registered,
403
+ kind: :route_not_registered,
402
404
  trigger: trigger,
403
405
  message: "Local `webhook :#{trigger}` block for #{name} is not " \
404
406
  "registered as a server trigger — run register_triggers! " \
@@ -410,7 +412,7 @@ module Parse
410
412
  server.each_key do |trigger|
411
413
  next if routes.include?(trigger)
412
414
  findings << {
413
- kind: :orphan_server_trigger,
415
+ kind: :orphan_server_trigger,
414
416
  trigger: trigger,
415
417
  message: "Server trigger #{trigger} is registered for #{name} but no " \
416
418
  "local webhook block handles it — every matching operation " \
@@ -426,7 +428,7 @@ module Parse
426
428
  end
427
429
  if local_only.any?
428
430
  findings << {
429
- kind: :local_only_callbacks,
431
+ kind: :local_only_callbacks,
430
432
  callbacks: local_only.sort,
431
433
  message: "#{name} has local-only callbacks (#{local_only.sort.join(", ")}) " \
432
434
  "that no server trigger can run — they fire for Ruby-initiated " \
@@ -451,25 +453,24 @@ module Parse
451
453
 
452
454
  def inert_message(name, trigger, missing, cb_keys)
453
455
  callbacks = cb_keys.sort.join(", ")
454
- reason =
455
- if missing == [:route, :server]
456
+ reason = if missing == [:route, :server]
456
457
  "neither a local `webhook :#{trigger}` block nor a server trigger is " \
457
- "registered"
458
+ "registered"
458
459
  elsif missing == [:route]
459
460
  "no local `webhook :#{trigger}` block is registered to handle it"
460
461
  else # [:server]
461
462
  "a local block exists but the #{trigger} server trigger is not registered"
462
463
  end
463
464
  "#{name} callbacks (#{callbacks}) will NOT run for non-Ruby clients: " \
464
- "#{reason}. Register `webhook :#{trigger}` and run register_triggers!."
465
+ "#{reason}. Register `webhook :#{trigger}` and run register_triggers!."
465
466
  end
466
467
 
467
468
  def finding_glyph(kind)
468
469
  case kind
469
- when :callbacks_inert then "GAP "
470
- when :route_not_registered then "GAP "
470
+ when :callbacks_inert then "GAP "
471
+ when :route_not_registered then "GAP "
471
472
  when :orphan_server_trigger then "WARN"
472
- when :local_only_callbacks then "note"
473
+ when :local_only_callbacks then "note"
473
474
  else " "
474
475
  end
475
476
  end
@@ -493,7 +494,7 @@ module Parse
493
494
  # `pretty: true`.
494
495
  def trigger_audit(pretty: false, network: true, client: nil, include_framework: false)
495
496
  audit = TriggerAudit.new(
496
- network: network, client: client, include_framework: include_framework
497
+ network: network, client: client, include_framework: include_framework,
497
498
  )
498
499
  pretty ? audit.pretty : audit.to_h
499
500
  end
@@ -132,6 +132,46 @@ module Parse
132
132
 
133
133
  class << self
134
134
 
135
+ # Whether an exception raised by one `after_*` handler prevents the
136
+ # remaining handlers for that same trigger from running.
137
+ #
138
+ # Only the accumulating, non-rejectable `after_*` triggers can have more
139
+ # than one handler (see {Parse::Webhooks::Registration#route}), so this
140
+ # governs `after_save`, `after_delete`, and `after_logout` and nothing
141
+ # else. `before_*` dispatch is untouched: a raise there is how a handler
142
+ # denies an operation, and it must continue to abort.
143
+ #
144
+ # Defaults to `true`, which is the historical behavior. Handlers are
145
+ # folded with `Array#map`, and `map` abandons the collection on the first
146
+ # raise, so a handler that raises silently prevents every handler
147
+ # registered after it from running. That ordering is not something an
148
+ # application fully controls: the SDK's own cache-invalidation triggers
149
+ # install during `Parse.setup` and therefore sit ahead of handlers
150
+ # registered by application files loaded later.
151
+ #
152
+ # Set to `false` to isolate handlers from each other, so that each one
153
+ # runs regardless of what an earlier one raised. The error is reported
154
+ # (a warning plus a `parse.webhooks.handler_error` notification) and
155
+ # dispatch continues.
156
+ #
157
+ # Either way, nothing is reverted. An `after_*` trigger fires once the
158
+ # write has already committed, so there is no version of this setting
159
+ # that can undo the save; the only question it answers is whether the
160
+ # remaining handlers still get to run.
161
+ #
162
+ # @example Keep one failing handler from starving the others
163
+ # Parse::Webhooks.abort_after_callbacks_on_error = false
164
+ #
165
+ # @return [Boolean]
166
+ attr_writer :abort_after_callbacks_on_error
167
+
168
+ # (see #abort_after_callbacks_on_error=)
169
+ # @return [Boolean]
170
+ def abort_after_callbacks_on_error
171
+ return @abort_after_callbacks_on_error unless @abort_after_callbacks_on_error.nil?
172
+ true
173
+ end
174
+
135
175
  # Allows support for web frameworks that support auto-reloading of source.
136
176
  # @!visibility private
137
177
  def reload!(args = {})
@@ -182,8 +222,26 @@ module Parse
182
222
  raise ArgumentError, "Invalid Webhook registration trigger #{type} #{className}"
183
223
  end
184
224
 
185
- # AfterSave/AfterDelete hooks support more than one
186
- if type == :after_save || type == :after_delete
225
+ # Triggers whose handlers compose instead of replacing one another.
226
+ #
227
+ # `after_save` / `after_delete` have always accumulated. The remaining
228
+ # `after_*` triggers are added because the SDK itself now registers
229
+ # them for cache invalidation: without this, registering an internal
230
+ # `after_logout` handler would silently replace an application's own,
231
+ # with the winner decided by file load order and no warning.
232
+ #
233
+ # This is safe only for non-rejectable triggers. Parse Server ignores
234
+ # their response body, and {#call_route} normalizes their result to
235
+ # `true` regardless, so `.last` semantics are irrelevant.
236
+ # {REJECTABLE_NON_OBJECT_TRIGGERS} are deliberately excluded: a
237
+ # composite of those must deny if ANY handler denies, and folding with
238
+ # `.last` would discard an earlier rejection.
239
+ composable = type == :after_save || type == :after_delete ||
240
+ (NON_OBJECT_TRIGGERS.include?(type) &&
241
+ !REJECTABLE_NON_OBJECT_TRIGGERS.include?(type) &&
242
+ type.to_s.start_with?("after_"))
243
+
244
+ if composable
187
245
  routes[type][className] ||= []
188
246
  routes[type][className].push block
189
247
  else
@@ -227,6 +285,60 @@ module Parse
227
285
  # block that declares a parameter (`do |payload| ... end`) or a splat
228
286
  # receives the payload.
229
287
  #
288
+ # Run every handler registered for one accumulating `after_*` trigger.
289
+ #
290
+ # `.last` is preserved as the composed result because Parse Server
291
+ # ignores the response body for these triggers and {#call_route}
292
+ # normalizes it anyway, so which handler's value survives is not
293
+ # observable.
294
+ #
295
+ # When {abort_after_callbacks_on_error} is false, a handler that raises
296
+ # is reported and skipped rather than taking the rest of the trigger down
297
+ # with it. Nothing is reverted in either mode: the write these triggers
298
+ # fire on has already committed.
299
+ #
300
+ # @param payload [Parse::Webhooks::Payload] the request payload.
301
+ # @param registry [Array<Proc>] the handlers, in registration order.
302
+ # @param type [Symbol] the trigger being dispatched.
303
+ # @return [Object] the last handler result.
304
+ def dispatch_composed(payload, registry, type)
305
+ return registry.map { |hook| invoke_handler(payload, hook) }.last if
306
+ abort_after_callbacks_on_error
307
+
308
+ last = nil
309
+ registry.each do |hook|
310
+ begin
311
+ last = invoke_handler(payload, hook)
312
+ rescue StandardError => e
313
+ report_handler_error(type, e)
314
+ end
315
+ end
316
+ last
317
+ end
318
+
319
+ # Report a handler failure that was isolated rather than propagated.
320
+ #
321
+ # The message is included because an application's own handler raised it
322
+ # and the application needs it to debug; this is not the SDK's internal
323
+ # `guard`, which deliberately omits messages that can carry a cache key.
324
+ #
325
+ # @param type [Symbol] the trigger being dispatched.
326
+ # @param error [StandardError] the raised error.
327
+ # @return [void]
328
+ def report_handler_error(type, error)
329
+ warn "[Parse::Webhooks] #{type} handler raised #{error.class}: #{error.message}; " \
330
+ "continuing with the remaining handlers " \
331
+ "(Parse::Webhooks.abort_after_callbacks_on_error is false)"
332
+ return unless defined?(ActiveSupport::Notifications)
333
+ begin
334
+ ActiveSupport::Notifications.instrument(
335
+ "parse.webhooks.handler_error", trigger: type, error: error.class.name,
336
+ )
337
+ rescue StandardError
338
+ nil
339
+ end
340
+ end
341
+
230
342
  # @param payload [Parse::Webhooks::Payload] the request payload (becomes `self`).
231
343
  # @param block [Proc] the registered handler block.
232
344
  # @return [Object] the handler's result value.
@@ -353,14 +465,17 @@ module Parse
353
465
  if pre_obj.respond_to?(:apply_field_guards!)
354
466
  pre_obj.apply_field_guards!(
355
467
  master: payload.master? || false,
356
- is_new: payload.original.blank?
468
+ is_new: payload.original.blank?,
357
469
  )
358
470
  end
359
471
  end
360
472
  end
361
473
 
362
474
  if registry.is_a?(Array)
363
- result = registry.map { |hook| invoke_handler(payload, hook) }.last
475
+ # An Array registry only ever exists for the accumulating,
476
+ # non-rejectable `after_*` triggers, so isolating handlers here
477
+ # cannot affect `before_*` rejection semantics.
478
+ result = dispatch_composed(payload, registry, type)
364
479
  else
365
480
  result = invoke_handler(payload, registry)
366
481
  end
@@ -777,7 +892,7 @@ module Parse
777
892
  else
778
893
  if self.logging.present?
779
894
  puts "[Webhooks] --> Could not find mapping route for " \
780
- "#{Parse::Middleware::BodyBuilder.redact(payload.to_json)}"
895
+ "#{Parse::Middleware::BodyBuilder.redact(payload.to_json)}"
781
896
  end
782
897
  end
783
898
 
@@ -6,7 +6,7 @@ require "parse/stack/version"
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "parse-stack-next"
8
8
  spec.version = Parse::Stack::VERSION
9
- spec.authors = ["Adrian Curtin", "Anthony Persaud", "Henry Spindell"]
9
+ spec.authors = ["Adrian Curtin", "Anthony Persaud", "Henry Spindell"]
10
10
  spec.email = ["adrian+parse-stack@neurosynq.net"]
11
11
 
12
12
  spec.summary = %q{Parse Server SDK for Ruby — ORM, queries, auth, and MongoDB-direct access}
@@ -15,11 +15,11 @@ Gem::Specification.new do |spec|
15
15
  spec.license = "MIT"
16
16
 
17
17
  spec.metadata = {
18
- "homepage_uri" => "https://github.com/neurosynq/parse-stack-next",
19
- "source_code_uri" => "https://github.com/neurosynq/parse-stack-next",
20
- "changelog_uri" => "https://github.com/neurosynq/parse-stack-next/blob/main/CHANGELOG.md",
21
- "bug_tracker_uri" => "https://github.com/neurosynq/parse-stack-next/issues",
22
- "documentation_uri" => "https://neurosynq.github.io/parse-stack-next/",
18
+ "homepage_uri" => "https://github.com/neurosynq/parse-stack-next",
19
+ "source_code_uri" => "https://github.com/neurosynq/parse-stack-next",
20
+ "changelog_uri" => "https://github.com/neurosynq/parse-stack-next/blob/main/CHANGELOG.md",
21
+ "bug_tracker_uri" => "https://github.com/neurosynq/parse-stack-next/issues",
22
+ "documentation_uri" => "https://neurosynq.github.io/parse-stack-next/",
23
23
  "rubygems_mfa_required" => "true",
24
24
  }
25
25
 
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.6.0
4
+ version: 5.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adrian Curtin
@@ -225,6 +225,7 @@ files:
225
225
  - docs/_config.yml
226
226
  - docs/acl_clp_guide.md
227
227
  - docs/atlas_vector_search_guide.md
228
+ - docs/caching.md
228
229
  - docs/client_sdk_guide.md
229
230
  - docs/mcp_guide.md
230
231
  - docs/mongodb_direct_guide.md
@@ -242,6 +243,7 @@ files:
242
243
  - examples/webhook_server.rb
243
244
  - lib/parse-stack-next.rb
244
245
  - lib/parse-stack.rb
246
+ - lib/parse/access.rb
245
247
  - lib/parse/acl_scope.rb
246
248
  - lib/parse/agent.rb
247
249
  - lib/parse/agent/approval_gate.rb
@@ -284,8 +286,15 @@ files:
284
286
  - lib/parse/atlas_search/result.rb
285
287
  - lib/parse/atlas_search/search_builder.rb
286
288
  - lib/parse/atlas_search/session.rb
289
+ - lib/parse/authorization.rb
290
+ - lib/parse/cache/invalidation.rb
291
+ - lib/parse/cache/keyspace.rb
292
+ - lib/parse/cache/moneta_surface.rb
287
293
  - lib/parse/cache/pool.rb
288
294
  - lib/parse/cache/redis.rb
295
+ - lib/parse/cache/scoped_view.rb
296
+ - lib/parse/cache/sub_cache.rb
297
+ - lib/parse/cache/upstream_roles.rb
289
298
  - lib/parse/client.rb
290
299
  - lib/parse/client/authentication.rb
291
300
  - lib/parse/client/batch.rb