HarperFast / HarperFast/harper-pro
Residency-scoped metadata visibility (generalize LOCAL_ONLY + public API)
- Dominant language
- JavaScript
- Stars
- 3
- Forks
- 0
- Avg merge
- 1d 21h
- Merged PRs (30d)
- 80
Description
## Background
[#331](https://github.com/HarperFast/harper-pro/pull/331) / core [harper#1239](https://github.com/HarperFast/harper/pull/1239) added an **internal** record-metadata bit `LOCAL_ONLY` (persisted-but-never-replicated), used to keep a v4 bridge peer's `hdb_nodes` row off the v5 mesh (#246). That's the degenerate, self-only case of a more general capability worth building deliberately.
## The general model
A record has two replication dimensions:
- **value-residency** — which nodes store the value (today's residency set).
- **metadata-visibility** — which nodes know the record exists.
Today: value→residency set, metadata→**all** nodes. The missing capability is **metadata-visibility scoped to the residency set** (non-resident nodes get nothing — not even the metadata stub). `LOCAL_ONLY` today = residency={self} + metadata-scoped (skip-all). The generalization is residency={B,C,…} + metadata-scoped → skip only peers **not in** the residency set.
Key implementation note: the self-only case is peer-independent (O(1) bitmask, what shipped). The general residency-scoped case is **peer-dependent** — the send path must test `peer ∈ residencySet`. That stays **no-decode**: `residencyId` already rides the metadata header (`HAS_RESIDENCY_ID`, available as `entry.residencyId` on the send path), so it needs only a (cacheable) residencyId→node-set resolution, not a value decode.
## Scope of this follow-up
1. **Per-peer residency-scoped send logic** — for a scoped record, skip a peer iff it's not in the record's residency set (LOCAL_ONLY = the self-residency special case that short-circuits to skip-all).
2. **Public API** (intentionally deferred from #331 so it's designed once, coherently):
- per-record write option (e.g. `put(record, { localOnly: true })` and/or `{ residency: [...], localMetadata: true }`),
- **table-level config** — `replicateMetadataOutsideResidency: false` (or similar) for whole-table localization/sharding/privacy.
3. **GET_RECORD guard** (deferred Low from #331's review): add a `LOCAL_ONLY` bitmask check on the `replicationConnection.ts` GET_RECORD point-lookup path (defense-in-depth; unreachable today since peers only learn keys from the audit stream, which already excludes local-only records).
## Guardrails
- Preserve the **no-decode** property on the send path (residency-set resolution must be cached, not a per-record value decode).
- Don't regress the self-only LOCAL_ONLY behavior already shipped in #331.
Refs #246, #331, harper#1239.
🤖 Filed by Claude Opus 4.7 on Kris's behalf.
Contributor guide
Assessment
This issue has not been assessed yet.