Problem
Orb's self-host telemetry collector hand-rolls its own per-instance-secret HMAC anonymization (getOrCreateAnonSecret/hmacField, src/selfhost/orb-collector.ts:63-93) with no reusable module — confirmed no other subsystem imports it as a client library. AMS is about to need the identical pattern (per-instance secret + HMAC'd identifiers) to safely export its own telemetry without leaking identifiable repo/PR data (see the companion issue wiring orb-export.js live). Building AMS's version independently would put two independently-maintained implementations of the same security-sensitive anonymization primitive in the codebase — a divergence between them (weaker hash, reused secret, different field set) would be a real privacy bug, not style debt.
Area
gittensory-engine / shared core
Proposal
Extract Orb's existing per-instance-secret + HMAC-anonymization logic into a new pure, DI-based module in packages/gittensory-engine/src/telemetry/anonymize.ts, following the same "engine computes, product persists" split already used for governor/portfolio-queue. The engine function takes a secret and a raw value and returns the anonymized value — pure, no I/O, no file access. Each product keeps its own local secret storage/generation (paths differ per product), calling into the shared primitive only for the hash itself. Re-wire orb-collector.ts onto the shared primitive with zero behavior change, verified by a regression test asserting identical output pre/post-refactor for the same secret+input.
Deliverables
packages/gittensory-engine/src/telemetry/anonymize.ts — pure hmacAnonymize(secret, value) plus any small pure helpers orb-collector.ts needs, with full engine-package test coverage (node:test)
orb-collector.ts refactored to import and call the shared primitive instead of its inline HMAC code
- Root vitest mirror test (this repo's
gittensory-engine node:test is invisible to Codecov otherwise)
Resources
src/selfhost/orb-collector.ts:63-93 (existing implementation to extract)
packages/gittensory-engine/src/governor/self-plagiarism.ts (recent precedent for this exact engine-side pure-function extraction pattern)
Boundaries
- Extraction and refactor only — must NOT change Orb's anonymization algorithm, secret rotation policy, or opt-out semantics.
- Must NOT touch AMS's
orb-export.js — wiring AMS onto the shared primitive is the separate follow-up issue below, since it also needs its own local-secret storage and network-send logic built first.
Problem
Orb's self-host telemetry collector hand-rolls its own per-instance-secret HMAC anonymization (
getOrCreateAnonSecret/hmacField,src/selfhost/orb-collector.ts:63-93) with no reusable module — confirmed no other subsystem imports it as a client library. AMS is about to need the identical pattern (per-instance secret + HMAC'd identifiers) to safely export its own telemetry without leaking identifiable repo/PR data (see the companion issue wiringorb-export.jslive). Building AMS's version independently would put two independently-maintained implementations of the same security-sensitive anonymization primitive in the codebase — a divergence between them (weaker hash, reused secret, different field set) would be a real privacy bug, not style debt.Area
gittensory-engine / shared core
Proposal
Extract Orb's existing per-instance-secret + HMAC-anonymization logic into a new pure, DI-based module in
packages/gittensory-engine/src/telemetry/anonymize.ts, following the same "engine computes, product persists" split already used for governor/portfolio-queue. The engine function takes a secret and a raw value and returns the anonymized value — pure, no I/O, no file access. Each product keeps its own local secret storage/generation (paths differ per product), calling into the shared primitive only for the hash itself. Re-wireorb-collector.tsonto the shared primitive with zero behavior change, verified by a regression test asserting identical output pre/post-refactor for the same secret+input.Deliverables
packages/gittensory-engine/src/telemetry/anonymize.ts— purehmacAnonymize(secret, value)plus any small pure helpersorb-collector.tsneeds, with full engine-package test coverage (node:test)orb-collector.tsrefactored to import and call the shared primitive instead of its inline HMAC codegittensory-enginenode:test is invisible to Codecov otherwise)Resources
src/selfhost/orb-collector.ts:63-93(existing implementation to extract)packages/gittensory-engine/src/governor/self-plagiarism.ts(recent precedent for this exact engine-side pure-function extraction pattern)Boundaries
orb-export.js— wiring AMS onto the shared primitive is the separate follow-up issue below, since it also needs its own local-secret storage and network-send logic built first.