Class: RKSeal::Editor

Inherits:
Object
  • Object
show all
Defined in:
lib/rkseal/editor.rb

Overview

Launches the user’s ‘$EDITOR` on a buffer and returns the edited content.

The editor never sees a persistent path: the caller supplies a RAM-backed path from SecureWorkspace, this class seeds it with the initial content, spawns ‘$EDITOR <path>`, blocks until the editor exits, then reads the result back. It does not create, choose, or destroy the path – that is the workspace’s job – which keeps the “never on disk” guarantee in one place.

Constant Summary collapse

ENV_KEYS =

Environment variables consulted, in priority order, to find the editor command when none is injected explicitly.

%w[VISUAL EDITOR].freeze
VIM_HARDENING =

vim-family editors persist buffer contents to files OUTSIDE the RAM-backed path – a swap file and the viminfo register/mark history – which would leak plaintext to persistent disk despite the workspace guarantee. Each flag below suppresses one such sink (‘-n` disables the swap file; `-i NONE` disables viminfo). Keyed by the flag we test for, so an operator who has already set it keeps their choice (we never duplicate it).

{ "-n" => ["-n"], "-i" => ["-i", "NONE"] }.freeze

Instance Method Summary collapse

Constructor Details

#initialize(command: nil) ⇒ Editor

Returns a new instance of Editor.

Parameters:

  • command (String, nil) (defaults to: nil)

    explicit editor command; when nil it is resolved from ENV_KEYS at edit time.



29
30
31
# File 'lib/rkseal/editor.rb', line 29

def initialize(command: nil)
  @command = command
end

Instance Method Details

#edit(content:, path:) ⇒ String

Seed ‘path` with `content`, open it in `$EDITOR`, wait for the editor to exit, and return the (possibly modified) file contents.

Side effects: writes ‘content` to `path` and re-reads it; spawns and waits on the editor process. Does not delete `path`.

Parameters:

  • content (String)

    initial buffer contents (e.g. a seed manifest).

  • path (String)

    RAM-backed file path to edit on (from SecureWorkspace).

Returns:

  • (String)

    the buffer contents after the editor exits.

Raises:

  • (RKSeal::EditorError)

    if no editor is configured, the editor cannot be launched, or it exits signaling the user aborted.



45
46
47
48
49
50
51
52
53
# File 'lib/rkseal/editor.rb', line 45

def edit(content:, path:)
  # Resolve BEFORE writing any secret: if no editor is available we must
  # fail fast, before the plaintext ever lands in the buffer.
  argv = editor_argv

  File.write(path, content)
  launch(argv, path)
  File.read(path)
end

#resolve_commandString

Resolve the editor command that would be used (injected value or the first set variable among ENV_KEYS). Exposed so a flow can fail fast before provisioning a workspace if no editor is available.

Returns:

  • (String)

    the resolved editor command.

Raises:



61
62
63
64
65
66
67
68
69
# File 'lib/rkseal/editor.rb', line 61

def resolve_command
  candidate = @command || env_command
  if candidate.nil? || candidate.strip.empty?
    raise EditorError,
          "no editor configured: set $VISUAL or $EDITOR (e.g. `export EDITOR=vim`)"
  end

  candidate
end