HarperFast / HarperFast/harper
Replication cert lookup misses an IPv6-literal node identity (compact vs OpenSSL-expanded SAN key)
- Dominant language
- JavaScript
- Stars
- 89
- Forks
- 10
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 200
Description
## Summary
When a node's identity is a bare IPv6 **literal** (e.g. `node.hostname: 2001:db8::1`), `getReplicationCert()` cannot find that node's own certificate, because the lookup key and the stored key use different IPv6 spellings.
`security/keys.ts:128` looks the context up by the identity string:
```js
const cert = secureTarget.secureContexts.get(getThisNodeName());
```
`getThisNodeName()` returns the **compact** form (`2001:db8::1`), while `secureContexts` is keyed from certificate SAN text parsed out of the cert, and OpenSSL/X509 renders IPv6 SANs **expanded** (`2001:DB8:0:0:0:0:0:1`; `::1` becomes `0:0:0:0:0:0:0:1`). The two never match, so the `get` returns `undefined`.
## Impact
- `getReplicationCert()` resolves empty for an IPv6-literal identity.
- `reviewSelfSignedCert()` then treats the existing certificate as absent and **regenerates it on every startup**.
- `getReplicationCertAuth()` (`security/keys.ts:139` — `(await getReplicationCert()).options.cert`) can dereference an absent result.
Failure is **silent** in normal logs — the node looks healthy until replication TLS misbehaves — which is what makes it worth tracking rather than leaving as folklore.
Scope is narrow: it needs the node identity to be a bare IPv6 literal. A hostname or IPv4 identity is unaffected.
## Not a regression
This is a **pre-existing** limitation of the cert lookup, not something #2223 introduced. It was surfaced by the cross-model review of [#2223](https://github.com/HarperFast/harper/pull/2223), which makes IPv6-literal identities *viable* (canonicalizing identity to the unbracketed form and bracketing only for URL construction) and therefore reachable. #2223 deliberately scoped this out, since fixing it means changing cert-context keying rather than identity resolution.
## Suggested fix
Canonicalize IP keys **identically on both insertion and lookup** — normalize an IPv6 literal to one canonical form on both sides (e.g. via `net.isIP` + a shared normalizer, cf. `normalizeIPv6` in `resources/analytics/hostnames.ts`) — or locate the replication context by its certificate-record name instead of by SAN text.
Worth adding a generate → parse → `getReplicationCert()` test over an IPv6 identity, since that path currently has no end-to-end coverage.
Contributor guide
Research direction
Start in security/keys.ts around lines 128-139 and compare its lookup key with certificate-context insertion; read normalizeIPv6 in resources/analytics/hostnames.ts as the referenced normalization example. Trace the certificate generate-and-parse path, then add end-to-end coverage showing getReplicationCert() finds an IPv6-literal identity after parsing and that existing hostname and IPv4 lookups remain working.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- node.js, typescript
- Domain
- backend, security
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100