ace-hitl 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/.ace-defaults/hitl/config.yml +0 -0
  3. data/.ace-defaults/nav/protocols/skill-sources/ace-hitl.yml +0 -0
  4. data/.ace-defaults/nav/protocols/wfi-sources/ace-hitl.yml +0 -0
  5. data/CHANGELOG.md +21 -0
  6. data/Rakefile +0 -0
  7. data/docs/demo/ace-hitl-scope-and-answer.tape.yml +0 -0
  8. data/docs/demo/fixtures/demo-context.md +0 -0
  9. data/docs/usage.md +8 -2
  10. data/handbook/README.md +0 -0
  11. data/handbook/skills/as-hitl/SKILL.md +0 -0
  12. data/handbook/workflow-instructions/hitl.wf.md +0 -0
  13. data/lib/ace/hitl/atoms/hitl_effect_validator.rb +0 -0
  14. data/lib/ace/hitl/atoms/hitl_file_pattern.rb +0 -0
  15. data/lib/ace/hitl/atoms/hitl_id_formatter.rb +0 -0
  16. data/lib/ace/hitl/cli/commands/create.rb +0 -0
  17. data/lib/ace/hitl/cli/commands/list.rb +0 -0
  18. data/lib/ace/hitl/cli/commands/serve.rb +2 -0
  19. data/lib/ace/hitl/cli/commands/show.rb +0 -0
  20. data/lib/ace/hitl/lifecycle/service.rb +9 -11
  21. data/lib/ace/hitl/lifecycle/store.rb +18 -2
  22. data/lib/ace/hitl/models/hitl_event.rb +0 -0
  23. data/lib/ace/hitl/molecules/hitl_answer_editor.rb +0 -0
  24. data/lib/ace/hitl/molecules/hitl_config_loader.rb +0 -0
  25. data/lib/ace/hitl/molecules/hitl_creator.rb +0 -0
  26. data/lib/ace/hitl/molecules/hitl_display_formatter.rb +0 -0
  27. data/lib/ace/hitl/molecules/hitl_loader.rb +0 -0
  28. data/lib/ace/hitl/molecules/hitl_resolver.rb +0 -0
  29. data/lib/ace/hitl/molecules/hitl_scanner.rb +0 -0
  30. data/lib/ace/hitl/molecules/resume_dispatcher.rb +0 -0
  31. data/lib/ace/hitl/molecules/worktree_scope_resolver.rb +0 -0
  32. data/lib/ace/hitl/version.rb +1 -1
  33. metadata +8 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2e0e3e52b0322d7e5b585bf30728ebaae32337e06b4a8be12e96dcba1c0d498b
4
- data.tar.gz: 4b79e7e2d5efd486c794be95cf515d147b17f322227d3cd6d6583382f3e6fb7e
3
+ metadata.gz: d921414979ccc0569dbfc0c8e102b3aa29c929f5e9ccde725968dc2a7227da9a
4
+ data.tar.gz: fb5c118b0f25a93507602223c5fb7f0751149883c4ead52ab96018d2651e4664
5
5
  SHA512:
6
- metadata.gz: a7abb0c60530c467efbb7a2b99d514e23a716bd61fce8d67c65966d629bb70969785043d63dd36e60eabd1d708d7d850b58eca6b31e5135c071e2791147c3bd7
7
- data.tar.gz: 339b0dee9be68ff3ef82b4de954e6642a58b4ccdf8cad109524b66991423f39f543a59f75e8e957c1be23e263975a3448009a3558aa3e622415059d14ad036bd
6
+ metadata.gz: 67d4f65668300b1c111937e9f0dd11aa4ab11684db06c0cbe65cc2f73d227601985b32734bcd21849e82740a7bf44133fbdeb4bd860c45836e2f8cd541874d25
7
+ data.tar.gz: a7ee80f146804aedf4f7f14d901c6678cee3e8de3d909feb79ef189b5c36a97980a3ce0892760943533907bbce766847848492f3c8e9f8578064ba859261f699
File without changes
File without changes
data/CHANGELOG.md CHANGED
@@ -7,6 +7,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.14.0] - 2026-10-11
11
+
12
+ ### Added
13
+
14
+ - Add `ace-hitl serve --group` so each repository authority can expose its lifecycle socket through a dedicated control group.
15
+
16
+ ### Changed
17
+
18
+ - Direct unsafe socket-directory failures to dedicated service-owned directories that do not contain unrelated service sockets.
19
+ - Apply the configured authority group to root-owned public lifecycle projections as well as the service socket.
20
+
21
+ ### Fixed
22
+
23
+ - Refuse startup if the configured socket group cannot be resolved or assigned, and retag existing public projections to the configured group before serving.
24
+
25
+ ## [0.13.1] - 2026-10-10
26
+
27
+ ### Fixed
28
+
29
+ - Require the published producer and consumer patch versions containing the protected context and managed-attempt APIs; exclude incompatible prior dependency graphs.
30
+
10
31
  ## [0.13.0] - 2026-10-08
