Commit graph

15 commits

Author SHA1 Message Date
trvon
a8137db76b
feat(control): neutral guest channels, quarantine recovery, capability sealing, local-service proxy
Introduce the framed guest_channel_transport with shared deadlines and
std::jthread ownership, metadata-only retired-schema quarantine with
fail-closed integrity, stateless frozen-catalog validators with
capability pinned to zero, and the generic local-service proxy with
descriptor-pinned endpoints, alias-only guest sockets, audit-gated
delivery, and a Linux managed runtime capability derived only from a
registry-bound operational factory. Sage vocabulary is confined to
src/adapters/sage.
2026-08-30 20:28:41 -06:00
0xkite
09d34002a6
Merge PR #25 (guest channel layer) into PR #24 (wallet stack + Apple repairs)
Combine maintainer/wallet-status-and-apple-repairs (18e75af8) with
maintainer/guest-channel-layer (00d7c473) into a single validated
integration branch for Ghost deployment testing.

Merge resolution decisions:

- Apple container runtime (the known conflict zone) auto-merged
  textually and was verified semantically against both parents:
  the maintainer hard-disable survives (lifecycle_operational()
  returns false unconditionally, apple_container_session_runtime.hpp),
  the sampler/finalizer jthread lifecycle seam and the finalizer
  catch-all well-formed terminal state (a96ab1e) are intact, and
  null_terminated=false strict_json_options is preserved. Velinus's
  observation-intent integration lands adapted on the repaired base:
  prepare_observation_service is only reachable from start(), which
  denies before side effects when the lifecycle is disabled, so the
  observation service never constructs on the disabled Apple path.
  The gated test from PR #25 (every control method refuses before
  side effect; record counts unchanged) survives.
- GLOVE_GUEST_OBSERVATION_* env names kept; observation socket/token
  volumes still mount only when observation_service->active().
- guest_channel layer, host-registered schema admission
  (channel_descriptor/channel_host), SO_PEERCRED/LOCAL_PEERCRED, LRU
  replay cache, bounded retry, fail-closed recovery, and
  channel_identifier_grammar.hpp land as-is; session_registry files
  did not conflict with PR #24's side.
- Wallet status files: PR #25's delta did not touch them, so the
  harness-neutral renames (wallet_status_projection_channel) stand
  unchanged.

Validation (umask 0022): dev/asan/tsan presets build clean and
CTest 80/80 each (control_apple_container_session_runtime
env-gated/skipped as expected); clang-format (llvm@22) applied to
changed sources; git diff --check clean. No push.
2026-08-29 16:23:23 -06:00
0xkite
4a487dafdb
feat(control): generalize the guest specialized-channel layer
Generalizes the PR #23 guest observation plumbing into a schema-agnostic
specialized-channel layer while keeping all harness policy out of core.

Generalized admission (F2/HIGH):
- New channel_descriptor/channel_host interface (include/glove/control/
  guest_channel.hpp): hosts register {channel_id, schema_id,
  body_validator, bounds{max_items, max_body_bytes, max_ttl_ms,
  max_skew_ms}, on_exchange} at registry construction; core keeps only
  structural invariants (identifier charset, digest hex, TTL/skew
  arithmetic, capacity, idempotency) and delegates body semantics to
  registered validators.
- The closed two-schema check in session_registry internals is removed:
  glove_observation_schema, glove_sxxx_proposal_* constants and the
  fixed SXXX digest move out of session_registry_impl.hpp. The Sage
  schemas are now registered by the harness adapter
  (apple_detail::sage_guest_channel_host) and gloved_main wires the host
  into the registry; schema strings appear only in harness-adapter and
  test-fixture registration examples.
- enqueue_observation_intent binds intents to the session's PARSED
  runtime_id; the hardcoded sage_guest_runtime equality checks are
  removed from session_registry.cpp, session_registry_recovery.cpp and
  valid_record_shape. Replay of a now-unregistered schema fails closed
  (open_or_create rejects stores carrying unadmitted intents), and
  enqueue without an admission table is rejected. The observation
  socket server takes runtime_id from configuration instead of
  hardcoding "sage-guest". The observation body hash domain becomes the
  harness-neutral "glove.observation-body.v1" (pre-merge delta; no
  on-disk compatibility is preserved).

Recovery fix (F1/HIGH):
- same_session_snapshot now neutralizes state, running_at_ms and
  policy_revision before comparing frozen intent/disposition snapshots
  against the bound session record, so lifecycle progression and policy
  revision advances never read as a binding crossing; every other
  frozen-field difference still does. Exposed for tests. Regression
  tests cover running->stopping and stopping->exited transitions plus a
  late post-exit disposition end to end (destroy/reopen), and a
  snapshot-identity unit test pins the neutralization (and proves
  non-neutralized fields still cross). Note: an empirical probe showed
  the previously-claimed failure does not reproduce under ordered
  journal replay because intent/disposition records freeze the session
  record they were appended from; the neutralization is applied as the
  defensive fix the memo requires and is now pinned by tests.

