Feature: LSP runtime path traversal security
  As a security-conscious platform operator
  I want the LSP runtime to reject file paths that escape the workspace
  So that malicious LSP clients cannot read sensitive system files

  # ── _validate_workspace_path unit tests ──────────────────────────

  Scenario: validate_workspace_path accepts a file directly inside workspace
    Given lspsec a workspace root at a temp directory
    And lspsec a file "safe.py" inside the workspace
    When lspsec I call validate_workspace_path with the file inside workspace
    Then lspsec no error should be raised

  Scenario: validate_workspace_path accepts a file in a subdirectory of workspace
    Given lspsec a workspace root at a temp directory
    And lspsec a file "subdir/nested.py" inside the workspace
    When lspsec I call validate_workspace_path with the nested file
    Then lspsec no error should be raised

  Scenario: validate_workspace_path rejects a path outside the workspace
    Given lspsec a workspace root at a temp directory
    When lspsec I call validate_workspace_path with absolute path "/etc/passwd"
    Then lspsec an LspError should be raised with message containing "Path traversal attempt blocked"

  Scenario: validate_workspace_path rejects a path that is a sibling directory
    Given lspsec a workspace root at a temp directory
    And lspsec a sibling directory exists next to the workspace
    When lspsec I call validate_workspace_path with a file in the sibling directory
    Then lspsec an LspError should be raised with message containing "Path traversal attempt blocked"

  Scenario: validate_workspace_path rejects the workspace root itself
    Given lspsec a workspace root at a temp directory
    When lspsec I call validate_workspace_path with the workspace root itself
    Then lspsec an LspError should be raised with message containing "Path traversal attempt blocked"

  # ── _read_file with workspace_root ───────────────────────────────

  Scenario: read_file succeeds for a valid file inside workspace
    Given lspsec a workspace root at a temp directory
    And lspsec a file "hello.py" inside the workspace with content "x = 1"
    When lspsec I call read_file on workspace file "hello.py" with the workspace root
    Then lspsec the file content should be "x = 1"

  Scenario: read_file blocks path traversal via dot-dot segments
    Given lspsec a workspace root at a temp directory
    And lspsec a file "hello.py" inside the workspace with content "x = 1"
    When lspsec I call read_file on a dot-dot traversal path targeting etc-passwd
    Then lspsec an LspError should be raised with message containing "Path traversal attempt blocked"

  Scenario: read_file blocks an absolute path outside the workspace
    Given lspsec a workspace root at a temp directory
    When lspsec I call read_file on absolute path "/etc/hostname" with the workspace root
    Then lspsec an LspError should be raised with message containing "Path traversal attempt blocked"

  Scenario: read_file blocks a symlink that points outside the workspace
    Given lspsec a workspace root at a temp directory
    And lspsec a symlink "evil_link.py" inside the workspace pointing to "/etc/passwd"
    When lspsec I call read_file on the symlink with the workspace root
    Then lspsec an LspError should be raised with message containing "Path traversal attempt blocked"

  Scenario: read_file without workspace_root skips boundary check
    Given lspsec a temp file outside any workspace with content "secret"
    When lspsec I call read_file on the temp file without workspace_root
    Then lspsec the file content should be "secret"

  # ── LspRuntime.get_diagnostics with workspace boundary ───────────

  Scenario: get_diagnostics blocks path traversal when workspace is registered
    Given lspsec an LspRuntime with workspace root at a temp directory
    And lspsec a healthy mock server "local/pyright" registered for the workspace
    When lspsec I try to get diagnostics for "local/pyright" on absolute path "/etc/passwd"
    Then lspsec an LspError should be raised with message containing "Path traversal attempt blocked"

  Scenario: get_diagnostics succeeds for a valid file inside the workspace
    Given lspsec an LspRuntime with workspace root at a temp directory
    And lspsec a healthy mock server "local/pyright" registered for the workspace
    And lspsec a file "main.py" inside the workspace with content "print('hello')"
    When lspsec I get diagnostics for "local/pyright" on workspace file "main.py"
    Then lspsec diagnostics should be returned as a list

  # ── LspRuntime.get_completions with workspace boundary ───────────

  Scenario: get_completions blocks path traversal when workspace is registered
    Given lspsec an LspRuntime with workspace root at a temp directory
    And lspsec a healthy mock server "local/pyright" registered for the workspace
    When lspsec I try to get completions for "local/pyright" on absolute path "/etc/passwd" at line 1 column 1
    Then lspsec an LspError should be raised with message containing "Path traversal attempt blocked"
