diff --git a/README.md b/README.md index 8d936d6b..99f63635 100644 --- a/README.md +++ b/README.md @@ -46,46 +46,24 @@ export BRAINTRUST_API_KEY="your-api-key" ```ruby require "braintrust" -# Initialize Braintrust Braintrust.init -# Simple food classifier (the code being evaluated) -def classify_food(input) - fruit = %w[apple banana strawberry orange grape mango] - vegetable = %w[carrot broccoli spinach potato tomato cucumber] - - input_lower = input.downcase - return "fruit" if fruit.any? { |f| input_lower.include?(f) } - return "vegetable" if vegetable.any? { |v| input_lower.include?(v) } - "unknown" -end +# Define task to evaluate +task = ->(input) { input.include?("a") ? "fruit" : "vegetable" } -# Run an evaluation -result = Braintrust::Eval.run( +# Run evaluation +Braintrust::Eval.run( project: "my-project", - experiment: "food-classifier-eval", - - # Test cases + experiment: "food-classifier", cases: [ {input: "apple", expected: "fruit"}, - {input: "carrot", expected: "vegetable"}, - {input: "banana", expected: "fruit"}, - {input: "broccoli", expected: "vegetable"} + {input: "carrot", expected: "vegetable"} ], - - # Task to evaluate - task: ->(input) { classify_food(input) }, - - # Scorers to judge output quality + task: task, scorers: [ - Braintrust::Eval.scorer("exact_match") { |input, expected, output| - (output == expected) ? 1.0 : 0.0 - } + ->(input, expected, output) { output == expected ? 1.0 : 0.0 } ] ) - -# View results -puts "View results at: #{result.permalink}" ``` ### Tracing @@ -128,20 +106,15 @@ puts "View trace in Braintrust!" require "braintrust" require "openai" -# Initialize Braintrust Braintrust.init -# Create OpenAI client client = OpenAI::Client.new(api_key: ENV["OPENAI_API_KEY"]) -# Wrap the client with Braintrust tracing Braintrust::Trace::OpenAI.wrap(client) -# Create a root span to capture the operation tracer = OpenTelemetry.tracer_provider.tracer("openai-app") root_span = nil -# Make a chat completion request (automatically traced!) response = tracer.in_span("chat-completion") do |span| root_span = span @@ -157,10 +130,8 @@ end puts "Response: #{response.choices[0].message.content}" -# View the trace puts "View trace at: #{Braintrust::Trace.permalink(root_span)}" -# Shutdown to flush spans OpenTelemetry.tracer_provider.shutdown ``` diff --git a/Rakefile b/Rakefile index 2226c08e..654caaae 100644 --- a/Rakefile +++ b/Rakefile @@ -28,6 +28,26 @@ task :clean do FileUtils.rm_f("changelog.md") end +def run_example(example) + prefix = case example + when /openai/, /kitchen-sink/ + "bundle exec appraisal openai-latest" + else + "bundle exec" + end + + sh "#{prefix} ruby #{example}" +end + +desc "Run a single example with the correct gemfile" +task :example, [:path] do |t, args| + example = args[:path] + raise "Usage: rake example[path/to/example.rb]" unless example + + puts "Running #{example}..." + run_example(example) +end + desc "Run all examples" task :examples do examples = FileList["examples/**/*.rb"].exclude("examples/**/README.md") @@ -36,10 +56,7 @@ task :examples do examples.each do |example| puts "\n=== Running #{example} ===" - sh "bundle exec ruby #{example}" do |ok, res| - puts "✓ #{example} completed" if ok - puts "✗ #{example} failed (#{res.exitstatus})" unless ok - end + run_example(example) end end @@ -94,6 +111,9 @@ namespace :test do sh "bundle exec appraisal rake test" end + desc "Run tests against all dependency scenarios (alias for test:appraisal)" + task all: :appraisal + namespace :appraisal do desc "Show help for appraisal scenarios and usage" task :help do diff --git a/examples/eval.rb b/examples/eval.rb index 7a0c900a..62a11da8 100644 --- a/examples/eval.rb +++ b/examples/eval.rb @@ -17,17 +17,7 @@ # Usage: # bundle exec ruby examples/eval.rb -# Initialize Braintrust with blocking login -Braintrust.init(blocking_login: true) - -# Create OpenTelemetry TracerProvider -tracer_provider = OpenTelemetry::SDK::Trace::TracerProvider.new - -# Enable Braintrust tracing -Braintrust::Trace.enable(tracer_provider) - -# Set as global provider -OpenTelemetry.tracer_provider = tracer_provider +Braintrust.init # Simple food classifier (the code being evaluated) # In a real scenario, this would call your model/API @@ -71,8 +61,7 @@ def call(input, expected, output, metadata = {}) } # Run the evaluation -puts "\nRunning evaluation..." -result = Braintrust::Eval.run( +Braintrust::Eval.run( # Required: Project and experiment project: "ruby-sdk-examples", experiment: "food-classifier-eval", @@ -130,30 +119,5 @@ def call(input, expected, output, metadata = {}) } ) -# Inspect the results -puts "\n" + "=" * 50 -puts "Evaluation Complete!" -puts "=" * 50 - -puts "\nExperiment: #{result.experiment_name}" -puts "Project ID: #{result.project_id}" -puts "Duration: #{result.duration.round(2)}s" -puts "Status: #{result.success? ? "✓ Success" : "✗ Failed"}" - -# Show the permalink to view in Braintrust UI -puts "\nView results at:" -puts " #{result.permalink}" - -# Show errors if any -if result.failed? - puts "\nErrors (#{result.errors.length}):" - result.errors.each do |error| - puts " - #{error}" - end - exit 1 -end - -puts "\n✓ All test cases passed!" - # Shutdown to flush spans to Braintrust -tracer_provider.shutdown +OpenTelemetry.tracer_provider.shutdown diff --git a/examples/eval/dataset.rb b/examples/eval/dataset.rb index 0aef735b..250ead02 100644 --- a/examples/eval/dataset.rb +++ b/examples/eval/dataset.rb @@ -14,16 +14,9 @@ require "bundler/setup" require "braintrust" -# Initialize Braintrust with login (sets global state) -Braintrust.init(blocking_login: true) +Braintrust.init api = Braintrust::API.new # Uses global state - -# Enable tracing to send spans to Braintrust -require "opentelemetry/sdk" -tracer_provider = OpenTelemetry::SDK::Trace::TracerProvider.new -Braintrust::Trace.enable(tracer_provider) -OpenTelemetry.tracer_provider = tracer_provider -at_exit { tracer_provider.shutdown } +at_exit { OpenTelemetry.tracer_provider.shutdown } # Project name project_name = "ruby-sdk-examples" diff --git a/examples/internal/evals-with-errors.rb b/examples/internal/evals-with-errors.rb index 1641a94c..6414afed 100755 --- a/examples/internal/evals-with-errors.rb +++ b/examples/internal/evals-with-errors.rb @@ -17,17 +17,7 @@ # Usage: # bundle exec ruby examples/internal/evals-with-errors.rb -# Initialize Braintrust with blocking login -Braintrust.init(blocking_login: true) - -# Create OpenTelemetry TracerProvider -tracer_provider = OpenTelemetry::SDK::Trace::TracerProvider.new - -# Enable Braintrust tracing -Braintrust::Trace.enable(tracer_provider) - -# Set as global provider -OpenTelemetry.tracer_provider = tracer_provider +Braintrust.init puts "Evals with Errors Example" puts "=" * 60 @@ -217,4 +207,4 @@ def risky_task(input) end # Shutdown to flush spans to Braintrust -tracer_provider.shutdown +OpenTelemetry.tracer_provider.shutdown diff --git a/examples/internal/kitchen-sink.rb b/examples/internal/kitchen-sink.rb index edcd6acd..34d44ea7 100755 --- a/examples/internal/kitchen-sink.rb +++ b/examples/internal/kitchen-sink.rb @@ -24,23 +24,13 @@ exit 1 end -# Initialize Braintrust with blocking login -Braintrust.init(blocking_login: true) - -# Create OpenTelemetry TracerProvider -tracer_provider = OpenTelemetry::SDK::Trace::TracerProvider.new - -# Enable Braintrust tracing -Braintrust::Trace.enable(tracer_provider) - -# Set as global provider -OpenTelemetry.tracer_provider = tracer_provider +Braintrust.init # Create OpenAI client openai_client = OpenAI::Client.new(api_key: ENV["OPENAI_API_KEY"]) # Wrap the client with Braintrust tracing -Braintrust::Trace::OpenAI.wrap(openai_client, tracer_provider: tracer_provider) +Braintrust::Trace::OpenAI.wrap(openai_client) puts "Kitchen Sink Eval Example" puts "=" * 60 @@ -363,10 +353,10 @@ def call(input, expected, output, metadata = {}) result.errors.each_with_index do |error, i| puts " #{i + 1}. #{error}" end - exit 1 + puts "\nNote: Some errors are intentional to demonstrate error handling." +else + puts "\n✓ All test cases completed successfully!" end -puts "\n✓ All test cases completed successfully!" - # Shutdown to flush spans -tracer_provider.shutdown +OpenTelemetry.tracer_provider.shutdown diff --git a/lib/braintrust.rb b/lib/braintrust.rb index 3c3913fa..4a8858ec 100644 --- a/lib/braintrust.rb +++ b/lib/braintrust.rb @@ -15,7 +15,7 @@ # @example Initialize with global state # Braintrust.init( # api_key: ENV['BRAINTRUST_API_KEY'], -# project: "my-project" +# default_project: "my-project" # ) # # @example Initialize with explicit state @@ -27,42 +27,31 @@ module Braintrust class Error < StandardError; end # Initialize Braintrust SDK - # Creates a State from config (ENV + options) and optionally sets it as global # - # By default, kicks off an async background login that retries indefinitely. - # Use blocking_login: true to login synchronously before returning. - # - # @param set_global [Boolean] whether to set as global state (default: true) - # @param blocking_login [Boolean] whether to block and login synchronously (default: false, which starts async login) - # @param tracing [Boolean] whether to enable OpenTelemetry tracing (default: true) - # @param tracer_provider [TracerProvider, nil] Optional tracer provider to use instead of creating one # @param api_key [String, nil] Braintrust API key (overrides BRAINTRUST_API_KEY env var) # @param org_name [String, nil] Organization name (overrides BRAINTRUST_ORG_NAME env var) # @param default_project [String, nil] Default project for spans (overrides BRAINTRUST_DEFAULT_PROJECT env var, format: "project_name:my-project" or "project_id:uuid") # @param app_url [String, nil] App URL (overrides BRAINTRUST_APP_URL env var, default: https://www.braintrust.dev) # @param api_url [String, nil] API URL (overrides BRAINTRUST_API_URL env var, default: https://api.braintrust.dev) + # @param set_global [Boolean] Whether to set as global state (default: true) + # @param blocking_login [Boolean] Whether to block and login synchronously (default: false - async background login) + # @param enable_tracing [Boolean] Whether to enable OpenTelemetry tracing (default: true) + # @param tracer_provider [TracerProvider, nil] Optional tracer provider to use instead of creating one # @return [State] the created state - def self.init(set_global: true, blocking_login: false, tracing: true, tracer_provider: nil, **options) - config = Config.from_env(**options) - state = State.new( - api_key: config.api_key, - org_name: config.org_name, - default_project: config.default_project, - app_url: config.app_url, - api_url: config.api_url + def self.init(api_key: nil, org_name: nil, default_project: nil, app_url: nil, api_url: nil, set_global: true, blocking_login: false, enable_tracing: true, tracer_provider: nil) + state = State.from_env( + api_key: api_key, + org_name: org_name, + default_project: default_project, + app_url: app_url, + api_url: api_url, + blocking_login: blocking_login, + enable_tracing: enable_tracing, + tracer_provider: tracer_provider ) State.global = state if set_global - # Login: either blocking (synchronous) or async (background thread with retries) - if blocking_login - state.login - else - state.login_in_thread # Default: async background login - end - - setup_tracing(state, tracer_provider) if tracing - state end @@ -71,40 +60,4 @@ def self.init(set_global: true, blocking_login: false, tracing: true, tracer_pro def self.current_state State.global end - - class << self - private - - # Set up OpenTelemetry tracing with Braintrust - # @param state [State] Braintrust state - # @param explicit_provider [TracerProvider, nil] Optional explicit tracer provider - # @return [void] - def setup_tracing(state, explicit_provider = nil) - require "opentelemetry/sdk" - - if explicit_provider - # Use the explicitly provided tracer provider - # DO NOT set as global - user is managing it themselves - Log.debug("Using explicitly provided OpenTelemetry tracer provider") - tracer_provider = explicit_provider - else - # Check if global tracer provider is already a real TracerProvider - current_provider = OpenTelemetry.tracer_provider - - if current_provider.is_a?(OpenTelemetry::SDK::Trace::TracerProvider) - # Use existing provider - Log.debug("Using existing OpenTelemetry tracer provider") - tracer_provider = current_provider - else - # Create new provider and set as global - tracer_provider = OpenTelemetry::SDK::Trace::TracerProvider.new - OpenTelemetry.tracer_provider = tracer_provider - Log.debug("Created OpenTelemetry tracer provider") - end - end - - # Enable Braintrust tracing (adds span processor) - Trace.enable(tracer_provider, state: state) - end - end end diff --git a/lib/braintrust/config.rb b/lib/braintrust/config.rb index 70d631db..5ab3ca9c 100644 --- a/lib/braintrust/config.rb +++ b/lib/braintrust/config.rb @@ -16,15 +16,20 @@ def initialize(api_key: nil, org_name: nil, default_project: nil, app_url: nil, # Create a Config from environment variables, with option overrides # Passed-in options take priority over ENV vars - def self.from_env(**options) - defaults = { - api_key: ENV["BRAINTRUST_API_KEY"], - org_name: ENV["BRAINTRUST_ORG_NAME"], - default_project: ENV["BRAINTRUST_DEFAULT_PROJECT"], - app_url: ENV["BRAINTRUST_APP_URL"] || "https://www.braintrust.dev", - api_url: ENV["BRAINTRUST_API_URL"] || "https://api.braintrust.dev" - } - new(**defaults.merge(options)) + # @param api_key [String, nil] Braintrust API key (overrides BRAINTRUST_API_KEY env var) + # @param org_name [String, nil] Organization name (overrides BRAINTRUST_ORG_NAME env var) + # @param default_project [String, nil] Default project (overrides BRAINTRUST_DEFAULT_PROJECT env var) + # @param app_url [String, nil] App URL (overrides BRAINTRUST_APP_URL env var) + # @param api_url [String, nil] API URL (overrides BRAINTRUST_API_URL env var) + # @return [Config] the created config + def self.from_env(api_key: nil, org_name: nil, default_project: nil, app_url: nil, api_url: nil) + new( + api_key: api_key || ENV["BRAINTRUST_API_KEY"], + org_name: org_name || ENV["BRAINTRUST_ORG_NAME"], + default_project: default_project || ENV["BRAINTRUST_DEFAULT_PROJECT"], + app_url: app_url || ENV["BRAINTRUST_APP_URL"] || "https://www.braintrust.dev", + api_url: api_url || ENV["BRAINTRUST_API_URL"] || "https://api.braintrust.dev" + ) end end end diff --git a/lib/braintrust/eval.rb b/lib/braintrust/eval.rb index fdc9782b..605652c1 100644 --- a/lib/braintrust/eval.rb +++ b/lib/braintrust/eval.rb @@ -137,6 +137,7 @@ def run_internal(experiment_id:, experiment_name:, project_id:, project_name:, experiment_id: experiment_id, experiment_name: experiment_name, project_id: project_id, + project_name: project_name, permalink: permalink, errors: errors, duration: duration @@ -146,6 +147,7 @@ def run_internal(experiment_id:, experiment_name:, project_id:, project_name:, # Print result summary to stdout # @param result [Result] The evaluation result def print_result(result) + puts "=" * 60 puts result end diff --git a/lib/braintrust/eval/result.rb b/lib/braintrust/eval/result.rb index c140baa6..74af653b 100644 --- a/lib/braintrust/eval/result.rb +++ b/lib/braintrust/eval/result.rb @@ -5,21 +5,23 @@ module Eval # Result represents the outcome of an evaluation run # Contains experiment metadata, errors, and timing information class Result - attr_reader :experiment_id, :experiment_name, :project_id, + attr_reader :experiment_id, :experiment_name, :project_id, :project_name, :permalink, :errors, :duration # Create a new result # @param experiment_id [String] The experiment ID # @param experiment_name [String] The experiment name # @param project_id [String] The project ID + # @param project_name [String] The project name # @param permalink [String] Link to view the experiment in Braintrust UI # @param errors [Array] List of errors that occurred # @param duration [Float] Duration in seconds - def initialize(experiment_id:, experiment_name:, project_id:, + def initialize(experiment_id:, experiment_name:, project_id:, project_name:, permalink:, errors:, duration:) @experiment_id = experiment_id @experiment_name = experiment_name @project_id = project_id + @project_name = project_name @permalink = permalink @errors = errors @duration = duration @@ -42,9 +44,10 @@ def failed? def to_s [ "Experiment: #{experiment_name}", + "Project: #{project_name}", "ID: #{experiment_id}", "Link: #{permalink}", - "Duration: #{duration.round(2)}s", + "Duration: #{duration.round(4)}s", "Errors: #{errors.length}" ].join("\n") end diff --git a/lib/braintrust/state.rb b/lib/braintrust/state.rb index c91c9ab8..60bf964a 100644 --- a/lib/braintrust/state.rb +++ b/lib/braintrust/state.rb @@ -11,7 +11,38 @@ class State @mutex = Mutex.new @global_state = nil - def initialize(api_key: nil, org_name: nil, org_id: nil, default_project: nil, app_url: nil, api_url: nil, proxy_url: nil, logged_in: false) + # Create a State from environment variables with option overrides + # @param api_key [String, nil] Braintrust API key (overrides BRAINTRUST_API_KEY env var) + # @param org_name [String, nil] Organization name (overrides BRAINTRUST_ORG_NAME env var) + # @param default_project [String, nil] Default project (overrides BRAINTRUST_DEFAULT_PROJECT env var) + # @param app_url [String, nil] App URL (overrides BRAINTRUST_APP_URL env var) + # @param api_url [String, nil] API URL (overrides BRAINTRUST_API_URL env var) + # @param blocking_login [Boolean] whether to block and login synchronously (default: false) + # @param enable_tracing [Boolean] whether to enable OpenTelemetry tracing (default: true) + # @param tracer_provider [TracerProvider, nil] Optional tracer provider to use + # @return [State] the created state + def self.from_env(api_key: nil, org_name: nil, default_project: nil, app_url: nil, api_url: nil, blocking_login: false, enable_tracing: true, tracer_provider: nil) + require_relative "config" + config = Config.from_env( + api_key: api_key, + org_name: org_name, + default_project: default_project, + app_url: app_url, + api_url: api_url + ) + new( + api_key: config.api_key, + org_name: config.org_name, + default_project: config.default_project, + app_url: config.app_url, + api_url: config.api_url, + blocking_login: blocking_login, + enable_tracing: enable_tracing, + tracer_provider: tracer_provider + ) + end + + def initialize(api_key: nil, org_name: nil, org_id: nil, default_project: nil, app_url: nil, api_url: nil, proxy_url: nil, blocking_login: false, enable_tracing: true, tracer_provider: nil) # Instance-level mutex for thread-safe login @login_mutex = Mutex.new raise ArgumentError, "api_key is required" if api_key.nil? || api_key.empty? @@ -23,7 +54,20 @@ def initialize(api_key: nil, org_name: nil, org_id: nil, default_project: nil, a @app_url = app_url || "https://www.braintrust.dev" @api_url = api_url @proxy_url = proxy_url - @logged_in = logged_in + @logged_in = false + + # Perform login after state setup + if blocking_login + login + else + login_in_thread + end + + # Setup tracing if requested + if enable_tracing + require_relative "trace" + Trace.setup(self, tracer_provider) + end end # Thread-safe global state getter diff --git a/lib/braintrust/trace.rb b/lib/braintrust/trace.rb index f689da85..9e1ba7d3 100644 --- a/lib/braintrust/trace.rb +++ b/lib/braintrust/trace.rb @@ -15,6 +15,35 @@ module Braintrust module Trace + # Set up OpenTelemetry tracing with Braintrust + # @param state [State] Braintrust state + # @param tracer_provider [TracerProvider, nil] Optional tracer provider + # @return [void] + def self.setup(state, tracer_provider = nil) + if tracer_provider + # Use the explicitly provided tracer provider + # DO NOT set as global - user is managing it themselves + Log.debug("Using explicitly provided OpenTelemetry tracer provider") + else + # Check if global tracer provider is already a real TracerProvider + current_provider = OpenTelemetry.tracer_provider + + if current_provider.is_a?(OpenTelemetry::SDK::Trace::TracerProvider) + # Use existing provider + Log.debug("Using existing OpenTelemetry tracer provider") + tracer_provider = current_provider + else + # Create new provider and set as global + tracer_provider = OpenTelemetry::SDK::Trace::TracerProvider.new + OpenTelemetry.tracer_provider = tracer_provider + Log.debug("Created OpenTelemetry tracer provider") + end + end + + # Enable Braintrust tracing (adds span processor) + enable(tracer_provider, state: state) + end + def self.enable(tracer_provider, state: nil, exporter: nil) state ||= Braintrust.current_state raise Error, "No state available" unless state diff --git a/test/braintrust/eval/result_test.rb b/test/braintrust/eval/result_test.rb index 5437fd04..4b362c51 100644 --- a/test/braintrust/eval/result_test.rb +++ b/test/braintrust/eval/result_test.rb @@ -10,6 +10,7 @@ def test_result_with_success experiment_id: "exp_123", experiment_name: "my-experiment", project_id: "proj_456", + project_name: "my-project", permalink: "https://braintrust.dev/link", errors: [], duration: 1.5 @@ -18,6 +19,7 @@ def test_result_with_success assert_equal "exp_123", result.experiment_id assert_equal "my-experiment", result.experiment_name assert_equal "proj_456", result.project_id + assert_equal "my-project", result.project_name assert_equal "https://braintrust.dev/link", result.permalink assert_equal [], result.errors assert_equal 1.5, result.duration @@ -32,6 +34,7 @@ def test_result_with_errors experiment_id: "exp_123", experiment_name: "my-experiment", project_id: "proj_456", + project_name: "my-project", permalink: "https://braintrust.dev/link", errors: ["Task failed for input 'apple'", "Scorer 'exact_match' failed"], duration: 2.3 @@ -48,6 +51,7 @@ def test_result_to_s_success experiment_id: "exp_123", experiment_name: "food-classifier", project_id: "proj_456", + project_name: "my-project", permalink: "https://braintrust.dev/link", errors: [], duration: 1.234 @@ -56,9 +60,10 @@ def test_result_to_s_success output = result.to_s assert_match(/Experiment: food-classifier/, output) + assert_match(/Project: my-project/, output) assert_match(/ID: exp_123/, output) assert_match(/Link: https:\/\/braintrust.dev\/link/, output) - assert_match(/Duration: 1.23s/, output) # Rounded to 2 decimals + assert_match(/Duration: 1.234/, output) # Rounded to 4 decimals assert_match(/Errors: 0/, output) end @@ -68,6 +73,7 @@ def test_result_to_s_with_errors experiment_id: "exp_123", experiment_name: "food-classifier", project_id: "proj_456", + project_name: "my-project", permalink: "https://braintrust.dev/link", errors: ["Error 1", "Error 2"], duration: 1.234 @@ -76,6 +82,7 @@ def test_result_to_s_with_errors output = result.to_s assert_match(/Experiment: food-classifier/, output) + assert_match(/Project: my-project/, output) assert_match(/ID: exp_123/, output) assert_match(/Errors: 2/, output) # Shows count, not details end diff --git a/test/braintrust/state_login_test.rb b/test/braintrust/state_login_test.rb index ad7484c7..856242b6 100644 --- a/test/braintrust/state_login_test.rb +++ b/test/braintrust/state_login_test.rb @@ -87,13 +87,14 @@ def test_login_in_thread_retries_on_failure def test_login_in_thread_returns_early_if_already_logged_in VCR.use_cassette("auth/login_idempotent") do + # Create state with blocking_login to get logged-in state state = Braintrust::State.new( api_key: @api_key, - app_url: "https://www.braintrust.dev" + app_url: "https://www.braintrust.dev", + blocking_login: true, + enable_tracing: false ) - # Log in first (blocking) - state.login assert state.logged_in # Track if Auth.login is called again diff --git a/test/braintrust/without_openai_test.rb b/test/braintrust/without_openai_test.rb index f34ec4f2..3e0c14a1 100644 --- a/test/braintrust/without_openai_test.rb +++ b/test/braintrust/without_openai_test.rb @@ -20,7 +20,7 @@ def test_core_functionality_without_openai api_key: "test-key", set_global: false, blocking_login: false, - tracing: false + enable_tracing: false ) assert_instance_of Braintrust::State, state diff --git a/test/braintrust_test.rb b/test/braintrust_test.rb index 168e42e9..3415fe6f 100644 --- a/test/braintrust_test.rb +++ b/test/braintrust_test.rb @@ -70,7 +70,7 @@ def test_init_with_tracing_true_creates_tracer_provider # Verify we start with the default proxy provider assert_instance_of OpenTelemetry::Internal::ProxyTracerProvider, OpenTelemetry.tracer_provider - Braintrust.init(set_global: false, api_key: "test-key", tracing: true) + Braintrust.init(set_global: false, api_key: "test-key", enable_tracing: true) # Should have created and set a real TracerProvider assert_instance_of OpenTelemetry::SDK::Trace::TracerProvider, OpenTelemetry.tracer_provider @@ -81,7 +81,7 @@ def test_init_with_tracing_true_uses_existing_provider existing_provider = OpenTelemetry::SDK::Trace::TracerProvider.new OpenTelemetry.tracer_provider = existing_provider - Braintrust.init(set_global: false, api_key: "test-key", tracing: true) + Braintrust.init(set_global: false, api_key: "test-key", enable_tracing: true) # Should reuse the existing provider (same object) assert_same existing_provider, OpenTelemetry.tracer_provider @@ -91,7 +91,7 @@ def test_init_with_tracing_false_skips_tracing # Verify we start with the default proxy provider assert_instance_of OpenTelemetry::Internal::ProxyTracerProvider, OpenTelemetry.tracer_provider - Braintrust.init(set_global: false, api_key: "test-key", tracing: false) + Braintrust.init(set_global: false, api_key: "test-key", enable_tracing: false) # Should still be the proxy provider (no tracing setup) assert_instance_of OpenTelemetry::Internal::ProxyTracerProvider, OpenTelemetry.tracer_provider @@ -109,7 +109,7 @@ def test_init_defaults_to_tracing_enabled end def test_init_with_tracing_adds_span_processor - Braintrust.init(set_global: false, api_key: "test-key", tracing: true) + Braintrust.init(set_global: false, api_key: "test-key", enable_tracing: true) provider = OpenTelemetry.tracer_provider processors = provider.instance_variable_get(:@span_processors) @@ -122,7 +122,7 @@ def test_init_with_explicit_tracer_provider # Create a custom tracer provider custom_provider = OpenTelemetry::SDK::Trace::TracerProvider.new - Braintrust.init(set_global: false, api_key: "test-key", tracing: true, tracer_provider: custom_provider) + Braintrust.init(set_global: false, api_key: "test-key", enable_tracing: true, tracer_provider: custom_provider) # Should NOT set the custom provider as global (user is managing it themselves) refute_same custom_provider, OpenTelemetry.tracer_provider diff --git a/test/fixtures/vcr_cassettes/eval/auto_init.yml b/test/fixtures/vcr_cassettes/eval/auto_init.yml new file mode 100644 index 00000000..172819d5 --- /dev/null +++ b/test/fixtures/vcr_cassettes/eval/auto_init.yml @@ -0,0 +1,4981 @@ +--- +http_interactions: +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-NGM0ZTIyMGYtYjFmNC00NWM0LThiNTItYWI5ZDU0OTNkMTVj'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:47 GMT + Etag: + - '"10a39h4v7gs5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - NGM0ZTIyMGYtYjFmNC00NWM0LThiNTItYWI5ZDU0OTNkMTVj + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::6xs6c-1761408287398-2ec3c35de0a0 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408287.436] + [request_id=iad1::6xs6c-1761408287398-2ec3c35de0a0]' + recorded_at: Sat, 25 Oct 2025 16:04:47 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-YzgyNzk2MTctMWQ4NC00MDcyLWI5MTUtYWNlYjRjMDZhMmI5'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:47 GMT + Etag: + - '"kjql215s1z5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - YzgyNzk2MTctMWQ4NC00MDcyLWI5MTUtYWNlYjRjMDZhMmI5 + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::s8h29-1761408287404-addfbc311180 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408287.447] + [request_id=iad1::s8h29-1761408287404-addfbc311180]' + recorded_at: Sat, 25 Oct 2025 16:04:47 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-MTIwOTc0MmUtNDNlNS00ZmRjLWI2NjctOTUxNmU4Yzc4MzNj'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:47 GMT + Etag: + - '"xobvoylzv65d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - MTIwOTc0MmUtNDNlNS00ZmRjLWI2NjctOTUxNmU4Yzc4MzNj + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::r9pv7-1761408287379-f7a20eb6a4fd + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408287.425] + [request_id=iad1::r9pv7-1761408287379-f7a20eb6a4fd]' + recorded_at: Sat, 25 Oct 2025 16:04:47 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-NzQ4NWIwZTYtMWFlNC00YjBlLThjODMtY2YxMmYxMTVjNDgx'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:47 GMT + Etag: + - '"l73l4atfx25d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - NzQ4NWIwZTYtMWFlNC00YjBlLThjODMtY2YxMmYxMTVjNDgx + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::xfm69-1761408287385-47d9dc52a27f + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408287.433] + [request_id=iad1::xfm69-1761408287385-47d9dc52a27f]' + recorded_at: Sat, 25 Oct 2025 16:04:47 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer explicit-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-OTJjMGIwYzAtMTA5ZC00ODNiLTgwNjUtNjU3ZmZiNGI1OWZh'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:47 GMT + Etag: + - '"x36im3404w5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - OTJjMGIwYzAtMTA5ZC00ODNiLTgwNjUtNjU3ZmZiNGI1OWZh + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::dthj2-1761408287420-8507cd8ed170 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408287.475] + [request_id=iad1::dthj2-1761408287420-8507cd8ed170]' + recorded_at: Sat, 25 Oct 2025 16:04:47 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '192' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-NTMzNjE1N2QtZGY0Zi00MThhLTlhOGItNDhjODRlMmExNjRi'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:47 GMT + Etag: + - '"d9hviqntdy5c"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - NTMzNjE1N2QtZGY0Zi00MThhLTlhOGItNDhjODRlMmExNjRi + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::rgmvd-1761408287426-b6b342a8af06 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408287.48] + [request_id=iad1::rgmvd-1761408287426-b6b342a8af06]' + recorded_at: Sat, 25 Oct 2025 16:04:47 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-ZDE4NjdiODAtZmJiOS00MjU5LThmNTItM2JhNzhhM2U0MmE0'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:47 GMT + Etag: + - '"txzs0zcnun5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - ZDE4NjdiODAtZmJiOS00MjU5LThmNTItM2JhNzhhM2U0MmE0 + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::5f2ww-1761408287428-277b0a60017c + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408287.482] + [request_id=iad1::5f2ww-1761408287428-277b0a60017c]' + recorded_at: Sat, 25 Oct 2025 16:04:47 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-NzczNGY2MzMtYTVmNS00NWIwLWIzMzYtYzRjZjE5NzlhMDMw'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:47 GMT + Etag: + - '"61aaui2ykx5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - NzczNGY2MzMtYTVmNS00NWIwLWIzMzYtYzRjZjE5NzlhMDMw + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::l98w4-1761408287446-15de70534173 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408287.488] + [request_id=iad1::l98w4-1761408287446-15de70534173]' + recorded_at: Sat, 25 Oct 2025 16:04:47 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-Y2RkZTIxZGQtNDU2MC00NGIxLWEyNTEtYjc1ZTBjNWI4MmIx'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:47 GMT + Etag: + - '"kqvmt4a69l5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - Y2RkZTIxZGQtNDU2MC00NGIxLWEyNTEtYjc1ZTBjNWI4MmIx + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::dnw4s-1761408287438-0b4a59f8f34a + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408287.499] + [request_id=iad1::dnw4s-1761408287438-0b4a59f8f34a]' + recorded_at: Sat, 25 Oct 2025 16:04:47 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer + response: + status: + code: 200 + message: OK + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '257' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-ZTAzMDY2MmUtZjdjNy00OTJhLThiZGQtNTgyYTM0OGJmMzIz'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - application/json; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:47 GMT + Etag: + - '"ubzjf1iqqj75"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - ZTAzMDY2MmUtZjdjNy00OTJhLThiZGQtNTgyYTM0OGJmMzIz + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::k25nq-1761408287453-7603588fe079 + body: + encoding: UTF-8 + string: '{"org_info":[{"id":"5ba6d482-b475-4c66-8cd2-5815694764e3","name":"matt-test-org","api_url":"https://api.braintrust.dev","git_metadata":null,"is_universal_api":null,"proxy_url":"https://api.braintrust.dev","realtime_url":"wss://realtime.braintrustapi.com"}]}' + recorded_at: Sat, 25 Oct 2025 16:04:47 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer + response: + status: + code: 200 + message: OK + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '257' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-MzY1NTliNGUtNmRiNy00YjUwLTkyY2ItOTAzNmI1YTE5ZTdj'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - application/json; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:47 GMT + Etag: + - '"ubzjf1iqqj75"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - MzY1NTliNGUtNmRiNy00YjUwLTkyY2ItOTAzNmI1YTE5ZTdj + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::pr8tn-1761408287394-6588e58ac565 + body: + encoding: UTF-8 + string: '{"org_info":[{"id":"5ba6d482-b475-4c66-8cd2-5815694764e3","name":"matt-test-org","api_url":"https://api.braintrust.dev","git_metadata":null,"is_universal_api":null,"proxy_url":"https://api.braintrust.dev","realtime_url":"wss://realtime.braintrustapi.com"}]}' + recorded_at: Sat, 25 Oct 2025 16:04:47 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-MDJjZGNjMDAtMWVmZi00OWQwLWJiN2ItNDIxMjhmOWY5YTcy'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:47 GMT + Etag: + - '"70zd749lyo5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - MDJjZGNjMDAtMWVmZi00OWQwLWJiN2ItNDIxMjhmOWY5YTcy + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::2lxbj-1761408287437-e020c9f5c62e + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408287.599] + [request_id=iad1::2lxbj-1761408287437-e020c9f5c62e]' + recorded_at: Sat, 25 Oct 2025 16:04:47 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-YjIwM2NkZmQtZDcyZS00ZjAxLThmNDktZjg5ZTVhZDQxN2Y5'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:47 GMT + Etag: + - '"x4nn3hg9v95d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - YjIwM2NkZmQtZDcyZS00ZjAxLThmNDktZjg5ZTVhZDQxN2Y5 + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::vsbhz-1761408287628-31ee36bac444 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408287.677] + [request_id=iad1::vsbhz-1761408287628-31ee36bac444]' + recorded_at: Sat, 25 Oct 2025 16:04:47 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-NGRiYjNmNDUtMDE3Yi00YTJkLWFmN2UtMTc4NzBmNzIwZjA0'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:47 GMT + Etag: + - '"b8kxiqads05d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - NGRiYjNmNDUtMDE3Yi00YTJkLWFmN2UtMTc4NzBmNzIwZjA0 + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::qzcxs-1761408287653-e1c52164cd26 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408287.694] + [request_id=iad1::qzcxs-1761408287653-e1c52164cd26]' + recorded_at: Sat, 25 Oct 2025 16:04:47 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-ZDRlZGFkYzYtYWY2Zi00NjcxLTk5Y2ItOTYyYmY5MThkY2Nk'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:47 GMT + Etag: + - '"fz4zc0a3wo5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - ZDRlZGFkYzYtYWY2Zi00NjcxLTk5Y2ItOTYyYmY5MThkY2Nk + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::ljl58-1761408287673-3c26834c3946 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408287.726] + [request_id=iad1::ljl58-1761408287673-3c26834c3946]' + recorded_at: Sat, 25 Oct 2025 16:04:47 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-NTE5NTYyMDQtZWFjNS00YzllLWFhODAtY2E2YTk5YWRkNTVh'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:47 GMT + Etag: + - '"o4tj8lywme5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - NTE5NTYyMDQtZWFjNS00YzllLWFhODAtY2E2YTk5YWRkNTVh + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::2lzwx-1761408287700-cefc2441852e + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408287.748] + [request_id=iad1::2lzwx-1761408287700-cefc2441852e]' + recorded_at: Sat, 25 Oct 2025 16:04:47 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-NzFjMWRjNGMtOTFiYy00OWY1LThjNzQtZTA4M2IzM2ZjODQy'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:47 GMT + Etag: + - '"lt3r7ugd9m5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - NzFjMWRjNGMtOTFiYy00OWY1LThjNzQtZTA4M2IzM2ZjODQy + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::wkfmb-1761408287725-2a488b3999a9 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408287.779] + [request_id=iad1::wkfmb-1761408287725-2a488b3999a9]' + recorded_at: Sat, 25 Oct 2025 16:04:47 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-OWUyYzAwZDQtMGEyNy00NmUyLWEzMjMtODg5MzE4YjY4NGM0'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:47 GMT + Etag: + - '"l7urs4kd4o5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - OWUyYzAwZDQtMGEyNy00NmUyLWEzMjMtODg5MzE4YjY4NGM0 + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::mfzhk-1761408287767-7673222ef3b9 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408287.805] + [request_id=iad1::mfzhk-1761408287767-7673222ef3b9]' + recorded_at: Sat, 25 Oct 2025 16:04:47 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-Y2RhMDQ3ZWYtNTJjYS00Yzg3LWEwY2UtNzZiYjEwZmQ2OTY5'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:47 GMT + Etag: + - '"hjth721faj5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - Y2RhMDQ3ZWYtNTJjYS00Yzg3LWEwY2UtNzZiYjEwZmQ2OTY5 + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::tls4h-1761408287737-756eba8c0a0c + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408287.779] + [request_id=iad1::tls4h-1761408287737-756eba8c0a0c]' + recorded_at: Sat, 25 Oct 2025 16:04:47 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-MmViZDIzNGMtNmMwNC00MmUyLWI0ZjEtZjJmNzdlMGE1ZmRk'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:47 GMT + Etag: + - '"184dv6hc62e5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - MmViZDIzNGMtNmMwNC00MmUyLWI0ZjEtZjJmNzdlMGE1ZmRk + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::7ccdk-1761408287722-95331e1328b2 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408287.776] + [request_id=iad1::7ccdk-1761408287722-95331e1328b2]' + recorded_at: Sat, 25 Oct 2025 16:04:47 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer explicit-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-MWZlOTRhY2YtOGE1NS00MmEzLWEzZGItNGI4YTViYjNhZjMx'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:47 GMT + Etag: + - '"138bkm3iawz5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - MWZlOTRhY2YtOGE1NS00MmEzLWEzZGItNGI4YTViYjNhZjMx + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::wjknd-1761408287744-33ff2007af42 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408287.786] + [request_id=iad1::wjknd-1761408287744-33ff2007af42]' + recorded_at: Sat, 25 Oct 2025 16:04:47 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-MzJlMGQyMWQtYTc5NC00ZWEyLWI5N2QtZWZmNWQ3ODRjYWE0'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:47 GMT + Etag: + - '"8t6xezzdys5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - MzJlMGQyMWQtYTc5NC00ZWEyLWI5N2QtZWZmNWQ3ODRjYWE0 + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::zpnjn-1761408287772-c97a8c69b399 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408287.814] + [request_id=iad1::zpnjn-1761408287772-c97a8c69b399]' + recorded_at: Sat, 25 Oct 2025 16:04:47 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-OTE5YjMxZTctMWZkMS00N2Q0LTllYTMtMzVjYWRmM2I0OTY4'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:47 GMT + Etag: + - '"9751irf4185d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - OTE5YjMxZTctMWZkMS00N2Q0LTllYTMtMzVjYWRmM2I0OTY4 + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::479dk-1761408287861-5223f61cd14d + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408287.998] + [request_id=iad1::479dk-1761408287861-5223f61cd14d]' + recorded_at: Sat, 25 Oct 2025 16:04:47 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-MmNhYTgzYmYtYjU4Ni00MGQ5LTg2MTktODcxYjk3ZmRmNzEw'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:48 GMT + Etag: + - '"dsrk4zn5b45d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - MmNhYTgzYmYtYjU4Ni00MGQ5LTg2MTktODcxYjk3ZmRmNzEw + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::jbgld-1761408287997-f2afbac25954 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408288.048] + [request_id=iad1::jbgld-1761408287997-f2afbac25954]' + recorded_at: Sat, 25 Oct 2025 16:04:47 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '192' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-OWZjOTMxOGMtNjY4OS00NDc4LWJlYjktN2U1YTI0ZDVhZTY2'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:48 GMT + Etag: + - '"qsyieyqkmk5c"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - OWZjOTMxOGMtNjY4OS00NDc4LWJlYjktN2U1YTI0ZDVhZTY2 + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::bjc62-1761408288028-d6e908182ac3 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408288.07] + [request_id=iad1::bjc62-1761408288028-d6e908182ac3]' + recorded_at: Sat, 25 Oct 2025 16:04:47 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-MDBlMDFjZDctNTM0YS00YWZmLWI4OTctMjJlODYyOWQyZmZi'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:48 GMT + Etag: + - '"15yzftygh7o5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - MDBlMDFjZDctNTM0YS00YWZmLWI4OTctMjJlODYyOWQyZmZi + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::r9mrn-1761408288039-8c9ed4c2c6d6 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408288.087] + [request_id=iad1::r9mrn-1761408288039-8c9ed4c2c6d6]' + recorded_at: Sat, 25 Oct 2025 16:04:48 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-NzkyNjk3MGItZWM2ZC00NjNiLTllYzQtZjViNjhiYzVlODJh'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:48 GMT + Etag: + - '"f4y1nsee3l5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - NzkyNjk3MGItZWM2ZC00NjNiLTllYzQtZjViNjhiYzVlODJh + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::xgdhs-1761408288069-6f5bd4a9a29b + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408288.101] + [request_id=iad1::xgdhs-1761408288069-6f5bd4a9a29b]' + recorded_at: Sat, 25 Oct 2025 16:04:48 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-YzU0MjI0ZWQtNWZmYy00YTI3LTk3MmItODIxMDYyZDEzYTdj'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:48 GMT + Etag: + - '"kvhhydb9m85d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - YzU0MjI0ZWQtNWZmYy00YTI3LTk3MmItODIxMDYyZDEzYTdj + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::pmdn8-1761408288091-0d74206708e2 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408288.138] + [request_id=iad1::pmdn8-1761408288091-0d74206708e2]' + recorded_at: Sat, 25 Oct 2025 16:04:48 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer explicit-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-MmY3YTc5NmUtZThjZi00Y2EyLWJkNDEtY2VjYTE2N2NhN2E1'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:48 GMT + Etag: + - '"q30c7j4ve95d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - MmY3YTc5NmUtZThjZi00Y2EyLWJkNDEtY2VjYTE2N2NhN2E1 + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::hnfcv-1761408288132-1f4ed914d8fc + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408288.188] + [request_id=iad1::hnfcv-1761408288132-1f4ed914d8fc]' + recorded_at: Sat, 25 Oct 2025 16:04:48 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-ZTFhNjNkMmYtOWE3My00MGFlLTljMGItODBlMDY0OWEwMWJi'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:48 GMT + Etag: + - '"c3b4qxsbqr5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - ZTFhNjNkMmYtOWE3My00MGFlLTljMGItODBlMDY0OWEwMWJi + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::9nx8s-1761408288117-a704cb3ea00c + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408288.163] + [request_id=iad1::9nx8s-1761408288117-a704cb3ea00c]' + recorded_at: Sat, 25 Oct 2025 16:04:48 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-ZTc5MjE4NDQtMjgwYS00MzQ3LWJmNWYtYWU4Yjg3ZGUwMTBl'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:48 GMT + Etag: + - '"pebjq6994q5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - ZTc5MjE4NDQtMjgwYS00MzQ3LWJmNWYtYWU4Yjg3ZGUwMTBl + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::czkdx-1761408288138-f9b59a8454e9 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408288.187] + [request_id=iad1::czkdx-1761408288138-f9b59a8454e9]' + recorded_at: Sat, 25 Oct 2025 16:04:48 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-YTY5NDU0YzYtMjY1ZC00M2FlLTlhZWYtY2M4OGY1ZmU1NWIz'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:48 GMT + Etag: + - '"zojxgzv8eg5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - YTY5NDU0YzYtMjY1ZC00M2FlLTlhZWYtY2M4OGY1ZmU1NWIz + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::tls4h-1761408288154-5c729e159958 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408288.199] + [request_id=iad1::tls4h-1761408288154-5c729e159958]' + recorded_at: Sat, 25 Oct 2025 16:04:48 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-NTA1ZGM3MmItOTMwNS00MzhmLTk4M2MtMzU4ZmZlMzlhOThh'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:48 GMT + Etag: + - '"dftxwijlza5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - NTA1ZGM3MmItOTMwNS00MzhmLTk4M2MtMzU4ZmZlMzlhOThh + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::cr982-1761408288097-316d54545f6d + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408288.202] + [request_id=iad1::cr982-1761408288097-316d54545f6d]' + recorded_at: Sat, 25 Oct 2025 16:04:48 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-Mzc0ZWExZjgtODQ5MC00ZGEyLTg5NDgtYzdmY2NlZDYzYmVk'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:48 GMT + Etag: + - '"tzld9j4v9w5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - Mzc0ZWExZjgtODQ5MC00ZGEyLTg5NDgtYzdmY2NlZDYzYmVk + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::9wdm8-1761408288316-04cf248c4890 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408288.348] + [request_id=iad1::9wdm8-1761408288316-04cf248c4890]' + recorded_at: Sat, 25 Oct 2025 16:04:48 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-OWUyYTdjYTUtODA0MS00NGJmLWI5NjktNWJlZDg5MTU0YjBh'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:48 GMT + Etag: + - '"d39wy7z1gu5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - OWUyYTdjYTUtODA0MS00NGJmLWI5NjktNWJlZDg5MTU0YjBh + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::wjknd-1761408288517-122a2590cc33 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408288.554] + [request_id=iad1::wjknd-1761408288517-122a2590cc33]' + recorded_at: Sat, 25 Oct 2025 16:04:48 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-OWY3OWQ0NDgtYzAxMi00MTRlLTk1MDEtZThhNjA3ODViYmI3'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:48 GMT + Etag: + - '"wnm4j49gin5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - OWY3OWQ0NDgtYzAxMi00MTRlLTk1MDEtZThhNjA3ODViYmI3 + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::f4dsm-1761408288484-f175b866e4e6 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408288.524] + [request_id=iad1::f4dsm-1761408288484-f175b866e4e6]' + recorded_at: Sat, 25 Oct 2025 16:04:48 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-MDViNTI5NDEtMjVhOC00ZTkyLWJmMGUtMDRjMGI4ZDdkOWVj'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:48 GMT + Etag: + - '"twzf6ynj0m5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - MDViNTI5NDEtMjVhOC00ZTkyLWJmMGUtMDRjMGI4ZDdkOWVj + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::fjcqf-1761408288562-a34ad14b5c05 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408288.615] + [request_id=iad1::fjcqf-1761408288562-a34ad14b5c05]' + recorded_at: Sat, 25 Oct 2025 16:04:48 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-ZTQ2NGUzNTUtY2FjYy00MGNkLThiYmItZWJlZGU3NDVmMGQ2'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:48 GMT + Etag: + - '"jh76ay1ai45d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - ZTQ2NGUzNTUtY2FjYy00MGNkLThiYmItZWJlZGU3NDVmMGQ2 + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::t7mcj-1761408288614-fc28fff0fd3b + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408288.652] + [request_id=iad1::t7mcj-1761408288614-fc28fff0fd3b]' + recorded_at: Sat, 25 Oct 2025 16:04:48 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '192' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-OTE4NTVlMTEtZmY1OC00MDBjLWIxNTEtNmY2N2VlNmUyNTJj'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:48 GMT + Etag: + - '"e8on7yqsk85c"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - OTE4NTVlMTEtZmY1OC00MDBjLWIxNTEtNmY2N2VlNmUyNTJj + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::ngkqz-1761408288585-53f9561899c8 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408288.63] + [request_id=iad1::ngkqz-1761408288585-53f9561899c8]' + recorded_at: Sat, 25 Oct 2025 16:04:48 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-NDZmZWE2ZDctODcwNS00ZDAxLWFmODMtODhjZjhlMmEzZWRk'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:48 GMT + Etag: + - '"x5l73oflwk5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - NDZmZWE2ZDctODcwNS00ZDAxLWFmODMtODhjZjhlMmEzZWRk + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::xtr5w-1761408288624-f0348a21194e + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408288.668] + [request_id=iad1::xtr5w-1761408288624-f0348a21194e]' + recorded_at: Sat, 25 Oct 2025 16:04:48 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-ZWJjYThjNGQtNTYxZS00NDA3LWI3YmMtZmFlYTA0MDM4MzE0'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:48 GMT + Etag: + - '"n7ydqks0xv5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - ZWJjYThjNGQtNTYxZS00NDA3LWI3YmMtZmFlYTA0MDM4MzE0 + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::fh8zw-1761408288624-06ebfe4b4b9e + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408288.674] + [request_id=iad1::fh8zw-1761408288624-06ebfe4b4b9e]' + recorded_at: Sat, 25 Oct 2025 16:04:48 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer explicit-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-MTVkNWM0NzUtNTJmMC00M2NiLTg1MjQtN2Y2MGFiNTdiNDFj'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:48 GMT + Etag: + - '"w0qbrdu0cg5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - MTVkNWM0NzUtNTJmMC00M2NiLTg1MjQtN2Y2MGFiNTdiNDFj + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::994nc-1761408288618-d67258b12658 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408288.688] + [request_id=iad1::994nc-1761408288618-d67258b12658]' + recorded_at: Sat, 25 Oct 2025 16:04:48 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-ODUzYzc5ZWEtNTM3Yi00ZjVmLWFkMTUtNTM3MzliOWYyMWRj'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:48 GMT + Etag: + - '"jmmep3lzw75d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - ODUzYzc5ZWEtNTM3Yi00ZjVmLWFkMTUtNTM3MzliOWYyMWRj + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::kzlgf-1761408288661-aac03a62a8ee + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408288.706] + [request_id=iad1::kzlgf-1761408288661-aac03a62a8ee]' + recorded_at: Sat, 25 Oct 2025 16:04:48 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-NmU5YTVjMDgtYmE4OC00Yjk1LTg2MzktNDEyZDRiNTZiNWQ0'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:48 GMT + Etag: + - '"13scppjrwag5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - NmU5YTVjMDgtYmE4OC00Yjk1LTg2MzktNDEyZDRiNTZiNWQ0 + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::7ccdk-1761408288805-554a964a3059 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408288.855] + [request_id=iad1::7ccdk-1761408288805-554a964a3059]' + recorded_at: Sat, 25 Oct 2025 16:04:48 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-NTkxNmRhYTgtYTE0MS00MDAzLWJlNmMtZjA2MjdkMzA1NTRi'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:49 GMT + Etag: + - '"fddpf5aooi5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - NTkxNmRhYTgtYTE0MS00MDAzLWJlNmMtZjA2MjdkMzA1NTRi + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::q5hf4-1761408289234-516557d53e73 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408289.275] + [request_id=iad1::q5hf4-1761408289234-516557d53e73]' + recorded_at: Sat, 25 Oct 2025 16:04:49 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-NzM3YmJkZmYtYWM1NS00M2FmLWI5YjItNzA2N2M3M2U2YzU4'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:49 GMT + Etag: + - '"1n8rgixg1p5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - NzM3YmJkZmYtYWM1NS00M2FmLWI5YjItNzA2N2M3M2U2YzU4 + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::9hfpp-1761408289245-9a3e4fc20571 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408289.285] + [request_id=iad1::9hfpp-1761408289245-9a3e4fc20571]' + recorded_at: Sat, 25 Oct 2025 16:04:49 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '192' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-Y2VmMzFhNWMtNGY5My00MzI1LThlZDQtZDhhZDczNWEyM2Zj'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:49 GMT + Etag: + - '"izrrotecaf5c"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - Y2VmMzFhNWMtNGY5My00MzI1LThlZDQtZDhhZDczNWEyM2Zj + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::vqgm5-1761408289309-859c16ddafef + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408289.36] + [request_id=iad1::vqgm5-1761408289309-859c16ddafef]' + recorded_at: Sat, 25 Oct 2025 16:04:49 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '192' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-YzBhNDg5YTUtMjU2ZS00MTExLWI5YTctMmQ5MTIwZmVkM2E3'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:49 GMT + Etag: + - '"kz8j27a665c"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - YzBhNDg5YTUtMjU2ZS00MTExLWI5YTctMmQ5MTIwZmVkM2E3 + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::pt8b8-1761408289310-5f2fe6631c1a + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408289.36] + [request_id=iad1::pt8b8-1761408289310-5f2fe6631c1a]' + recorded_at: Sat, 25 Oct 2025 16:04:49 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-OWMwNzM3MWQtNTJjMi00NDliLWEyMWYtOWY1OTExOTQ5YzRm'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:49 GMT + Etag: + - '"j0y8xnsfs95d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - OWMwNzM3MWQtNTJjMi00NDliLWEyMWYtOWY1OTExOTQ5YzRm + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::szlpq-1761408289311-1e6114a91200 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408289.365] + [request_id=iad1::szlpq-1761408289311-1e6114a91200]' + recorded_at: Sat, 25 Oct 2025 16:04:49 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '192' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-OTE1NjQ3OTQtMGUzNC00YmI0LTk1ZjEtOWZhNmUyYjkzYzZk'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:49 GMT + Etag: + - '"15izlyv5mpi5c"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - OTE1NjQ3OTQtMGUzNC00YmI0LTk1ZjEtOWZhNmUyYjkzYzZk + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::pb5ql-1761408289348-63a9ccdbd199 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408289.39] + [request_id=iad1::pb5ql-1761408289348-63a9ccdbd199]' + recorded_at: Sat, 25 Oct 2025 16:04:49 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-MDEwZTU1ODUtNDg1NS00NWVhLTgxYzctMGIxMTBkOWI4MGEy'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:49 GMT + Etag: + - '"16qmcw8fboo5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - MDEwZTU1ODUtNDg1NS00NWVhLTgxYzctMGIxMTBkOWI4MGEy + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::6c7dc-1761408289355-3a747c30fae3 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408289.405] + [request_id=iad1::6c7dc-1761408289355-3a747c30fae3]' + recorded_at: Sat, 25 Oct 2025 16:04:49 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer explicit-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '192' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-YTI5NzgwZTAtOTFjNC00ZjMxLWJiYjctOTliYzU1NTIyZTMz'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:49 GMT + Etag: + - '"16cztlk1g445c"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - YTI5NzgwZTAtOTFjNC00ZjMxLWJiYjctOTliYzU1NTIyZTMz + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::92s2d-1761408289373-5d1521dbacec + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408289.41] + [request_id=iad1::92s2d-1761408289373-5d1521dbacec]' + recorded_at: Sat, 25 Oct 2025 16:04:49 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-ZmRhMDJkMjYtODM4MS00MjVmLTk3ZmItY2QwNjJlYzA4N2U3'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:49 GMT + Etag: + - '"zhqk2u20dc5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - ZmRhMDJkMjYtODM4MS00MjVmLTk3ZmItY2QwNjJlYzA4N2U3 + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::6c7dc-1761408289398-78ce34776ef8 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408289.434] + [request_id=iad1::6c7dc-1761408289398-78ce34776ef8]' + recorded_at: Sat, 25 Oct 2025 16:04:49 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-YzljMzIwMGEtOTgzNC00NDBkLWE4ZDUtNmM3Yjg0OWVlYjIy'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:49 GMT + Etag: + - '"a6xnvzla895d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - YzljMzIwMGEtOTgzNC00NDBkLWE4ZDUtNmM3Yjg0OWVlYjIy + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::vslc2-1761408289586-1337a1689aed + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408289.626] + [request_id=iad1::vslc2-1761408289586-1337a1689aed]' + recorded_at: Sat, 25 Oct 2025 16:04:49 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer + response: + status: + code: 200 + message: OK + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '257' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-NGRiMjMyNTAtZjVhMC00ZDQ1LThlOGYtMzRkMDRjMGMyY2I3'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - application/json; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:49 GMT + Etag: + - '"ubzjf1iqqj75"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - NGRiMjMyNTAtZjVhMC00ZDQ1LThlOGYtMzRkMDRjMGMyY2I3 + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::j8f42-1761408287402-e63ba1dffdde + body: + encoding: UTF-8 + string: '{"org_info":[{"id":"5ba6d482-b475-4c66-8cd2-5815694764e3","name":"matt-test-org","api_url":"https://api.braintrust.dev","git_metadata":null,"is_universal_api":null,"proxy_url":"https://api.braintrust.dev","realtime_url":"wss://realtime.braintrustapi.com"}]}' + recorded_at: Sat, 25 Oct 2025 16:04:49 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '192' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-M2I1MWRjZTUtMmUyYS00MjAxLWIzODgtNGFiZjBmY2Y4ZmQw'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:50 GMT + Etag: + - '"ra8scx99mp5c"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - M2I1MWRjZTUtMmUyYS00MjAxLWIzODgtNGFiZjBmY2Y4ZmQw + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::gxrvn-1761408290510-178425ee9237 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408290.57] + [request_id=iad1::gxrvn-1761408290510-178425ee9237]' + recorded_at: Sat, 25 Oct 2025 16:04:50 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-ZDRkMTM5MDItN2ViZC00NGYxLTk5OTAtMzAxNGQwYTFkN2E0'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:50 GMT + Etag: + - '"h2mp24gdb65d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - ZDRkMTM5MDItN2ViZC00NGYxLTk5OTAtMzAxNGQwYTFkN2E0 + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::7dbgp-1761408290513-cb76b226e0af + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408290.558] + [request_id=iad1::7dbgp-1761408290513-cb76b226e0af]' + recorded_at: Sat, 25 Oct 2025 16:04:50 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-MTcxMzkzMDctNzgwZC00MzE3LWJmYWItNWE1M2ZlZTFjZjY1'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:50 GMT + Etag: + - '"xzm6hy5fl5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - MTcxMzkzMDctNzgwZC00MzE3LWJmYWItNWE1M2ZlZTFjZjY1 + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::79sgv-1761408290552-874f84661869 + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408290.621] + [request_id=iad1::79sgv-1761408290552-874f84661869]' + recorded_at: Sat, 25 Oct 2025 16:04:50 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer test-key + response: + status: + code: 401 + message: Unauthorized + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '193' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-ZmU3ZmI0Y2ItMGY3MC00NjgzLWJmMzAtMTA1YjAwZTBhMWQ2'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - text/plain; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:04:50 GMT + Etag: + - '"ri9n11ew5n5d"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - ZmU3ZmI0Y2ItMGY3MC00NjgzLWJmMzAtMTA1YjAwZTBhMWQ2 + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::6lnpt-1761408290589-ec9969fc843c + body: + encoding: UTF-8 + string: 'Failed to validate Cognito JWT: Error: JWT string does not consist + of exactly 3 parts (header, payload, signature) [timestamp=1761408290.623] + [request_id=iad1::6lnpt-1761408290589-ec9969fc843c]' + recorded_at: Sat, 25 Oct 2025 16:04:50 GMT +- request: + method: post + uri: https://www.braintrust.dev/api/apikey/login + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - www.braintrust.dev + Authorization: + - Bearer + response: + status: + code: 200 + message: OK + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Headers: + - X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, + Content-Type, Date, X-Api-Version + Access-Control-Allow-Methods: + - GET,OPTIONS,PATCH,DELETE,POST,PUT + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - public, max-age=0, must-revalidate + Content-Length: + - '257' + Content-Security-Policy: + - 'script-src ''self'' ''unsafe-eval'' ''wasm-unsafe-eval'' ''strict-dynamic'' + ''nonce-M2Q2MzI1MjEtMWY4Mi00ZDMzLTkxOTUtYTE4NjFmMTg0NDFk'' *.js.stripe.com + js.stripe.com maps.googleapis.com ; style-src ''self'' ''unsafe-inline'' *.braintrust.dev + btcm6qilbbhv4yi1.public.blob.vercel-storage.com fonts.googleapis.com www.gstatic.com; + font-src ''self'' data: fonts.gstatic.com btcm6qilbbhv4yi1.public.blob.vercel-storage.com; + object-src ''none''; base-uri ''self''; form-action ''self''; frame-ancestors + ''self''; worker-src ''self'' blob:; report-uri https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14; + report-to csp-endpoint-0' + Content-Type: + - application/json; charset=utf-8 + Date: + - Sat, 25 Oct 2025 16:07:26 GMT + Etag: + - '"ubzjf1iqqj75"' + Reporting-Endpoints: + - csp-endpoint-0="https://o4507221741076480.ingest.us.sentry.io/api/4507221754380288/security/?sentry_key=27fa5ac907cf7c6ce4a1ab2a03f805b4&sentry_environment=production&sentry_release=14" + Server: + - Vercel + Strict-Transport-Security: + - max-age=63072000 + X-Clerk-Auth-Message: + - Invalid JWT form. A JWT consists of three parts separated by dots. (reason=token-invalid, + token-carrier=header) + X-Clerk-Auth-Reason: + - token-invalid + X-Clerk-Auth-Status: + - signed-out + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Matched-Path: + - "/api/apikey/login" + X-Nonce: + - M2Q2MzI1MjEtMWY4Mi00ZDMzLTkxOTUtYTE4NjFmMTg0NDFk + X-Vercel-Cache: + - MISS + X-Vercel-Id: + - iad1::iad1::p5jdx-1761408446506-3dcb1aeec4c9 + body: + encoding: UTF-8 + string: '{"org_info":[{"id":"5ba6d482-b475-4c66-8cd2-5815694764e3","name":"matt-test-org","api_url":"https://api.braintrust.dev","git_metadata":null,"is_universal_api":null,"proxy_url":"https://api.braintrust.dev","realtime_url":"wss://realtime.braintrustapi.com"}]}' + recorded_at: Sat, 25 Oct 2025 16:07:26 GMT +- request: + method: post + uri: https://api.braintrust.dev/v1/project + body: + encoding: UTF-8 + string: '{"name":"ruby-sdk-test"}' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - api.braintrust.dev + Content-Type: + - application/json + Authorization: + - Bearer + response: + status: + code: 200 + message: OK + headers: + Content-Type: + - application/json; charset=utf-8 + Content-Length: + - '236' + Connection: + - keep-alive + X-Amz-Cf-Pop: + - PHL51-P2 + - PHL51-P3 + Date: + - Sat, 25 Oct 2025 16:07:27 GMT + Access-Control-Allow-Credentials: + - 'true' + X-Amzn-Requestid: + - 6219fe1e-de12-4d46-bbd7-6fc6ff481626 + X-Bt-Internal-Trace-Id: + - 68fcf5be0000000004465ca68e5dc662 + X-Amz-Apigw-Id: + - TAtV5HovIAMEWYw= + Vary: + - Origin, Accept-Encoding + Etag: + - W/"ec-ae+104VIsuTGSnPanxA+Dc4IyRE" + Access-Control-Expose-Headers: + - x-bt-cursor,x-bt-found-existing,x-bt-query-plan + X-Amzn-Trace-Id: + - Root=1-68fcf5be-2f16d19206f5db6d5b0a15b5;Parent=707aeef9485f605d;Sampled=0;Lineage=1:24be3d11:0 + X-Bt-Found-Existing: + - 'true' + Via: + - 1.1 09065f5a7dc17a65496eddf826458682.cloudfront.net (CloudFront), 1.1 208a9f2e1f79b95fcc17a047c4c04e9c.cloudfront.net + (CloudFront) + X-Cache: + - Miss from cloudfront + X-Amz-Cf-Id: + - 6NEBHQA6PZl3_tMYlfibKSXTHS_ldvwp5yLU3qfi70IuTdlMMeallg== + body: + encoding: ASCII-8BIT + string: '{"id":"c532bc50-7094-4bbb-8704-42344c9728b9","org_id":"5ba6d482-b475-4c66-8cd2-5815694764e3","name":"ruby-sdk-test","created":"2025-10-22T02:53:49.779Z","deleted_at":null,"user_id":"855483c6-68f0-4df4-a147-df9b4ea32e0c","settings":null}' + recorded_at: Sat, 25 Oct 2025 16:07:26 GMT +- request: + method: post + uri: https://api.braintrust.dev/v1/experiment + body: + encoding: UTF-8 + string: '{"project_id":"c532bc50-7094-4bbb-8704-42344c9728b9","name":"test-auto-init","ensure_new":true}' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Host: + - api.braintrust.dev + Content-Type: + - application/json + Authorization: + - Bearer + response: + status: + code: 200 + message: OK + headers: + Content-Type: + - application/json; charset=utf-8 + Content-Length: + - '385' + Connection: + - keep-alive + X-Amz-Cf-Pop: + - PHL51-P2 + - PHL51-P3 + Date: + - Sat, 25 Oct 2025 16:07:27 GMT + Access-Control-Allow-Credentials: + - 'true' + X-Amzn-Requestid: + - 7c10ace2-ba9e-4667-bee7-1eed16249c4e + X-Bt-Internal-Trace-Id: + - 68fcf5bf000000001aca104770a45443 + X-Amz-Apigw-Id: + - TAtV7H05IAMEJaQ= + Vary: + - Origin, Accept-Encoding + Etag: + - W/"181-uJXa91vLzWR2qImjzy9xFdgfFHk" + Access-Control-Expose-Headers: + - x-bt-cursor,x-bt-found-existing,x-bt-query-plan + X-Amzn-Trace-Id: + - Root=1-68fcf5bf-3f0494290aee355e4714ed51;Parent=15cde0c101d632b1;Sampled=0;Lineage=1:24be3d11:0 + Via: + - 1.1 edb78a24a403acf9e5a52dc1055fd8c2.cloudfront.net (CloudFront), 1.1 5666ac43d17aeb308a9b45833ddb5b80.cloudfront.net + (CloudFront) + X-Cache: + - Miss from cloudfront + X-Amz-Cf-Id: + - 2DdACCF3UkVzwc0UrfKOEoBGarbcIxcNpUGxVGea4gJX1tg2bvgMkA== + body: + encoding: ASCII-8BIT + string: '{"id":"2f9080a2-368d-403f-8d11-9b8f94ed8153","project_id":"c532bc50-7094-4bbb-8704-42344c9728b9","name":"test-auto-init-e01a8919","description":null,"created":"2025-10-25T16:07:27.302Z","repo_info":{},"commit":null,"base_exp_id":null,"deleted_at":null,"dataset_id":null,"dataset_version":null,"public":false,"user_id":"855483c6-68f0-4df4-a147-df9b4ea32e0c","metadata":null,"tags":null}' + recorded_at: Sat, 25 Oct 2025 16:07:27 GMT +recorded_with: VCR 6.3.1