Module: Ace::Hitl::Hermes::Molecules::HermesContract

Defined in:
lib/ace/hitl/hermes/molecules/hermes_contract.rb

Overview

Versioned folder contract constants + folder-level rules (spec 8wm.t.vs1 §§1-5). The plugin implements contract version ace.hitl.hermes.folder/v1; the canonical shared-contract file is settled by A4 (8wm.t.vs2), the lab-config consumer side is 8wm.t.vp9 (separate repository).

Constant Summary collapse

FOLDER_CONTRACT =
"ace.hitl.hermes.folder/v1"
MESSAGE_SCHEMA =
"ace.hitl.hermes.message/v1"
MAX_BYTES =

Content bounds: UTF-8 only, at most 64 KiB per message file.

65_536
FILE_MODE =

Permissions: message files 0640, tmp files 0600 during the atomic write, quarantine directory 0750. No root, ever.

0o640
TMP_MODE =
0o600
QUARANTINE_DIR_MODE =
0o750
MESSAGE_EXT =
".json"
TMP_PREFIX =
".hermes-tmp-"
QUARANTINE_DIR =
".quarantine"
REASON_EXT =
".reason.txt"
TMP_BASENAME_PREFIX =

every tmp file is a dotfile; poll never sees it

"."

Class Method Summary collapse

Class Method Details

.file_name(id) ⇒ Object



56
57
58
# File 'lib/ace/hitl/hermes/molecules/hermes_contract.rb', line 56

def file_name(id)
  "#{Atoms::HermesTokens.validate!(id, "message id")}#{MESSAGE_EXT}"
end

.message_path(folder, id) ⇒ Object



68
69
70
# File 'lib/ace/hitl/hermes/molecules/hermes_contract.rb', line 68

def message_path(folder, id)
  File.join(folder, file_name(id))
end

.parse_file_name(name) ⇒ Object

<token>.json -> id token; anything else is not a message file.



61
62
63
64
65
66
# File 'lib/ace/hitl/hermes/molecules/hermes_contract.rb', line 61

def parse_file_name(name)
  return nil unless name.is_a?(String) && name.end_with?(MESSAGE_EXT)

  id = name.delete_suffix(MESSAGE_EXT)
  Atoms::HermesTokens.valid?(id) ? id : nil
end

.quarantine_path(folder) ⇒ Object



72
73
74
# File 'lib/ace/hitl/hermes/molecules/hermes_contract.rb', line 72

def quarantine_path(folder)
  File.join(folder, QUARANTINE_DIR)
end

.schema_asset_path ⇒ Object

Shipped machine-readable contract artifact (JSON Schema draft-07) for the message envelope v1.



78
79
80
# File 'lib/ace/hitl/hermes/molecules/hermes_contract.rb', line 78

def schema_asset_path
  File.expand_path("../schemas/message.v1.schema.json", __dir__)
end

.verify_folder!(path) ⇒ Object

Fail-closed folder verification before EVERY folder operation: exists, is a directory, writable by the invoking user, and not world-writable.



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/ace/hitl/hermes/molecules/hermes_contract.rb', line 39

def verify_folder!(path)
  unless File.exist?(path)
    raise ContractError, "hermes folder does not exist: #{path}"
  end
  unless File.directory?(path)
    raise ContractError, "hermes folder is not a directory: #{path}"
  end
  unless File.writable?(path)
    raise ContractError, "hermes folder is not writable by the invoking user: #{path}"
  end
  if File.stat(path).mode & 0o002 != 0
    raise ContractError, "hermes folder must not be world-writable: #{path}"
  end

  path
end