11
32
 
12
33
  ### Added
data/Rakefile CHANGED
File without changes
File without changes
File without changes
data/docs/usage.md CHANGED
@@ -170,10 +170,16 @@ document — the same file and traversal trust rules as ace-lab
170
170
 
171
171
  ```bash
172
172
  # Deployment (root runs the service under its own account):
173
- ace-hitl serve # ACE_HITL_SOCKET, ACE_HITL_STORE_ROOT,
174
- # ACE_HITL_GRANTS_PATH override paths
173
+ ace-hitl serve --socket /run/ace-hitl-project/lifecycle.sock \
174
+ --store-root /var/lib/ace-hitl-project --group ace-hitl-project
175
+ # ACE_HITL_SOCKET, ACE_HITL_STORE_ROOT and ACE_HITL_GRANTS_PATH may supply paths.
175
176
  ```
176
177
 
178
+ Give each authority a dedicated service/root-owned, non-world-writable socket
179
+ directory and a dedicated control group. Do not place its socket in `/run/lab`
180
+ or another directory containing unrelated service sockets: granting the
181
+ transport access to that directory's shared group can expose those endpoints.
182
+
177
183
  Store layout (all service-owned): `0711` traverse-only root;
178
184
  `requests/ answers/ secrets/ effects/ locks/ terminals/` are `0700`;
179
185
  `public/` is `0755` with `0440` non-secret projections. There is no
data/handbook/README.md CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -19,6 +19,7 @@ module Ace
19
19
  desc "Run the authenticated HITL store boundary service (peer-credential access)"
20
20
 
21
21
  option :socket, type: :string, desc: "Boundary socket path (default: ACE_HITL_SOCKET or /run/lab/hitl.sock)"
22
+ option :group, type: :string, desc: "Dedicated control group allowed to connect (default: lab-control)"
22
23
  option :store_root, type: :string, desc: "Private store root (default: ACE_HITL_STORE_ROOT or /run/lab/hitl)"
23
24
  option :grants_path, type: :string, desc: "Trusted grants document (default: ACE_HITL_GRANTS_PATH or /etc/lab/ace-lab/authorization.yml)"
24
25
  option :repo_root, type: :string, desc: "Candidate repository for the managed attempt authority"
@@ -41,6 +42,7 @@ module Ace
41
42
  binding: binding_policy,
42
43
  policy: policy,
43
44
  socket_path: socket_path(options),
45
+ group: options[:group] || Lifecycle::Store::DEFAULT_GROUP,
44
46
  logger: options[:verbose] ? ->(message) { warn message } : nil
45
47
  )
46
48
  service.run
File without changes
@@ -139,22 +139,19 @@ module Ace
139
139
 
140
140
  def prepare!
141
141
  begin
142
+ group_id = Etc.getgrnam(@group).gid
142
143
  verify_socket_directory!
143
144
  acquire_endpoint_lock!
144
145
  recover_stale_endpoint!
145
146
  @server = UNIXServer.open(@socket_path)
146
147
  @endpoint_identity = endpoint_identity
148
+ File.chown(nil, group_id, @socket_path)
149
+ File.chmod(DEFAULT_SOCKET_MODE, @socket_path)
150
+ rescue ArgumentError => e
151
+ raise TransportError, "the HITL boundary control group is unavailable (#{e.message})"
147
152
  rescue SystemCallError, IOError => e
148
153
  raise TransportError, "the HITL boundary endpoint is not usable (#{e.class}: #{e.message})"
149
154
  end
150
- File.chmod(DEFAULT_SOCKET_MODE, @socket_path)
151
- begin
152
- File.chown(nil, Etc.getgrnam(@group).gid, @socket_path)
153
- rescue ArgumentError, SystemCallError
154
- # A service that cannot set the control group keeps the
155
- # owner-only socket; the peer-credential gate still applies.
156
- nil
157
- end
158
155
  begin
159
156
  root_store.ensure_layout!
160
157
  rescue SystemCallError => e
@@ -204,7 +201,8 @@ module Ace
204
201
 
205
202
  raise TransportError,
206
203
  "HITL boundary socket directory is not protected: #{dir} " \
207
- "(must be service/root-owned and not world-writable)"
204
+ "(use a dedicated service/root-owned, non-world-writable directory; " \
205
+ "do not share a directory containing unrelated service sockets)"
208
206
  end
209
207
 
210
208
  def authenticate!(socket)
