parse-stack-next 5.5.3 → 5.5.5
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 +13 -4
- data/README.md +26 -13
- data/bin/parse-console +9 -1
- data/docs/TEST_SERVER.md +115 -238
- data/docs/mcp_guide.md +1 -1
- data/docs/mongodb_index_optimization_guide.md +3 -2
- data/docs/usage_guide.md +1 -1
- data/docs/yard-template/default/fulldoc/html/css/common.css +52 -9
- data/docs/yard-template/default/fulldoc/html/css/full_list.css +40 -13
- data/lib/parse/agent/constraint_translator.rb +18 -18
- data/lib/parse/agent/errors.rb +29 -7
- data/lib/parse/agent/metadata_dsl.rb +6 -6
- data/lib/parse/agent/tools.rb +250 -59
- data/lib/parse/agent.rb +42 -30
- data/lib/parse/api/aggregate.rb +3 -3
- data/lib/parse/api/cloud_functions.rb +19 -10
- data/lib/parse/api/objects.rb +8 -8
- data/lib/parse/api/users.rb +9 -9
- data/lib/parse/atlas_search/session.rb +34 -34
- data/lib/parse/atlas_search.rb +243 -110
- data/lib/parse/client/body_builder.rb +10 -10
- data/lib/parse/client/logging.rb +5 -2
- data/lib/parse/client/profiling.rb +5 -2
- data/lib/parse/client/protocol.rb +1 -1
- data/lib/parse/client/url_redaction.rb +94 -0
- data/lib/parse/client.rb +43 -28
- data/lib/parse/embeddings/image_fetch.rb +6 -1
- data/lib/parse/embeddings/voyage.rb +16 -17
- data/lib/parse/live_query/client.rb +7 -7
- data/lib/parse/live_query/subscription.rb +1 -1
- data/lib/parse/lock.rb +1 -1
- data/lib/parse/lock_backend.rb +118 -2
- data/lib/parse/model/acl.rb +24 -24
- data/lib/parse/model/classes/job_schedule.rb +8 -8
- data/lib/parse/model/classes/job_status.rb +9 -9
- data/lib/parse/model/classes/role.rb +49 -49
- data/lib/parse/model/classes/session.rb +2 -2
- data/lib/parse/model/classes/user.rb +66 -66
- data/lib/parse/model/core/builder.rb +7 -7
- data/lib/parse/model/core/create_lock.rb +1 -1
- data/lib/parse/model/core/properties.rb +4 -4
- data/lib/parse/model/file.rb +57 -16
- data/lib/parse/model/model.rb +19 -19
- data/lib/parse/model/object.rb +38 -38
- data/lib/parse/model/pointer.rb +4 -4
- data/lib/parse/model/push.rb +5 -5
- data/lib/parse/mongodb.rb +84 -26
- data/lib/parse/pipeline_security.rb +2 -2
- data/lib/parse/query/constraints.rb +38 -38
- data/lib/parse/query.rb +151 -75
- data/lib/parse/retrieval/reranker/cohere.rb +30 -0
- data/lib/parse/schema.rb +1 -1
- data/lib/parse/stack/version.rb +1 -1
- data/lib/parse/stack.rb +23 -10
- data/lib/parse/two_factor_auth/user_extension.rb +25 -25
- data/lib/parse/webhooks/payload.rb +35 -35
- data/lib/parse/webhooks/registration.rb +2 -2
- data/lib/parse/webhooks/replay_protection.rb +16 -16
- data/lib/parse/webhooks.rb +11 -11
- data/parse-stack-next.gemspec +19 -1
- metadata +2 -38
- data/.bundle/config +0 -5
- data/.env.sample +0 -138
- data/.env.test +0 -10
- data/.github/ISSUE_TEMPLATE/bug_report.yml +0 -105
- data/.github/ISSUE_TEMPLATE/feature_request.yml +0 -67
- data/.github/dependabot.yml +0 -13
- data/.github/workflows/codeql.yml +0 -44
- data/.github/workflows/docs.yml +0 -39
- data/.github/workflows/release.yml +0 -43
- data/.github/workflows/ruby.yml +0 -38
- data/.gitignore +0 -56
- data/.ruby-version +0 -1
- data/.solargraph.yml +0 -22
- data/.vscode/settings.json +0 -3
- data/.yardopts +0 -19
- data/Gemfile +0 -43
- data/Gemfile.lock +0 -198
- data/Makefile +0 -63
- data/Rakefile +0 -825
- data/config/parse-config.json +0 -12
- data/scripts/debug-ips.js +0 -35
- data/scripts/docker/Dockerfile.parse +0 -17
- data/scripts/docker/atlas-init.js +0 -284
- data/scripts/docker/docker-compose.atlas.yml +0 -80
- data/scripts/docker/docker-compose.test.yml +0 -159
- data/scripts/docker/docker-compose.verifyemail.yml +0 -4
- data/scripts/docker/mongo-init.js +0 -21
- data/scripts/docker/preflight.sh +0 -76
- data/scripts/eval_mcp_with_lm_studio.rb +0 -274
- data/scripts/start-parse.sh +0 -154
- data/scripts/start_mcp_server.rb +0 -78
- data/scripts/test_server_connection.rb +0 -82
- data/scripts/vector_prototype/create_vector_index.js +0 -105
- data/scripts/vector_prototype/fetch_embeddings.py +0 -241
- data/scripts/vector_prototype/fixture_manifest.json +0 -9
- data/scripts/vector_prototype/query_prototype.rb +0 -84
- data/scripts/vector_prototype/run.sh +0 -34
|
@@ -67,28 +67,28 @@ module Parse
|
|
|
67
67
|
attr_accessor :query, :log, :objects
|
|
68
68
|
attr_accessor :original, :update, :raw
|
|
69
69
|
# @!attribute [rw] event
|
|
70
|
-
# The LiveQuery event type for an
|
|
71
|
-
#
|
|
72
|
-
#
|
|
70
|
+
# The LiveQuery event type for an `afterEvent` trigger -- one of
|
|
71
|
+
# `"create"`, `"enter"`, `"update"`, `"leave"`, or `"delete"` -- or
|
|
72
|
+
# `"connect"` for a `beforeConnect` trigger. `nil` for every non-
|
|
73
73
|
# LiveQuery trigger. See {#after_event?} / {#before_connect?}.
|
|
74
74
|
# @return [String, nil]
|
|
75
75
|
# @!attribute [rw] clients
|
|
76
|
-
# Connection-global metadata sent on the LiveQuery
|
|
77
|
-
#
|
|
78
|
-
# clients.
|
|
76
|
+
# Connection-global metadata sent on the LiveQuery `beforeConnect` /
|
|
77
|
+
# `afterEvent` triggers: the number of currently-connected LiveQuery
|
|
78
|
+
# clients. `nil` for non-LiveQuery triggers.
|
|
79
79
|
# @return [Integer, nil]
|
|
80
80
|
# @!attribute [rw] subscriptions
|
|
81
|
-
# Connection-global metadata sent on the LiveQuery
|
|
82
|
-
#
|
|
81
|
+
# Connection-global metadata sent on the LiveQuery `beforeConnect` /
|
|
82
|
+
# `afterEvent` triggers: the number of active subscriptions. `nil` for
|
|
83
83
|
# non-LiveQuery triggers.
|
|
84
84
|
# @return [Integer, nil]
|
|
85
85
|
attr_accessor :event, :clients, :subscriptions
|
|
86
86
|
# @!attribute [rw] context
|
|
87
87
|
# The caller-supplied context object threaded from the originating REST
|
|
88
|
-
# write or cloud-function call via the
|
|
89
|
-
# Parse Server includes this as a top-level
|
|
88
|
+
# write or cloud-function call via the `X-Parse-Cloud-Context` header.
|
|
89
|
+
# Parse Server includes this as a top-level `context` key in trigger
|
|
90
90
|
# payloads (beforeSave/afterSave/etc.). Returns a Hash when present, or
|
|
91
|
-
#
|
|
91
|
+
# `nil` when the originating request carried no context.
|
|
92
92
|
# @return [Hash, nil]
|
|
93
93
|
attr_accessor :context
|
|
94
94
|
# @!attribute [r] session_token
|
|
@@ -96,7 +96,7 @@ module Parse
|
|
|
96
96
|
# webhook payload (`user.sessionToken`) before credentials are scrubbed
|
|
97
97
|
# from {#user} / {#object} / {#original} / {#update}. Present only when
|
|
98
98
|
# the originating request was made by a logged-in user -- a master-key
|
|
99
|
-
# request carries no user and no token, so this is
|
|
99
|
+
# request carries no user and no token, so this is `nil`. It is
|
|
100
100
|
# intentionally NOT one of {ATTRIBUTES}, so it never appears in
|
|
101
101
|
# {#as_json} or in the redacted request log. Reach for it (or the
|
|
102
102
|
# higher-level {#user_client} / {#user_agent}) only when a handler
|
|
@@ -232,7 +232,7 @@ module Parse
|
|
|
232
232
|
].freeze
|
|
233
233
|
|
|
234
234
|
# @!visibility private
|
|
235
|
-
# Returns a copy of
|
|
235
|
+
# Returns a copy of `obj` with only `WEBHOOK_TRIGGER_CREDENTIAL_KEYS`
|
|
236
236
|
# removed. Operates on string and symbol keys (Parse Server uses camelCase
|
|
237
237
|
# strings on the wire; downstream code may have already symbolized).
|
|
238
238
|
# Pass-through for non-Hash input.
|
|
@@ -274,7 +274,7 @@ module Parse
|
|
|
274
274
|
end
|
|
275
275
|
|
|
276
276
|
# @!visibility private
|
|
277
|
-
# Returns a copy of
|
|
277
|
+
# Returns a copy of `obj` with the model's declared `:vector`
|
|
278
278
|
# columns removed. Embeddings are large dense float arrays that leak
|
|
279
279
|
# ML signal; a webhook handler has no reason to receive them, and
|
|
280
280
|
# leaving them in bloats logs and any object a handler re-persists.
|
|
@@ -302,10 +302,10 @@ module Parse
|
|
|
302
302
|
end
|
|
303
303
|
|
|
304
304
|
# @!visibility private
|
|
305
|
-
# Pulls the caller's session token out of the (unscrubbed)
|
|
306
|
-
# Parse Server sends it as the camelCase string key
|
|
305
|
+
# Pulls the caller's session token out of the (unscrubbed) `user` hash.
|
|
306
|
+
# Parse Server sends it as the camelCase string key `sessionToken`; this
|
|
307
307
|
# tolerates a symbol key and the snake_case form too, mirroring the
|
|
308
|
-
# leniency in
|
|
308
|
+
# leniency in `scrub_credentials`. Returns `nil` for a blank token or a
|
|
309
309
|
# non-Hash / absent user (a master-key request has no user).
|
|
310
310
|
def self.extract_session_token(user_hash)
|
|
311
311
|
return nil unless user_hash.is_a?(Hash)
|
|
@@ -365,14 +365,14 @@ module Parse
|
|
|
365
365
|
|
|
366
366
|
# An opt-in, user-scoped {Parse::Client} for acting on the server as the
|
|
367
367
|
# webhook's calling user. It mirrors the default client's connection
|
|
368
|
-
# settings (
|
|
368
|
+
# settings (`server_url`, `application_id`, `api_key`) but carries NO
|
|
369
369
|
# master key and BINDS the caller's {#session_token}, so every request it
|
|
370
370
|
# makes -- with no further ceremony -- is authorized by Parse Server as
|
|
371
|
-
# that user: ACL, CLP and
|
|
371
|
+
# that user: ACL, CLP and `protectedFields` are all enforced. (A
|
|
372
372
|
# `Parse.with_session` block still overrides the bound token if you need
|
|
373
373
|
# to act as someone else within a call.) Memoized per payload, since each
|
|
374
374
|
# webhook delivery carries a distinct token.
|
|
375
|
-
# @return [Parse::Client, nil]
|
|
375
|
+
# @return [Parse::Client, nil] `nil` when the payload carried no token.
|
|
376
376
|
def user_client
|
|
377
377
|
return nil if @session_token.nil?
|
|
378
378
|
@user_client ||= Parse::Client.client.become(@session_token)
|
|
@@ -380,15 +380,15 @@ module Parse
|
|
|
380
380
|
|
|
381
381
|
# An opt-in, non-master {Parse::Agent} scoped to the webhook caller's
|
|
382
382
|
# session token. Because its client has no master key and it is built
|
|
383
|
-
# with a non-empty
|
|
383
|
+
# with a non-empty `session_token:`, the agent runs in CLIENT MODE:
|
|
384
384
|
# every tool/query routes through a path Parse Server (or the SDK's own
|
|
385
385
|
# ACL/CLP enforcement layer) authorizes as the calling user, with no
|
|
386
386
|
# master-key fallback to silently bypass row-level security. This is the
|
|
387
387
|
# handle to use when a handler should read or act strictly within the
|
|
388
388
|
# caller's permissions. Additional agent options (e.g.
|
|
389
|
-
#
|
|
389
|
+
# `permissions: :readwrite`) may be passed through.
|
|
390
390
|
# @param opts [Hash] extra keyword args forwarded to {Parse::Agent#initialize}.
|
|
391
|
-
# @return [Parse::Agent, nil]
|
|
391
|
+
# @return [Parse::Agent, nil] `nil` when the payload carried no token.
|
|
392
392
|
def user_agent(**opts)
|
|
393
393
|
return nil if @session_token.nil?
|
|
394
394
|
require_relative "../agent" unless defined?(Parse::Agent)
|
|
@@ -462,11 +462,11 @@ module Parse
|
|
|
462
462
|
|
|
463
463
|
# true if this is a beforeLogin webhook trigger request.
|
|
464
464
|
#
|
|
465
|
-
# NOTE: a
|
|
466
|
-
# {#object} / {#parse_object} (a
|
|
467
|
-
# not yet authenticated when the trigger fires, so {#user} is
|
|
468
|
-
#
|
|
469
|
-
# inspect the logging-in user during
|
|
465
|
+
# NOTE: a `beforeLogin` payload carries the user being authenticated as
|
|
466
|
+
# {#object} / {#parse_object} (a `_User`), NOT as {#user} -- the caller is
|
|
467
|
+
# not yet authenticated when the trigger fires, so {#user} is `nil`. (By
|
|
468
|
+
# `afterLogin` both are populated and equal.) Reach for {#parse_object} to
|
|
469
|
+
# inspect the logging-in user during `beforeLogin`.
|
|
470
470
|
def before_login?
|
|
471
471
|
trigger? && @trigger_name.to_sym == :beforeLogin
|
|
472
472
|
end
|
|
@@ -477,19 +477,19 @@ module Parse
|
|
|
477
477
|
end
|
|
478
478
|
|
|
479
479
|
# true if this is a afterLogout webhook trigger request. The logged-out
|
|
480
|
-
# session is carried as {#object} / {#parse_object} (a
|
|
480
|
+
# session is carried as {#object} / {#parse_object} (a `_Session`).
|
|
481
481
|
def after_logout?
|
|
482
482
|
trigger? && @trigger_name.to_sym == :afterLogout
|
|
483
483
|
end
|
|
484
484
|
|
|
485
485
|
# true if this is a beforePasswordResetRequest webhook trigger request.
|
|
486
|
-
# The target user is carried as {#object} / {#parse_object} (a
|
|
486
|
+
# The target user is carried as {#object} / {#parse_object} (a `_User`).
|
|
487
487
|
def before_password_reset_request?
|
|
488
488
|
trigger? && @trigger_name.to_sym == :beforePasswordResetRequest
|
|
489
489
|
end
|
|
490
490
|
|
|
491
491
|
# true if this is a LiveQuery beforeConnect webhook trigger request.
|
|
492
|
-
# Connection-global: carries no {#object}; the className is the
|
|
492
|
+
# Connection-global: carries no {#object}; the className is the `@Connect`
|
|
493
493
|
# sentinel and the caller's token (if any) is in {#session_token}.
|
|
494
494
|
def before_connect?
|
|
495
495
|
trigger? && @trigger_name.to_sym == :beforeConnect
|
|
@@ -510,10 +510,10 @@ module Parse
|
|
|
510
510
|
|
|
511
511
|
# true if this is one of the authentication-side triggers
|
|
512
512
|
# (beforeLogin / afterLogin / afterLogout / beforePasswordResetRequest).
|
|
513
|
-
# These carry a
|
|
513
|
+
# These carry a `_User` / `_Session` as {#object} but are NOT object
|
|
514
514
|
# save/delete triggers: no ActiveModel save/create/destroy callbacks run
|
|
515
515
|
# for them, and Parse Server ignores the response body (the only way to
|
|
516
|
-
# affect a
|
|
516
|
+
# affect a `before*` one is to deny it -- see the webhook router).
|
|
517
517
|
def auth_trigger?
|
|
518
518
|
before_login? || after_login? || after_logout? || before_password_reset_request?
|
|
519
519
|
end
|
|
@@ -521,7 +521,7 @@ module Parse
|
|
|
521
521
|
# true if this is one of the LiveQuery triggers (beforeConnect /
|
|
522
522
|
# beforeSubscribe / afterEvent). Parse Server delivers these over an HTTP
|
|
523
523
|
# webhook only in a co-located single-process LiveQuery setup;
|
|
524
|
-
#
|
|
524
|
+
# `beforeConnect` in particular carries a live client and is effectively
|
|
525
525
|
# in-process-only. See the webhooks guide.
|
|
526
526
|
def live_query_trigger?
|
|
527
527
|
before_connect? || before_subscribe? || after_event?
|
|
@@ -560,7 +560,7 @@ module Parse
|
|
|
560
560
|
end
|
|
561
561
|
|
|
562
562
|
# @!visibility private
|
|
563
|
-
# Returns
|
|
563
|
+
# Returns `true` when `@object`/`@original` contain a className that
|
|
564
564
|
# disagrees with the trigger's expected class. Used to skip building
|
|
565
565
|
# a typed object when the payload was clearly forged or routed
|
|
566
566
|
# incorrectly.
|
|
@@ -24,8 +24,8 @@ module Parse
|
|
|
24
24
|
# Parse Server. Rejects non-http(s) schemes, embedded userinfo, and
|
|
25
25
|
# hostnames that resolve to loopback, link-local, RFC1918, CGNAT,
|
|
26
26
|
# multicast, or cloud-metadata addresses (covered by
|
|
27
|
-
#
|
|
28
|
-
# can reach
|
|
27
|
+
# `Parse::File::BLOCKED_CIDRS`). Without these checks an attacker who
|
|
28
|
+
# can reach `register_webhook!` could redirect Parse Server's trigger
|
|
29
29
|
# POSTs to an internal host (e.g. the cloud metadata service) and
|
|
30
30
|
# exfiltrate request bodies. Returns the input URL unchanged on
|
|
31
31
|
# success.
|
|
@@ -11,8 +11,8 @@ module Parse
|
|
|
11
11
|
# NEW-EXT-4: webhook freshness and replay protection.
|
|
12
12
|
#
|
|
13
13
|
# Parse Server's default webhook delivery is authenticated only by the
|
|
14
|
-
# static
|
|
15
|
-
# indefinitely replayable -- a Ruby-initiated save bearing an
|
|
14
|
+
# static `X-Parse-Webhook-Key` header. A captured POST is therefore
|
|
15
|
+
# indefinitely replayable -- a Ruby-initiated save bearing an `_RB_`
|
|
16
16
|
# request id will continue to suppress server-side after_* callbacks
|
|
17
17
|
# every time it is replayed, and a generic trigger payload can be
|
|
18
18
|
# delivered repeatedly to fire double-charges or other side effects.
|
|
@@ -20,23 +20,23 @@ module Parse
|
|
|
20
20
|
# This module adds two layers on top of the existing static-key check:
|
|
21
21
|
#
|
|
22
22
|
# 1. **Always-on body+request-id dedup.** A bounded LRU records a
|
|
23
|
-
# SHA-256 of
|
|
24
|
-
# duplicate seen within
|
|
25
|
-
#
|
|
23
|
+
# SHA-256 of `(request_id || "")` joined with the request body. A
|
|
24
|
+
# duplicate seen within `replay_window_seconds` is rejected with
|
|
25
|
+
# `"Webhook replay detected."`. Cooperation with Parse Server is not
|
|
26
26
|
# required; this protects against in-window replays only, but those
|
|
27
27
|
# are the cheapest attack to mount (proxy retries, captured fast
|
|
28
28
|
# loops, retransmits).
|
|
29
29
|
#
|
|
30
|
-
# 2. **Opt-in HMAC freshness verification.** When a
|
|
30
|
+
# 2. **Opt-in HMAC freshness verification.** When a `signing_secret` is
|
|
31
31
|
# configured (programmatically or via
|
|
32
|
-
#
|
|
32
|
+
# `PARSE_WEBHOOK_SIGNING_SECRET`) the dispatcher requires two extra
|
|
33
33
|
# headers on every request:
|
|
34
34
|
#
|
|
35
|
-
# *
|
|
36
|
-
# *
|
|
37
|
-
# bytes
|
|
35
|
+
# * `X-Parse-Webhook-Timestamp` -- decimal Unix epoch seconds.
|
|
36
|
+
# * `X-Parse-Webhook-Signature` -- hex-encoded HMAC-SHA256 of the
|
|
37
|
+
# bytes `"#{timestamp}.#{body}"` keyed with the signing secret.
|
|
38
38
|
#
|
|
39
|
-
# Requests outside
|
|
39
|
+
# Requests outside `signing_max_skew_seconds` (default 300) or with
|
|
40
40
|
# an invalid signature are rejected. Once enabled, this gives full
|
|
41
41
|
# binding between the body and the time of delivery and closes the
|
|
42
42
|
# replay window beyond the freshness skew.
|
|
@@ -61,9 +61,9 @@ module Parse
|
|
|
61
61
|
attr_writer :signing_secret, :signing_max_skew_seconds,
|
|
62
62
|
:replay_window_seconds, :replay_cache_size
|
|
63
63
|
|
|
64
|
-
# Shared HMAC secret used to verify
|
|
64
|
+
# Shared HMAC secret used to verify `X-Parse-Webhook-Signature`.
|
|
65
65
|
# When nil/empty, signature verification is skipped (layer 1 still
|
|
66
|
-
# applies). Defaults to
|
|
66
|
+
# applies). Defaults to `ENV["PARSE_WEBHOOK_SIGNING_SECRET"]`.
|
|
67
67
|
def signing_secret
|
|
68
68
|
return @signing_secret if defined?(@signing_secret) && !@signing_secret.nil?
|
|
69
69
|
ENV["PARSE_WEBHOOK_SIGNING_SECRET"]
|
|
@@ -71,12 +71,12 @@ module Parse
|
|
|
71
71
|
|
|
72
72
|
# Maximum allowed clock skew (in seconds) between the timestamp
|
|
73
73
|
# header and the receiver. Requests outside this window are
|
|
74
|
-
# rejected as stale when
|
|
74
|
+
# rejected as stale when `signing_secret` is set.
|
|
75
75
|
def signing_max_skew_seconds
|
|
76
76
|
@signing_max_skew_seconds || DEFAULT_MAX_SKEW
|
|
77
77
|
end
|
|
78
78
|
|
|
79
|
-
# How long a
|
|
79
|
+
# How long a `(request_id, body)` digest stays in the dedup cache.
|
|
80
80
|
# Duplicates seen within this window are rejected.
|
|
81
81
|
def replay_window_seconds
|
|
82
82
|
@replay_window_seconds || DEFAULT_REPLAY_WINDOW
|
|
@@ -112,7 +112,7 @@ module Parse
|
|
|
112
112
|
# @!visibility private
|
|
113
113
|
# Returns nil when the request passes both replay and signature
|
|
114
114
|
# checks; otherwise returns a short error string suitable for the
|
|
115
|
-
# webhook error response. The headers come from
|
|
115
|
+
# webhook error response. The headers come from `env` so this
|
|
116
116
|
# works with any Rack request.
|
|
117
117
|
def verify!(env, body_str, request_id)
|
|
118
118
|
secret = signing_secret
|
data/lib/parse/webhooks.rb
CHANGED
|
@@ -85,7 +85,7 @@ module Parse
|
|
|
85
85
|
class ResponseError < StandardError; end
|
|
86
86
|
|
|
87
87
|
# The authentication-side triggers (local underscore form). These carry a
|
|
88
|
-
#
|
|
88
|
+
# `_User` / `_Session` as the payload object but are NOT object save/delete
|
|
89
89
|
# triggers: the router runs no ActiveModel save/create/destroy callbacks for
|
|
90
90
|
# them, and Parse Server ignores their response body.
|
|
91
91
|
AUTH_TRIGGERS = %i[
|
|
@@ -98,18 +98,18 @@ module Parse
|
|
|
98
98
|
LIVE_QUERY_TRIGGERS = %i[before_connect before_subscribe after_event].freeze
|
|
99
99
|
|
|
100
100
|
# Every trigger whose payload is not an object save/delete/find shape.
|
|
101
|
-
# Parse Server's webhook response handler resolves
|
|
101
|
+
# Parse Server's webhook response handler resolves `{}` for all of these
|
|
102
102
|
# (the body is ignored), so the router normalizes their handler result to a
|
|
103
103
|
# success no-op rather than serializing a returned object into the response.
|
|
104
104
|
NON_OBJECT_TRIGGERS = (AUTH_TRIGGERS + LIVE_QUERY_TRIGGERS).freeze
|
|
105
105
|
|
|
106
|
-
# The
|
|
107
|
-
# the operation. Parse Server only treats an
|
|
108
|
-
# rejection -- a
|
|
109
|
-
# connect / subscribe / reset proceed. So, mirroring the
|
|
110
|
-
# convention, the router converts a
|
|
111
|
-
# {ResponseError} (which serializes to
|
|
112
|
-
# trigger; the
|
|
106
|
+
# The `before*` subset of {NON_OBJECT_TRIGGERS} for which a handler can DENY
|
|
107
|
+
# the operation. Parse Server only treats an `{error}` response as a
|
|
108
|
+
# rejection -- a `{success:false}` body resolves and lets the login /
|
|
109
|
+
# connect / subscribe / reset proceed. So, mirroring the `before_save`
|
|
110
|
+
# convention, the router converts a `false` return from one of these into a
|
|
111
|
+
# {ResponseError} (which serializes to `{error}`). `error!` works for any
|
|
112
|
+
# trigger; the `after*` variants fire after the fact and cannot undo it.
|
|
113
113
|
REJECTABLE_NON_OBJECT_TRIGGERS = %i[
|
|
114
114
|
before_login before_password_reset_request before_connect before_subscribe
|
|
115
115
|
].freeze
|
|
@@ -607,9 +607,9 @@ module Parse
|
|
|
607
607
|
# skips the DNS resolution and private/internal CIDR refusal. Other
|
|
608
608
|
# checks (scheme, userinfo, host presence) still apply. Intended for
|
|
609
609
|
# integration tests that register webhooks at Docker bridge hosts
|
|
610
|
-
# (e.g.
|
|
610
|
+
# (e.g. `host.docker.internal`) which only resolve from inside the
|
|
611
611
|
# Parse Server container. May also be enabled via
|
|
612
|
-
#
|
|
612
|
+
# `PARSE_WEBHOOK_ALLOW_PRIVATE_URLS=true`. Do not enable in
|
|
613
613
|
# production: the resolution guard is what blocks attacker-driven
|
|
614
614
|
# webhook redirection to internal hosts.
|
|
615
615
|
# @return [Boolean]
|
data/parse-stack-next.gemspec
CHANGED
|
@@ -23,7 +23,25 @@ Gem::Specification.new do |spec|
|
|
|
23
23
|
"rubygems_mfa_required" => "true",
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
# Ship only what an SDK consumer needs: the library, executables, the
|
|
27
|
+
# rendered guides + copy-paste examples, the README banner asset, and the
|
|
28
|
+
# standard metadata files. Everything else that is tracked purely for
|
|
29
|
+
# development — .github/, .vscode/, .bundle/, .env.*, scripts/, config/,
|
|
30
|
+
# Makefile, Rakefile, Gemfile(.lock), and dotfiles — is intentionally
|
|
31
|
+
# excluded so ~1MB of packaging noise isn't shipped to every install.
|
|
32
|
+
spec.files = `git ls-files -z`.split("\x0").select do |f|
|
|
33
|
+
f.start_with?("lib/", "bin/", "docs/", "examples/", "assets/") ||
|
|
34
|
+
%w[
|
|
35
|
+
README.md
|
|
36
|
+
CHANGELOG.md
|
|
37
|
+
LICENSE.txt
|
|
38
|
+
SECURITY.md
|
|
39
|
+
parse-stack-next.gemspec
|
|
40
|
+
].include?(f)
|
|
41
|
+
end.reject do |f|
|
|
42
|
+
# Internal dev docs that live under docs/ but aren't consumer-facing.
|
|
43
|
+
f == "docs/client_sdk_todo.md"
|
|
44
|
+
end
|
|
27
45
|
spec.bindir = "bin"
|
|
28
46
|
spec.executables = ["parse-console"] #spec.files.grep(%r{^bin/pstack/}) { |f| File.basename(f) }
|
|
29
47
|
spec.require_paths = ["lib"]
|
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.
|
|
4
|
+
version: 5.5.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Adrian Curtin
|
|
@@ -208,28 +208,9 @@ executables:
|
|
|
208
208
|
extensions: []
|
|
209
209
|
extra_rdoc_files: []
|
|
210
210
|
files:
|
|
211
|
-
- ".bundle/config"
|
|
212
|
-
- ".env.sample"
|
|
213
|
-
- ".env.test"
|
|
214
|
-
- ".github/ISSUE_TEMPLATE/bug_report.yml"
|
|
215
|
-
- ".github/ISSUE_TEMPLATE/feature_request.yml"
|
|
216
|
-
- ".github/dependabot.yml"
|
|
217
|
-
- ".github/workflows/codeql.yml"
|
|
218
|
-
- ".github/workflows/docs.yml"
|
|
219
|
-
- ".github/workflows/release.yml"
|
|
220
|
-
- ".github/workflows/ruby.yml"
|
|
221
|
-
- ".gitignore"
|
|
222
|
-
- ".ruby-version"
|
|
223
|
-
- ".solargraph.yml"
|
|
224
|
-
- ".vscode/settings.json"
|
|
225
|
-
- ".yardopts"
|
|
226
211
|
- CHANGELOG.md
|
|
227
|
-
- Gemfile
|
|
228
|
-
- Gemfile.lock
|
|
229
212
|
- LICENSE.txt
|
|
230
|
-
- Makefile
|
|
231
213
|
- README.md
|
|
232
|
-
- Rakefile
|
|
233
214
|
- SECURITY.md
|
|
234
215
|
- assets/parse-stack-next-avatar.png
|
|
235
216
|
- assets/parse-stack-next-avatar.svg
|
|
@@ -240,7 +221,6 @@ files:
|
|
|
240
221
|
- bin/parse-console
|
|
241
222
|
- bin/server
|
|
242
223
|
- bin/setup
|
|
243
|
-
- config/parse-config.json
|
|
244
224
|
- docs/TEST_SERVER.md
|
|
245
225
|
- docs/_config.yml
|
|
246
226
|
- docs/acl_clp_guide.md
|
|
@@ -316,6 +296,7 @@ files:
|
|
|
316
296
|
- lib/parse/client/protocol.rb
|
|
317
297
|
- lib/parse/client/request.rb
|
|
318
298
|
- lib/parse/client/response.rb
|
|
299
|
+
- lib/parse/client/url_redaction.rb
|
|
319
300
|
- lib/parse/clp_scope.rb
|
|
320
301
|
- lib/parse/console.rb
|
|
321
302
|
- lib/parse/embeddings.rb
|
|
@@ -438,23 +419,6 @@ files:
|
|
|
438
419
|
- lib/parse/webhooks/replay_protection.rb
|
|
439
420
|
- lib/parse/webhooks/trigger_audit.rb
|
|
440
421
|
- parse-stack-next.gemspec
|
|
441
|
-
- scripts/debug-ips.js
|
|
442
|
-
- scripts/docker/Dockerfile.parse
|
|
443
|
-
- scripts/docker/atlas-init.js
|
|
444
|
-
- scripts/docker/docker-compose.atlas.yml
|
|
445
|
-
- scripts/docker/docker-compose.test.yml
|
|
446
|
-
- scripts/docker/docker-compose.verifyemail.yml
|
|
447
|
-
- scripts/docker/mongo-init.js
|
|
448
|
-
- scripts/docker/preflight.sh
|
|
449
|
-
- scripts/eval_mcp_with_lm_studio.rb
|
|
450
|
-
- scripts/start-parse.sh
|
|
451
|
-
- scripts/start_mcp_server.rb
|
|
452
|
-
- scripts/test_server_connection.rb
|
|
453
|
-
- scripts/vector_prototype/create_vector_index.js
|
|
454
|
-
- scripts/vector_prototype/fetch_embeddings.py
|
|
455
|
-
- scripts/vector_prototype/fixture_manifest.json
|
|
456
|
-
- scripts/vector_prototype/query_prototype.rb
|
|
457
|
-
- scripts/vector_prototype/run.sh
|
|
458
422
|
homepage: https://github.com/neurosynq/parse-stack-next
|
|
459
423
|
licenses:
|
|
460
424
|
- MIT
|
data/.bundle/config
DELETED
data/.env.sample
DELETED
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
# Sample environment configuration for parse-stack.
|
|
2
|
-
#
|
|
3
|
-
# Copy to `.env` and fill in real values. `.env` is gitignored;
|
|
4
|
-
# this file (`.env.sample`) is committed as the reference.
|
|
5
|
-
#
|
|
6
|
-
# Loaded automatically by:
|
|
7
|
-
# - `ruby -rdotenv/load -Ilib:test path/to/test.rb`
|
|
8
|
-
# - Anything that requires `dotenv` at boot
|
|
9
|
-
# Or pass values inline:
|
|
10
|
-
# LLM_PROVIDER=openai LLM_API_KEY=sk-... bundle exec rake test:foo
|
|
11
|
-
|
|
12
|
-
# ===========================================================================
|
|
13
|
-
# Test harness
|
|
14
|
-
# ===========================================================================
|
|
15
|
-
|
|
16
|
-
# Routes the test suite at the Docker Compose Parse Server + MongoDB defined
|
|
17
|
-
# in scripts/docker/docker-compose.test.yml. Unset for in-process unit tests.
|
|
18
|
-
PARSE_TEST_USE_DOCKER='true'
|
|
19
|
-
|
|
20
|
-
# ===========================================================================
|
|
21
|
-
# Parse client (test fixtures + Rake tasks that boot a Parse client)
|
|
22
|
-
#
|
|
23
|
-
# Defaults below match scripts/docker/docker-compose.test.yml.
|
|
24
|
-
# Override for testing against a different Parse Server instance.
|
|
25
|
-
# ===========================================================================
|
|
26
|
-
|
|
27
|
-
PARSE_SERVER_URL=http://localhost:2337/parse
|
|
28
|
-
PARSE_APP_ID=myAppId
|
|
29
|
-
PARSE_API_KEY=myApiKey
|
|
30
|
-
PARSE_MASTER_KEY=myMasterKey
|
|
31
|
-
|
|
32
|
-
# Optional client tuning (read by Parse::Client.new):
|
|
33
|
-
# PARSE_OPEN_TIMEOUT=5
|
|
34
|
-
# PARSE_TIMEOUT=30
|
|
35
|
-
# PARSE_REQUIRE_HTTPS=true
|
|
36
|
-
|
|
37
|
-
# Optional service URLs (only if you split webhooks/hooks endpoints):
|
|
38
|
-
# PARSE_LIVE_QUERY_URL=
|
|
39
|
-
# HOOKS_URL=
|
|
40
|
-
|
|
41
|
-
# ===========================================================================
|
|
42
|
-
# Test harness — uses an ISOLATED stack (not the values above)
|
|
43
|
-
#
|
|
44
|
-
# The integration test suite does NOT connect with the defaults above. It runs
|
|
45
|
-
# on a deliberately isolated Docker stack — a private 29xxx host-port block, a
|
|
46
|
-
# dedicated Compose project `psnext-it`, and the `parse_stack_next_it` database
|
|
47
|
-
# — so it never collides with another Parse system on the same host. The full
|
|
48
|
-
# value set is listed in `.env.test` (a committed reference; nothing auto-loads
|
|
49
|
-
# it — source it or export the vars). The full port map and override variables
|
|
50
|
-
# are documented in the "Isolated test environment" section of CLAUDE.md.
|
|
51
|
-
# ===========================================================================
|
|
52
|
-
|
|
53
|
-
# ===========================================================================
|
|
54
|
-
# Webhooks
|
|
55
|
-
# ===========================================================================
|
|
56
|
-
|
|
57
|
-
# Required for the Parse::Webhooks Rack endpoint to accept calls.
|
|
58
|
-
# Without this, the endpoint fails closed (4.0.0+ behavior).
|
|
59
|
-
# PARSE_WEBHOOK_KEY=
|
|
60
|
-
# PARSE_SERVER_WEBHOOK_KEY=
|
|
61
|
-
# PARSE_WEBHOOK_ALLOW_UNAUTHENTICATED=false
|
|
62
|
-
|
|
63
|
-
# ===========================================================================
|
|
64
|
-
# MCP Server
|
|
65
|
-
# ===========================================================================
|
|
66
|
-
|
|
67
|
-
# Required dual-gate for the standalone MCP server. Both this AND
|
|
68
|
-
# `Parse.mcp_server_enabled = true` (in code) are required before
|
|
69
|
-
# Parse::Agent.enable_mcp! will boot. Embedded MCPRackApp does NOT require
|
|
70
|
-
# either flag.
|
|
71
|
-
# PARSE_MCP_ENABLED=true
|
|
72
|
-
|
|
73
|
-
# X-MCP-API-Key value used by MCPServer and the rake test:mcp_inspector task.
|
|
74
|
-
# MCP_API_KEY=changeme-mcp-key
|
|
75
|
-
|
|
76
|
-
# Override the inspector port (default 3099) and key when running
|
|
77
|
-
# `rake test:mcp_inspector`:
|
|
78
|
-
# MCP_INSPECTOR_PORT=3099
|
|
79
|
-
# MCP_INSPECTOR_KEY=rake-inspector-key
|
|
80
|
-
|
|
81
|
-
# ===========================================================================
|
|
82
|
-
# LLM provider for `rake mcp:chat` / `rake mcp:console`
|
|
83
|
-
# (also consumed by the LLM-driven integration test files under
|
|
84
|
-
# test/lib/parse/agent/mcp_real_llm_*_test.rb)
|
|
85
|
-
#
|
|
86
|
-
# Pick ONE provider stanza below and uncomment its block. The chat console
|
|
87
|
-
# refuses to start without LLM_PROVIDER set.
|
|
88
|
-
# ===========================================================================
|
|
89
|
-
|
|
90
|
-
# --- Option A: LM Studio (free, local) -------------------------------------
|
|
91
|
-
# Start the LM Studio HTTP server first (Server tab → Start Server), with a
|
|
92
|
-
# tool-capable model loaded (Qwen2.5-7B-instruct, Llama-3.1-8B-instruct,
|
|
93
|
-
# gpt-oss-20b, etc.). The API key value is ignored by LM Studio.
|
|
94
|
-
#
|
|
95
|
-
# LLM_PROVIDER=lmstudio
|
|
96
|
-
# LLM_MODEL=qwen2.5-7b-instruct
|
|
97
|
-
# LLM_BASE_URL=http://localhost:1234/v1
|
|
98
|
-
# LLM_API_KEY=lm-studio
|
|
99
|
-
|
|
100
|
-
# --- Option B: OpenAI gpt-4o-mini (~$0.0001 per run) -----------------------
|
|
101
|
-
# Get a key at https://platform.openai.com/api-keys
|
|
102
|
-
#
|
|
103
|
-
# LLM_PROVIDER=openai
|
|
104
|
-
# LLM_API_KEY=sk-proj-...
|
|
105
|
-
# LLM_MODEL=gpt-4o-mini
|
|
106
|
-
# LLM_BASE_URL=https://api.openai.com/v1 # default; override only if proxying
|
|
107
|
-
|
|
108
|
-
# --- Option C: Anthropic Claude Haiku (~$0.001 per run) --------------------
|
|
109
|
-
# Get a key at https://console.anthropic.com/settings/keys
|
|
110
|
-
#
|
|
111
|
-
# LLM_PROVIDER=anthropic
|
|
112
|
-
# LLM_API_KEY=sk-ant-api03-...
|
|
113
|
-
# LLM_MODEL=claude-haiku-4-5
|
|
114
|
-
# LLM_BASE_URL=https://api.anthropic.com/v1
|
|
115
|
-
|
|
116
|
-
# --- Legacy LLM endpoint (Parse::Agent#ask path, NOT the MCP smoke test) ---
|
|
117
|
-
# Used by the in-process Parse::Agent#ask conversational path, separate from
|
|
118
|
-
# the MCP smoke test above. Defaults to a local OpenAI-compatible endpoint.
|
|
119
|
-
#
|
|
120
|
-
# LLM_ENDPOINT=http://localhost:1234/v1
|
|
121
|
-
# OPENAI_API_KEY=
|
|
122
|
-
# ANTHROPIC_API_KEY=
|
|
123
|
-
|
|
124
|
-
# ===========================================================================
|
|
125
|
-
# Embedding providers (Parse::Embeddings)
|
|
126
|
-
#
|
|
127
|
-
# Used by `Parse::Embeddings.register(...)` in initializers / tests for the
|
|
128
|
-
# text-only providers shipped in v5.0: OpenAI, Cohere, Voyage, Jina, Qwen.
|
|
129
|
-
# LocalHTTP providers (Ollama, LM Studio, vLLM, self-hosted voyage-4-nano /
|
|
130
|
-
# Qwen3-Embedding) read no env var by default — their api_key (if any) is
|
|
131
|
-
# passed at registration time.
|
|
132
|
-
# ===========================================================================
|
|
133
|
-
|
|
134
|
-
# OPENAI_API_KEY=sk-...
|
|
135
|
-
# COHERE_API_KEY=
|
|
136
|
-
# VOYAGE_API_KEY=pa-...
|
|
137
|
-
# JINA_API_KEY=jina_...
|
|
138
|
-
# DASHSCOPE_API_KEY=sk-... # Alibaba Cloud DashScope (Qwen 3 embeddings)
|
data/.env.test
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
# Parse Server Test Configuration
|
|
2
|
-
PARSE_TEST_SERVER_URL=http://localhost:29337/parse
|
|
3
|
-
PARSE_TEST_APP_ID=psnextItAppId
|
|
4
|
-
PARSE_TEST_API_KEY=psnext-it-rest-key
|
|
5
|
-
PARSE_TEST_MASTER_KEY=psnextItMasterKey
|
|
6
|
-
|
|
7
|
-
# Docker Configuration
|
|
8
|
-
PARSE_TEST_USE_DOCKER=true
|
|
9
|
-
PARSE_TEST_AUTO_START=false
|
|
10
|
-
PARSE_TEST_AUTO_STOP=false
|