@hasna/hooks 0.10.3 → 0.10.5

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.
package/README.md CHANGED
@@ -82,6 +82,16 @@ or in-place edits. A missing or unauthenticated Trash client refuses the rewritt
82
82
  operation; it never falls back to raw removal. Configure hosted Trash and verify a
83
83
  disposable capture/restore before relying on recoverable deletion.
84
84
 
85
+ `hooks safety inspect` is a small, read-only installation check. It returns
86
+ compact JSON with the verified Trash path and version, or a fixed failure code
87
+ such as `unsafe_executable`, `unsafe_directory`, `unsafe_manifest` or
88
+ `identity_failed`, and exits nonzero on failure. It checks package identity,
89
+ ownership, permissions and a bounded credential-free protocol probe; it does not
90
+ contact the registry or Trash API. Use it after setup and package upgrades.
91
+ Repair unsafe installation permissions with a verified package installer, then
92
+ check again. This check alone does not prove hosted authentication, native hook
93
+ trust or a running agent's interception.
94
+
85
95
  ## Optional Mementos prompt context
86
96
 
87
97
  `hooks install mementos-context --target codex` registers a native prompt hook.
@@ -300,6 +310,51 @@ store is never a silent default: every client surface either resolves a registry
300
310
  credential (hosted route — no local store is opened) or is told `HASNA_HOOKS_LOCAL=1`
301
311
  (local mode — announced on stderr); with neither it exits non-zero and creates nothing.
302
312
 
313
+ ## Required Sumi safety binding
314
+
315
+ `hooks safety install trash-guard --target sumi` registers the bundled composite
316
+ guard for Sumi's required native adapter. `hooks safety verify --target sumi`
317
+ checks the exact saved supervisor by classifying a synthetic removal without
318
+ creating a file or executing the rewritten command. Both
319
+ commands are credential-free and return compact JSON. Verification explicitly
320
+ reports `nativeAdoptionVerified: false`: a fresh native Sumi tool invocation is
321
+ still required to prove that the installed harness uses this binding.
322
+
323
+ The owner-only `~/.hasna/hooks/native/sumi-trash-guard.json` pins the supervisor's
324
+ runtime, worker, home and PATH. Identical setup is a no-op. An upgrade requires
325
+ `--expected-binding-sha256 <current-digest>` and preserves the previous record.
326
+ An interrupted lock or unexpected current record requires reconciliation; setup
327
+ does not overwrite it. This file is native configuration, not a Hooks app store.
328
+ Setup checks the supervisor's bound PATH before registration; verification checks
329
+ the same readback digest before and after the probe. Package-manager bin file
330
+ symlinks are supported, but symlinked or writable PATH directory ancestry refuses
331
+ instead of hiding an unsafe parent through realpath resolution. The published
332
+ Trash script's Bun interpreter and all preceding PATH directories are checked
333
+ before its identity probe runs; unsafe or unsupported interpreter resolution
334
+ reports `unsafe_interpreter` without executing it.
335
+
336
+ Native adapters import `@hasna/hooks/native-safety` and pass the final shell/patch
337
+ operation to `evaluateNativeSafetyForExecution`, with cancellation and an explicit
338
+ agent label. A rewrite returns the complete command, shell, resolved cwd and
339
+ environment. The adapter must use those fields together, disable environment
340
+ inheritance, and prevent later hooks from changing them. Every rewritten removal
341
+ uses the verified absolute Bun runtime with a clean environment and project
342
+ configuration, env files, macros and installation disabled. Deletions combined
343
+ with shell environment changes are refused; run those removals separately.
344
+
345
+ Use `hooks safety verify --target sumi --execution` for a small, read-only check
346
+ that the saved worker supports this execution contract. A legacy worker that only
347
+ classifies commands cannot pass it. The compatible `evaluateNativeSafety` API and
348
+ verification without `--execution` classify commands only; their success does not
349
+ prove execution compatibility. Neither check runs the returned deletion, creates
350
+ a test file, authenticates Trash or proves native adoption.
351
+
352
+ The bounded agent label can identify the Sumi session in Trash's existing name
353
+ field; it does not invent unsupported harness/session fields. Missing or unhealthy
354
+ bindings reject the call. This covers supported shell removal and whole-file patch
355
+ deletion, not arbitrary filesystem writes or plugin executor replacements.
356
+ Installing the record alone does not activate a harness.
357
+
303
358
  ## Data Directory
304
359
 
305
360
  Data is stored in `~/.hasna/hooks/`.
package/bin/hooks-mcp.js CHANGED
@@ -2781,6 +2781,9 @@ function buildNativeSafetyCommand(binding) {
2781
2781
  return prefix + [encoded, binding.runtime, binding.home, binding.path].map(quote).join(" ");
2782
2782
  }
2783
2783
  function nativeSafetyRegistration(command) {
2784
+ return nativeSafetyCommandBinding(command)?.name;
2785
+ }
2786
+ function nativeSafetyCommandBinding(command) {
2784
2787
  if (!command.startsWith(prefix))
2785
2788
  return;
2786
2789
  const encoded = command.slice(prefix.length).match(/^'([A-Za-z0-9_-]+)' /)?.[1];
@@ -2788,7 +2791,7 @@ function nativeSafetyRegistration(command) {
2788
2791
  return;
2789
2792
  try {
2790
2793
  const binding = JSON.parse(Buffer.from(encoded, "base64url").toString("utf8"));
2791
- return buildNativeSafetyCommand(binding) === command ? binding.name : undefined;
2794
+ return buildNativeSafetyCommand(binding) === command ? binding : undefined;
2792
2795
  } catch {
2793
2796
  return;
2794
2797
  }