Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
21 changes: 20 additions & 1 deletion .env.test
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,26 @@ PARSE_TEST_APP_ID=psnextItAppId
PARSE_TEST_API_KEY=psnext-it-rest-key
PARSE_TEST_MASTER_KEY=psnextItMasterKey

# Redis (client side, read by the Ruby suite).
#
# db 0 is the SDK's own cache: the Faraday response cache, the identity and
# role planes, and the parse-stack:foc:v1:* create-locks.
PARSE_TEST_REDIS_URL=redis://localhost:29379/0
# db 1 is Parse Server's OWN cache, which the SDK only ever reads
# (Parse::Cache::UpstreamRoles, parse_cache_url:). Parse Server clears this
# database with a raw FLUSHDB on every _Role write, so it must never be the
# same database as PARSE_TEST_REDIS_URL.
# See https://github.com/parse-community/parse-server/issues/10617
PARSE_TEST_SERVER_CACHE_REDIS_URL=redis://localhost:29379/1

# Redis (compose side, resolved INSIDE the parse-server container). Uses the
# compose service name and container port, not the 29xxx host port. Setting
# this engages test/cloud/redis-cache-adapter.js; unset it and Parse Server
# falls back to its in-process InMemoryCacheAdapter.
PARSE_CACHE_REDIS_URL=redis://redis:6379/1
PARSE_CACHE_REDIS_TTL_MS=30000

# Docker Configuration
PARSE_TEST_USE_DOCKER=true
PARSE_TEST_AUTO_START=false
PARSE_TEST_AUTO_STOP=false
PARSE_TEST_AUTO_STOP=false
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ logs
!docs/atlas_vector_search_guide.md
!docs/usage_guide.md
!docs/webhooks_guide.md
!docs/caching.md
!SECURITY.md
!docs/client_sdk_guide.md
!docs/acl_clp_guide.md
Expand Down
409 changes: 409 additions & 0 deletions CHANGELOG.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ group :test, :development do
gem "debug", ">= 1.0"
gem "minitest"
gem "minitest-mock"
gem 'minitest-reporters'
gem "minitest-reporters"
gem "pry"
# bundler-audit: scans Gemfile.lock against the ruby-advisory-db for known
# CVEs. Used by the upstream-watch skill and dependency review.
Expand Down
26 changes: 13 additions & 13 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
parse-stack-next (5.6.0)
parse-stack-next (5.7.0)
activemodel (>= 6.1, < 9)
activesupport (>= 6.1, < 9)
connection_pool (>= 2.2, < 4)
Expand All @@ -16,9 +16,9 @@ PATH
GEM
remote: https://rubygems.org/
specs:
activemodel (8.1.3)
activesupport (= 8.1.3)
activesupport (8.1.3)
activemodel (8.1.3.1)
activesupport (= 8.1.3.1)
activesupport (8.1.3.1)
base64
bigdecimal
concurrent-ruby (~> 1.0, >= 1.3.1)
Expand All @@ -41,15 +41,15 @@ GEM
thor (~> 1.0)
chunky_png (1.4.0)
coderay (1.1.3)
concurrent-ruby (1.3.7)
concurrent-ruby (1.3.8)
connection_pool (3.0.2)
csv (3.3.5)
csv (3.3.6)
debug (1.11.1)
irb (~> 1.10)
reline (>= 0.3.8)
dotenv (3.2.0)
drb (2.2.3)
erb (6.0.4)
erb (6.0.6)
faraday (2.14.3)
faraday-net_http (>= 2.0, < 3.5)
json
Expand All @@ -60,7 +60,7 @@ GEM
faraday (~> 2.5)
net-http-persistent (>= 4.0.4, < 5)
fiber-storage (1.0.1)
graphql (2.6.6)
graphql (2.6.7)
base64
fiber-storage
logger
Expand All @@ -72,7 +72,7 @@ GEM
prism (>= 1.3.0)
rdoc (>= 4.0.0)
reline (>= 0.4.2)
json (2.21.1)
json (2.21.2)
logger (1.7.0)
method_source (1.1.0)
minitest (6.0.6)
Expand Down Expand Up @@ -119,7 +119,7 @@ GEM
rackup (2.3.1)
rack (>= 3)
rake (13.4.2)
rbs (4.0.3)
rbs (4.1.1)
logger
prism (>= 1.6.0)
tsort
Expand All @@ -129,9 +129,9 @@ GEM
rbs (>= 4.0.0)
tsort
redcarpet (3.6.1)
redis (5.4.1)
redis-client (>= 0.22.0)
redis-client (0.30.0)
redis (6.0.0)
redis-client (= 0.30.1)
redis-client (0.30.1)
connection_pool
reline (0.6.3)
io-console (~> 0.5)
Expand Down
384 changes: 378 additions & 6 deletions README.md

Large diffs are not rendered by default.

65 changes: 32 additions & 33 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,18 @@ require "rake/testtask"
# @return [Array(String, String, String, String)]
# server_url, application_id, api_key, master_key
def mcp_credentials_or_abort!
server_url = ENV["PARSE_SERVER_URL"] || "http://localhost:29337/parse"
app_id = ENV["PARSE_APP_ID"]
server_url = ENV["PARSE_SERVER_URL"] || "http://localhost:29337/parse"
app_id = ENV["PARSE_APP_ID"]
rest_api_key = ENV["PARSE_API_KEY"]
master_key = ENV["PARSE_MASTER_KEY"]
master_key = ENV["PARSE_MASTER_KEY"]

is_local = server_url =~ %r{\Ahttps?://(?:localhost|127\.0\.0\.1|::1|\[::1\])(?::|/|\z)}

if app_id.to_s.empty? || master_key.to_s.empty?
if is_local
app_id = (app_id.to_s.empty? ? "psnextItAppId" : app_id)
app_id = (app_id.to_s.empty? ? "psnextItAppId" : app_id)
rest_api_key = (rest_api_key.to_s.empty? ? "myApiKey" : rest_api_key)
master_key = (master_key.to_s.empty? ? "psnextItMasterKey" : master_key)
master_key = (master_key.to_s.empty? ? "psnextItMasterKey" : master_key)
else
abort "[Rakefile] PARSE_SERVER_URL=#{server_url} is not local; refusing to fall back to " \
"placeholder credentials. Set PARSE_APP_ID and PARSE_MASTER_KEY explicitly."
Expand Down Expand Up @@ -118,8 +118,7 @@ def console_login_with_optional_mfa(user, pwd)
# ServiceUnavailableError for the OTHER_CAUSE code) or a nil return. Since a
# token was supplied here, treat any failure as an MFA verification failure
# and abort cleanly rather than letting an unhandled exception escape.
result =
begin
result = begin
Parse::User.login_with_mfa(user, pwd, token)
rescue Parse::MFA::VerificationError, Parse::Error => e
abort "[client:console] MFA verification failed for #{user.inspect}: #{e.message}"
Expand All @@ -139,11 +138,11 @@ end
# environment. A default `rake test` must never become live and billable
# as a side effect of an exported key. Run them via `rake test:contract`.
Rake::TestTask.new do |t|
ENV['PARSE_TEST_USE_DOCKER'] = 'true'
ENV["PARSE_TEST_USE_DOCKER"] = "true"
t.libs << "lib/parse/stack"
t.test_files = FileList["test/lib/**/*_test.rb"]
.exclude("test/lib/**/*disruptive*")
.exclude("test/lib/**/*contract_test.rb")
.exclude("test/lib/**/*disruptive*")
.exclude("test/lib/**/*contract_test.rb")
t.warning = false
t.verbose = true
end
Expand Down Expand Up @@ -227,17 +226,17 @@ namespace :test do
# `test:integration:disruptive` so they never interleave with — and
# flake — the rest of the integration suite against the shared server.
files = FileList["test/lib/**/*integration_test.rb"]
.exclude("test/lib/**/*disruptive*")
.exclude("test/lib/**/*disruptive*")
run_test_files!("Integration tests", files, log: "tmp/integration-progress.log")
end

desc "Run unit tests only (no Docker required). " \
"Knobs: TEST_PATTERN=<substr>, CONTINUE_ON_FAILURE=false."
task :unit do
files = FileList["test/lib/**/*_test.rb"]
.exclude("test/lib/**/*integration_test.rb")
.exclude("test/lib/**/*disruptive*")
.exclude("test/lib/**/*contract_test.rb")
.exclude("test/lib/**/*integration_test.rb")
.exclude("test/lib/**/*disruptive*")
.exclude("test/lib/**/*contract_test.rb")
run_test_files!("Unit tests", files, log: "tmp/unit-progress.log")
end

Expand Down Expand Up @@ -325,9 +324,9 @@ namespace :test do
abort "[mcp_inspector] npx not found on PATH. Install Node.js 18+ or use `nvm use 18`."
end

port = ENV["MCP_INSPECTOR_PORT"] || "3099"
api_key = ENV["MCP_INSPECTOR_KEY"] || "rake-inspector-key"
method = ENV["METHOD"] || "tools/list"
port = ENV["MCP_INSPECTOR_PORT"] || "3099"
api_key = ENV["MCP_INSPECTOR_KEY"] || "rake-inspector-key"
method = ENV["METHOD"] || "tools/list"

server_url, app_id, rest_api_key, master_key = mcp_credentials_or_abort!

Expand Down Expand Up @@ -388,7 +387,7 @@ namespace :test do
ensure
if pid
Process.kill("TERM", pid) rescue nil
Process.wait(pid) rescue nil
Process.wait(pid) rescue nil
end
end
end
Expand Down Expand Up @@ -457,13 +456,13 @@ namespace :mcp do
require "parse/agent/mcp_client"

server_url, app_id, rest_api_key, master_key = mcp_credentials_or_abort!
permissions = (ENV["MCP_AGENT_PERMISSIONS"] || "readonly").to_sym
permissions = (ENV["MCP_AGENT_PERMISSIONS"] || "readonly").to_sym

Parse.setup(
server_url: server_url,
server_url: server_url,
application_id: app_id,
api_key: rest_api_key,
master_key: master_key,
api_key: rest_api_key,
master_key: master_key,
)

agent = Parse::Agent.new(permissions: permissions)
Expand All @@ -485,7 +484,7 @@ namespace :mcp do
puts "get_all_schemas failed: #{result[:error]}"
next nil
end
custom = (result[:data][:custom] || []).map { |c| c[:name] }
custom = (result[:data][:custom] || []).map { |c| c[:name] }
built_in = (result[:data][:built_in] || []).map { |c| c[:name] }
puts "Custom: #{custom.sort.join(", ")}"
puts "Built-in: #{built_in.sort.join(", ")}"
Expand Down Expand Up @@ -607,10 +606,10 @@ namespace :mcp do

server_url, app_id, rest_api_key, master_key = mcp_credentials_or_abort!
Parse.setup(
server_url: server_url,
server_url: server_url,
application_id: app_id,
api_key: rest_api_key,
master_key: master_key,
api_key: rest_api_key,
master_key: master_key,
)

permissions = (ENV["MCP_AGENT_PERMISSIONS"] || "readonly").to_sym
Expand Down Expand Up @@ -733,16 +732,16 @@ namespace :mcp do
require "parse/agent"

tool_name = (args[:name] || abort("usage: rake 'mcp:tool[name,jsonArgs]'")).to_sym
raw = args[:args_json] || "{}"
parsed = JSON.parse(raw)
kwargs = parsed.transform_keys(&:to_sym)
raw = args[:args_json] || "{}"
parsed = JSON.parse(raw)
kwargs = parsed.transform_keys(&:to_sym)

server_url, app_id, rest_api_key, master_key = mcp_credentials_or_abort!
Parse.setup(
server_url: server_url,
server_url: server_url,
application_id: app_id,
api_key: rest_api_key,
master_key: master_key,
api_key: rest_api_key,
master_key: master_key,
)

agent = Parse::Agent.new(permissions: (ENV["MCP_AGENT_PERMISSIONS"] || "readonly").to_sym)
Expand All @@ -761,7 +760,7 @@ namespace :client do
desc "Interactive console authenticated as a Parse user (session token or login), not master"
task :console do
require "irb"
begin; require "dotenv/load"; rescue LoadError; end
begin; require "dotenv/load"; rescue LoadError; end
$LOAD_PATH.unshift(File.expand_path("lib", __dir__))
require "parse-stack"

Expand Down
Loading
Loading