@@ -236,7 +234,7 @@ module Ace
236
234
  policy: @policy,
237
235
  identity: peer,
238
236
  vault: @vault,
239
- proposal_clock: @proposal_clock, stopping: -> { @stopping }
237
+ proposal_clock: @proposal_clock, stopping: -> { @stopping }, group: @group
240
238
  )
241
239
  end
242
240
 
@@ -371,7 +369,7 @@ module Ace
371
369
  end
372
370
 
373
371
  def root_store
374
- Store.new(root: @root, binding: @binding, policy: @policy)
372
+ Store.new(root: @root, binding: @binding, policy: @policy, group: @group)
375
373
  end
376
374
 
377
375
  def log(message)
@@ -79,7 +79,8 @@ module Ace
79
79
 
80
80
  def initialize(root:, binding:, policy: AccessPolicy.new,
81
81
  identity: Identity, ownership: AtomicJson::DEFAULT_OWNERSHIP,
82
- poll_seconds: CONSUME_POLL_SECONDS, vault: :file, proposal_clock: -> { Time.now.utc }, stopping: -> { false })
82
+ poll_seconds: CONSUME_POLL_SECONDS, vault: :file, proposal_clock: -> { Time.now.utc },
83
+ stopping: -> { false }, group: DEFAULT_GROUP)
83
84
  raise ArgumentError, "a binding policy is required (fail closed without one)" unless binding
84
85
  raise ArgumentError, "an access policy is required (fail closed without one)" unless policy
85
86
 
@@ -92,6 +93,7 @@ module Ace
92
93
  @vault = vault == :file ? OtpVault::FileVault : vault
93
94
  @proposal_clock = proposal_clock
94
95
  @stopping = stopping
96
+ @group = group
95
97
  end
96
98
 
97
99
  # ---- requester side ------------------------------------------------
@@ -585,6 +587,7 @@ module Ace
585
587
  FileUtils.mkdir_p(dir)
586
588
  File.chmod(mode, dir)
587
589
  end
590
+ retag_public_projections! if @identity.root?
588
591
  nil
589
592
  end
590
593
 
@@ -1083,7 +1086,20 @@ module Ace
1083
1086
  end
1084
1087
 
1085
1088
  def group_id
1086
- @group_id ||= @identity.group_id(DEFAULT_GROUP)
1089
+ @group_id ||= @identity.group_id(@group)
1090
+ end
1091
+
1092
+ def retag_public_projections!
1093
+ public_dir.children.each do |path|
1094
+ next unless path.basename.to_s.end_with?(".json")
1095
+
1096
+ stat = File.lstat(path)
1097
+ unless stat.file? && !stat.symlink?
1098
+ raise StateError, "public lifecycle projection is not a regular file"
1099
+ end
1100
+ File.chmod(PUBLIC_MODE, path)
1101
+ @ownership.chown(path, AtomicJson::Ownership.new(uid: stat.uid, gid: group_id))
1102
+ end
1087
1103
  end
1088
1104
  end
1089
1105
  end
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Ace
4
4
  module Hitl
5
- VERSION = "0.13.0"
5
+ VERSION = "0.14.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ace-hitl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.0
4
+ version: 0.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michal Czyz
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2026-10-08 00:00:00.000000000 Z
10
+ date: 2026-10-12 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: ace-hitl-contract
@@ -15,14 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: '0.2'
18
+ version: 0.2.1
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - "~>"
24
24
  - !ruby/object:Gem::Version
25
- version: '0.2'
25
+ version: 0.2.1
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: ace-support-core
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -113,28 +113,28 @@ dependencies:
113
113
  requirements:
114
114
  - - "~>"
115
115
  - !ruby/object:Gem::Version
116
- version: '0.66'
116
+ version: '0.67'
117
117
  type: :runtime
118
118
  prerelease: false
119
119
  version_requirements: !ruby/object:Gem::Requirement
120
120
  requirements:
121
121
  - - "~>"
122
122
  - !ruby/object:Gem::Version
123
- version: '0.66'
123
+ version: '0.67'
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: ace-herdr
126
126
  requirement: !ruby/object:Gem::Requirement
127
127
  requirements:
128
128
  - - "~>"
129
129
  - !ruby/object:Gem::Version
130
- version: '0.5'
130
+ version: 0.5.1
131
131
  type: :runtime
132
132
  prerelease: false
133
133
  version_requirements: !ruby/object:Gem::Requirement
134
134
  requirements:
135
135
  - - "~>"
136
136
  - !ruby/object:Gem::Version
137
- version: '0.5'
137
+ version: 0.5.1
138
138
  description: Provides the dedicated ace-hitl package surface for human in the loop
139
139
  (HITL) semantics and CLI workflows.
140
140
  email: