Skip to content

WEB-4809: Go rewrite of unbound-hook (scaffold + shared core + claude-code port)#134

Draft
pugazhendhi-m wants to merge 1 commit into
mainfrom
WEB-4809
Draft

WEB-4809: Go rewrite of unbound-hook (scaffold + shared core + claude-code port)#134
pugazhendhi-m wants to merge 1 commit into
mainfrom
WEB-4809

Conversation

@pugazhendhi-m

Copy link
Copy Markdown
Contributor

Why

Executes E7-2 from WEB-4799: PyInstaller binaries structurally look like packers (bootloader unpacking an embedded interpreter + bytecode at runtime) — the exact pattern EDR behavioral engines hunt. A Go binary is plain statically-linked machine code: it never exhibits the packed-loader behavior, so it clears EDRs without Team-ID allowlist babysitting. Bonus: ~5ms startup vs ~100ms PyInstaller warm.

Does NOT touch the Salesloft PyInstaller v1 rollout — strictly additive (go/ dir + opt-in test param). Ships later as runtime-v2.x.

Linear: WEB-4809

Guiding rule

Mimic exactly what unbound.py / setup.py do. Python is the golden reference; quirks copied verbatim. Parity is CI-enforceable: UNBOUND_GO_BINARY=<path> pytest binary/tests/test_hook_cli.py -k go_binary compares stdout + exit code against python3 <tool>/unbound.py for every tool × event.

What's in this PR

  • go/ module (stdlib-only, zero deps): CLI dispatcher mirroring binary/src/unbound_hookhook <tool> [<event>] | setup | backfill | clear | --version; fail-open dispatch ({"suppressOutput": true} + exit 0 on any fault)
  • Shared core (go/internal/): pyjson (byte-parity json.dumps — separators, ensure_ascii, float repr, ordered keys; verified against real python on edge-case corpora), config, httpc (curl-subprocess, Zscaler house rule), report, audit, locks, transcript — each doc-commented with the python lines it mirrors
  • claude-code hook fully ported: all 6 events incl. policy cache (300s TTL), approval marker/retry + poll phases, discovery + mcp-scan dispatch (local binary only, 4-gate locking, detached Setsid spawn), device-serial/identity cache, account identity
  • selfupdate package stubbed — full python-mimic binary-swap port (2h cadence, .self_update_check/.self_update.lock, managed-location skip) is the next phase
  • go/build.sh: 2× go build + lipo -create universal2 + smoke, mirroring binary/build.sh gates

Verification

  • go test ./... — all packages green; gofmt + go vet clean
  • ./build.sh — universal2 assert + smoke pass
  • Parity: 26/30 green (claude-code 6/6, cursor, copilot; 4 codex cases pending — codex is still a stub)
  • Python suite without env var: 73 passed, 61 skipped — zero regression

Remaining (next phases, tracked in WEB-4809)

  1. codex + cursor + copilot event ports (cursor: exit-2 deny, SQLite identity)
  2. selfupdate full port (binary rename-swap)
  3. setup / migration / backfill / clear
  4. release pipeline build-step swap → runtime-v2.0.0

🤖 Generated with Claude Code

…code port

- go/ module (stdlib-only): CLI dispatcher mirroring binary/src/unbound_hook
  (hook|setup|backfill|clear|--version), fail-open {} semantics preserved
- shared core: pyjson (byte-parity json.dumps), config, httpc (curl subprocess),
  report, audit, locks, transcript — each doc-commented with mirrored python lines
- claude-code hook fully ported: all 6 events, policy cache, approval retry,
  discovery/mcp-scan dispatch (local binary only), device serial, identity
- selfupdate package stubbed (full binary-swap port is next phase)
- build.sh: 2x go build + lipo -create universal2, smoke
- parity harness: opt-in via UNBOUND_GO_BINARY in binary/tests; 26/30 green
  (4 codex cases pending — codex still stub); python suite zero regression

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant