Commit graph

112 commits

Author SHA1 Message Date
0xkite
00d7c47338
refactor(control): sol audit remediations — fail-closed recovery test, cut dead seam hooks, consolidate identifier grammar
Add the fail-closed recovery regression: reopening a store holding
durable observation intents must fail without the registered schema
table — neither a null channel host nor an empty one (no registered
schemas) can admit the frozen intents, so recovery is refused at the
session_registry_impl.hpp channel guard.

Cut speculative generality with no consumer: the channel_descriptor
on_exchange callback and its exchange_hook plumbing in
enqueue_observation_intent return when the wallet-bridge unification
lands; likewise channel_host::catalog() and channel_catalog_entry had
zero callers and no authorized RPC.

Consolidate the identical 128-byte bounded charset identifier and
64-hex digest grammar (previously duplicated in guest_channel.cpp,
session_registry_impl.hpp, and observation_intent_unix_server.cpp)
into src/control/channel_identifier_grammar.hpp without changing
semantics, and document the cached-replay vs registry-replay response
divergence plus that channel_id is registration metadata only
(registry admission matches by schema_id).
2026-08-29 16:15:17 -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
d8b628e066 Document the Sage guest proposal boundary 2026-08-29 13:40:27 -04:00
velinussage
61762c1ce0 Add a closed SXXX proposal envelope 2026-08-29 13:37:15 -04: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
2fa18a2e97 Connect Sage guest observations to managed sessions 2026-08-29 01:32:19 -04:00
velinussage
4385e1b5ee Add per-session guest observation socket 2026-08-29 01:04:55 -04:00
velinussage
483400f887 Expose observation intents through host control RPC 2026-08-29 00:51:37 -04:00
velinussage
5c2d11a82e Add durable Sage observation intent queue 2026-08-29 00:34:21 -04:00
velinussage
4097a21adb Make Apple resource sampling lifecycle safe 2026-08-28 23:17:57 -04:00
velinussage
ca8600a739 Complete Apple managed resource receipts 2026-08-28 22:52:09 -04:00
velinussage
583608c31b fix: close Apple lifecycle review gaps 2026-08-28 21:53:35 -04:00
velinussage
7f2118c325 phase-3 Add read-only Sage guest projection
Bind digest-addressed Sage bundles and immutable guest identity into the constrained Apple Container runtime.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 20:53:11 -04:00
velinussage
a9e659c7a5 phase-2 Fix macOS managed session lifecycle
Enable platform-neutral control dispatch and bind Apple Container projection evidence into authenticated terminal receipts.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 19:43:02 -04:00
0xkite
9ac024866f
Merge pull request #21 from 0xkite/fix/adoption-digest-order
fix(adoption): align snapshot digest ordering
2026-08-23 21:45:22 -06:00
0xkite
3ba6ce46a1
fix(adoption): align snapshot digest ordering
Revalidation walked immutable payloads depth-first while planning hashed a flat lexicographic path sequence. Sort bounded descriptor-safe records before hashing so valid adopted Pi packages retain their canonical identity.
2026-08-23 21:19:23 -06:00
0xkite
4ad346eb8d
Merge pull request #20 from 0xkite/test/managed-client-matrix
test: add managed client adoption matrix
2026-08-23 10:12:00 -06:00
0xkite
d2884cdef9
test: add managed client adoption matrix 2026-08-23 09:18:59 -06:00
0xkite
188ceb481a
Merge pull request #19 from 0xkite/fix/asan-contained-yams-lsan
test: contain synthetic child sanitizer behavior
2026-08-23 09:18:35 -06:00
0xkite
e3efe3bffc
fix(test): isolate contained leak sanitizer 2026-08-23 08:33:33 -06:00
0xkite
37078b0057
Merge pull request #18 from 0xkite/refactor/receipt-audit-handlers
refactor(control): extract receipt handlers
2026-08-15 06:42:23 -06:00
0xkite
41aba6af8f
refactor(control): extract receipt handlers 2026-08-15 05:39:18 -06:00
0xkite
ef1929a2f2
Merge pull request #17 from 0xkite/refactor/receipt-audit-wire
refactor(control): extract receipt wire
2026-08-15 05:32:42 -06:00
0xkite
3743c64a78
refactor(control): extract receipt wire 2026-08-15 04:35:12 -06:00
0xkite
d39c7edd5a
Merge pull request #16 from 0xkite/refactor/cli-policy-wire
refactor(host): extract policy wire
2026-08-15 04:32:24 -06:00
0xkite
119c5e98c3
refactor(host): extract policy wire 2026-08-15 03:30:48 -06:00
0xkite
ae6d11ffbc
Merge pull request #15 from 0xkite/refactor/cli-doctor-wire
refactor(host): extract doctor wire
2026-08-15 03:28:00 -06:00
0xkite
a4f6bcd38b
refactor(host): extract doctor wire 2026-08-15 02:29:54 -06:00
0xkite
6c0e1c5d90
Merge pull request #13 from 0xkite/refactor/runtime-snapshot-engine
refactor(host): extract runtime snapshot engine
2026-08-15 02:25:51 -06:00
0xkite
dd13e928c7
merge: update runtime snapshot branch 2026-08-15 01:23:24 -06:00
0xkite
80548d58a9
Merge pull request #14 from 0xkite/fix/ci-actionlint-version
fix(ci): restore preflight baseline
2026-08-15 01:20:21 -06:00
0xkite
06d6ebb37a
fix(linux): join bridge before closing 2026-08-15 00:21:07 -06:00
0xkite
f1d6a0897e
fix(fuzz): use portable session path 2026-08-14 23:41:43 -06:00
0xkite
43cc02de49
fix(fuzz): resolve runtime ABI library 2026-08-14 22:48:36 -06:00
0xkite
766ad205f4
fix(fuzz): order packaged runtime linkage 2026-08-14 22:07:04 -06:00
0xkite
ac59e58be8
fix(fuzz): retain runtime ABI library 2026-08-14 21:07:38 -06:00
0xkite
0c827bdebc
fix(fuzz): bridge Ubuntu runtime ABI 2026-08-14 20:13:48 -06:00
0xkite
3c538d0fcd
fix(ci): align Linux fuzzer C++ ABI 2026-08-14 19:33:55 -06:00
0xkite
ef7413232c
fix(test): scope leak tracing to parent 2026-08-14 18:40:38 -06:00
0xkite
e0faa4e6bc
fix(ci): isolate namespace test leak tracing 2026-08-14 17:50:56 -06:00
0xkite
fda02033a0
fix(ci): pin compatible macOS fuzzer LLVM 2026-08-14 17:03:08 -06:00
0xkite
a74f814f4f
fix(ci): validate complete fuzzer policies 2026-08-14 16:10:42 -06:00
0xkite
ad02703151
fix(ci): require complete designated initializers 2026-08-14 15:27:14 -06:00
0xkite
22b60726c2
fix(control): initialize validation session state 2026-08-14 14:45:39 -06:00
0xkite
7a141c55a8
ci: deduplicate pull request preflight 2026-08-14 14:17:17 -06:00
0xkite
434d86d9c2
fix(host): seal snapshots after publication 2026-08-14 14:16:33 -06:00
0xkite
79d04f5e9b
fix(control): restore hosted CI portability 2026-08-14 13:26:03 -06:00
0xkite
afa46f901a
style: apply pinned clang-format baseline 2026-08-14 13:20:48 -06:00
0xkite
44e69dbf1a
fix(ci): normalize actionlint version prefix 2026-08-14 13:18:19 -06:00