Hardening:
- F3: peer-uid verification (SO_PEERCRED / LOCAL_PEERCRED) on observation
  socket accepts, configurable expected uid, rejecting unexpected peers
  before any frame is read.
- F4: the replay cache is a bounded LRU (configurable capacity), so the
  old fixed 1024 cap can no longer permanently kill the channel; the
  durable registry remains the authoritative idempotency layer.
- F5: transient wait/accept errors (EINTR/EAGAIN/ECONNABORTED/EMFILE/
  ENFILE/ENOBUFS/ENOMEM) are retried inside serve_one_for with a bounded
  backoff ladder; only persistent or fatal errors surface. The Apple
  worker loop absorbs persistent failures up to a consecutive-failure
  bound and emits an audit event (new audit action "observation") on
  repeated failures instead of dying on the first hiccup.
- F6: env/mount names generalized to GLOVE_GUEST_OBSERVATION_SOCKET /
  GLOVE_GUEST_OBSERVATION_TOKEN_FILE and the in-container token path to
  /home/agent/.glove-observation-token (Apple runtime, docs).

Apple boundary: the soft lifecycle_operational() definition is unchanged;
the lifecycle-disabled lane now additionally asserts start_session/
stop_session deny with method_not_found and leave the registry untouched
(denial before side effects; the observation service only constructs
inside a lifecycle-gated start).

Docs: architecture.md and session-policy.md describe the guest
specialized-channel admission model and the peer-uid/env naming.

Validation (umask 0022):
- cmake --preset dev/asan/tsan + build + ctest: 100% (76/76) in each
  configuration; asan/tsan are warnings-as-errors builds.
- git diff --check clean; changed files clang-formatted with Homebrew
  llvm@22 against the repo .clang-format.
- No fuzz target exists for the queue/registry (fuzz/ covers plans,
  bundles, manifests, MCP codec, jsonpath only), so no fuzz corpus run.
- control_remote_validation_executor is a pre-existing load-sensitive
  sleep-race test; it flakes identically on the unmodified pr23-head
  baseline under CPU load (verified 1/6 both trees) and always passes
  isolated.

Files: 23 changed (+~1500/-~360), including new guest_channel.{hpp,cpp}.

Signed-off-by: 0xkite <me@hack4kites.dev>
2026-08-29 16:04:27 -06:00
velinussage
05c3571b33 Expose expired observation intents for reconciliation 2026-08-29 01:48:49 -04:00
velinussage
0746fc3fcb Make observation disposition replay durable 2026-08-29 01:36:55 -04:00
velinussage
483400f887 Expose observation intents through host control RPC 2026-08-29 00:51:37 -04:00
0xkite
ad02703151
fix(ci): require complete designated initializers 2026-08-14 15:27:14 -06:00
trvon
afecee2c90
feat(remote): add construction-only backend
Co-authored-by: trvon <git@trevon.dev>
Signed-off-by: trvon <git@trevon.dev>
2026-08-07 22:27:35 -04:00
trvon
825a129fbd
feat(refinement): evaluate fixtures in sandbox
Model and PTY cannot self-report pass or failure. Glove now runs
each refinement-eval-v1 session through a declarative evaluator that
checks bounded fixture assertions (termination cause, exit code, max
latency, required and forbidden transcript literals) against audited
resource events, then binds the evaluated outcome inside the
authenticated receipt digest. Capability advances to version 1 with
the evaluator landed.
2026-07-31 16:07:43 -04:00
trvon
2ab53bcc35
feat(refinement): define evidence protocol 2026-07-31 14:08:28 -04:00
0xkite
497e703e70
feat(runtime): manage sandboxed agent sessions
Keep credentials and network access behind authenticated, audited brokers while binding launch adapters, immutable closures, recovery identities, receipts, and cleanup to the approved plan. Add Apple Container and Linux release lanes without weakening the outer sandbox.
2026-07-30 08:49:42 -04:00
0xkite
67f0acf716
fix(control): implement authenticated health RPC 2026-07-22 13:26:48 -04:00
0xkite
0fe581b028
Add bounded path exposure and retained apply controls 2026-07-20 08:59:38 -04:00
0xkite
176d032723
feat: expose managed session readiness boundary 2026-07-19 22:01:13 -04:00
0xkite
0dafbed1e8
Initial Glove sandbox baseline 2026-07-19 21:06:11 -04:00