instar 1.3.548 → 1.3.549
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/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +112 -0
- package/dist/commands/server.js.map +1 -1
- package/dist/config/ConfigDefaults.d.ts.map +1 -1
- package/dist/config/ConfigDefaults.js +29 -0
- package/dist/config/ConfigDefaults.js.map +1 -1
- package/dist/core/CoherenceJournal.d.ts +1 -1
- package/dist/core/CoherenceJournal.d.ts.map +1 -1
- package/dist/core/CoherenceJournal.js +23 -2
- package/dist/core/CoherenceJournal.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +27 -1
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/TopicOperatorReplicatedStore.d.ts +250 -0
- package/dist/core/TopicOperatorReplicatedStore.d.ts.map +1 -0
- package/dist/core/TopicOperatorReplicatedStore.js +413 -0
- package/dist/core/TopicOperatorReplicatedStore.js.map +1 -0
- package/dist/core/UserRegistryReplicatedStore.d.ts +287 -0
- package/dist/core/UserRegistryReplicatedStore.d.ts.map +1 -0
- package/dist/core/UserRegistryReplicatedStore.js +527 -0
- package/dist/core/UserRegistryReplicatedStore.js.map +1 -0
- package/dist/core/devGatedFeatures.d.ts.map +1 -1
- package/dist/core/devGatedFeatures.js +10 -0
- package/dist/core/devGatedFeatures.js.map +1 -1
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +3 -1
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/users/TopicOperatorStore.d.ts +24 -0
- package/dist/users/TopicOperatorStore.d.ts.map +1 -1
- package/dist/users/TopicOperatorStore.js +28 -0
- package/dist/users/TopicOperatorStore.js.map +1 -1
- package/dist/users/UserManager.d.ts +27 -0
- package/dist/users/UserManager.d.ts.map +1 -1
- package/dist/users/UserManager.js +44 -0
- package/dist/users/UserManager.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +19 -19
- package/src/scaffold/templates.ts +3 -1
- package/upgrades/1.3.549.md +36 -0
- package/upgrades/side-effects/multi-machine-replicated-store-ws26-user-topicop.md +123 -0
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UserRegistryReplicatedStore — the SIXTH concrete consumer of the HLC replicated-store
|
|
3
|
+
* foundation (WS2.6a) and the SECOND PII kind (after WS2.3 relationships). It layers the
|
|
4
|
+
* `user-record` replicated kind onto the generic substrate (ReplicatedRecordEnvelope /
|
|
5
|
+
* UnionReader / ConflictStore / RollbackUnmerge / ReplicationBudget / StoreSnapshot) so that
|
|
6
|
+
* a user the agent knows on machine A is known on machine B — ONE user registry, not
|
|
7
|
+
* one-per-machine.
|
|
8
|
+
*
|
|
9
|
+
* It is the literal analog of `RelationshipsReplicatedStore.ts` (the WS2.3 PII reference
|
|
10
|
+
* consumer): a UserProfile is a registered principal (the multi-user identity the
|
|
11
|
+
* UserManager resolves an inbound message to), so it carries directly-identifying PII and
|
|
12
|
+
* REUSES the WS2.3 PII machinery (type-clamp, disclosure-min projection, channel-set
|
|
13
|
+
* recordKey, tombstones, flag-coherence) rather than reinventing or downgrading it. THIS IS
|
|
14
|
+
* PURE LOGIC. No fs, no Date directly, no network. It defines:
|
|
15
|
+
*
|
|
16
|
+
* A. The `user-record` store schema — a STRICT typed validator that TYPE-CLAMPS every
|
|
17
|
+
* known field (`createdAt` ISO-8601-or-absent, `telegramUserId` a finite number,
|
|
18
|
+
* `channels[]`/`permissions[]`/free text length-bounded + jailed). The schema is a
|
|
19
|
+
* DISCRIMINATED UNION on `op` — an `op:'put'` VALUE schema AND an `op:'delete'`
|
|
20
|
+
* TOMBSTONE schema coexist under the one kind, so a tombstone is never marked invalid
|
|
21
|
+
* by the value schema.
|
|
22
|
+
*
|
|
23
|
+
* B. The disclosure-minimized PROJECTION — `buildUserRecordData` emits ONLY the enumerated
|
|
24
|
+
* resolution + merge-relevant fields, NEVER the raw on-disk blob and NEVER the local
|
|
25
|
+
* `userId` `id`. `recordKey` is the cross-machine IDENTITY SURFACE, derived
|
|
26
|
+
* deterministically from the SORTED channel-set ("type:identifier" pairs) — the SAME
|
|
27
|
+
* identity model as relationships (a user IS their channel identifiers, mirroring
|
|
28
|
+
* UserManager.channelIndex) — never the per-machine `userId` (VM-A and VM-B mint
|
|
29
|
+
* different ids for the same human; a UUID-keyed record could never collide them).
|
|
30
|
+
*
|
|
31
|
+
* C. The TOMBSTONE builder — `buildUserTombstoneData` emits an `op:'delete'` record
|
|
32
|
+
* `{ recordKey, op, hlc, origin, deletedAt }` so a removeUser propagates as a positive
|
|
33
|
+
* signal across an offline-then-rejoining peer instead of a record absence. CRITICAL:
|
|
34
|
+
* the UserManager.removeUser() path MUST emit a tombstone, else a peer re-replicates the
|
|
35
|
+
* locally-removed user forever (resurrection).
|
|
36
|
+
*
|
|
37
|
+
* D. The union-aware read — `mergeUnionToUsers` collapses a `Map<recordKey, UnionResult>`
|
|
38
|
+
* into the merged user view. Users are HIGH-impact at the REPLICATION layer (a concurrent
|
|
39
|
+
* divergent edit to the SAME channel-set identity goes through APPEND-BOTH-AND-FLAG —
|
|
40
|
+
* both versions surface, never a silent clobber; auto-merging two divergent profiles
|
|
41
|
+
* could fuse two distinct humans). The CONSUMER READ path is ADVISORY: a replicated user
|
|
42
|
+
* record is a HINT about what my OTHER machines know — NEVER my authoritative answer to
|
|
43
|
+
* "who is this inbound sender?" (identity RESOLUTION of an inbound principal is
|
|
44
|
+
* LOCAL-ONLY, mirroring REQ-M14 — the local channelIndex is always authoritative). The
|
|
45
|
+
* read NEVER writes a foreign record into the local store.
|
|
46
|
+
*
|
|
47
|
+
* E. Foreign-record render safety — `renderForeignUserContext` wraps a replicated record in
|
|
48
|
+
* an explicit `<replicated-untrusted-data origin="…">` envelope and sanitizes EVERY
|
|
49
|
+
* rendered field. There is no "trusted because machine-set" render slot for a foreign
|
|
50
|
+
* record.
|
|
51
|
+
*
|
|
52
|
+
* DECIDED FORKS (build prompt, recorded verbatim in the PR ELI16):
|
|
53
|
+
* 1. recordKey = sha256 of the SORTED channel-set ("type:identifier" pairs), NEVER the
|
|
54
|
+
* local `userId` (cross-machine identity surface — see deriveUserRecordKey).
|
|
55
|
+
* 2. Impact tier = HIGH at the REPLICATION layer (append-both-and-flag), ADVISORY at the
|
|
56
|
+
* READ layer (a replicated user is a hint, never the authoritative inbound-resolution).
|
|
57
|
+
* 3. disclosure-min: strip the local `userId` — a peer's local id is meaningless + a mild
|
|
58
|
+
* correlation leak; the channel-set IS the cross-machine identity.
|
|
59
|
+
*
|
|
60
|
+
* SAFETY POSTURE: MECHANISM, dark by default. Nothing here blocks a user-initiated action.
|
|
61
|
+
* The local `userId` is NEVER part of the replicated schema and is stripped from every emitted
|
|
62
|
+
* projection (disclosure minimization).
|
|
63
|
+
*/
|
|
64
|
+
import type { UserProfile, UserChannel } from './types.js';
|
|
65
|
+
import type { StoreFieldSchema, ReplicatedEnvelope } from './ReplicatedRecordEnvelope.js';
|
|
66
|
+
import type { ImpactTier, OriginRecord, UnionResult } from './UnionReader.js';
|
|
67
|
+
import type { ReplicatedKindBounds } from './ReplicationBudget.js';
|
|
68
|
+
import type { HlcTimestamp } from './HybridLogicalClock.js';
|
|
69
|
+
/** The stateSync config sub-key + advert suffix for this store (e.g.
|
|
70
|
+
* `multiMachine.stateSync.userRegistry.enabled`). Equal to the advert flag key
|
|
71
|
+
* `stateSyncReceive['userRegistry']`. */
|
|
72
|
+
export declare const USER_STORE_KEY = "userRegistry";
|
|
73
|
+
/** The JournalKind string this store rides — the DUAL-REGISTRY's dynamic half.
|
|
74
|
+
* MUST also be present in CoherenceJournal.JOURNAL_KINDS (the static half), or the
|
|
75
|
+
* store advertises receive=true yet serves/applies/pulls nothing. */
|
|
76
|
+
export declare const USER_RECORD_KIND = "user-record";
|
|
77
|
+
/**
|
|
78
|
+
* Users are HIGH-impact at the REPLICATION layer (fork #2): a concurrent divergent VALUE
|
|
79
|
+
* edit to the SAME channel-set identity surface from different origins goes through
|
|
80
|
+
* APPEND-BOTH-AND-FLAG — both versions preserved, ONE deduped conflict, never a silent
|
|
81
|
+
* overwrite (auto-merging two divergent profiles could fuse two distinct humans). The READ
|
|
82
|
+
* path (mergeUnionToUsers) is ADVISORY — a replicated user record is a HINT about what my
|
|
83
|
+
* OTHER machines know, NEVER my authoritative answer to "who is this inbound sender?".
|
|
84
|
+
*/
|
|
85
|
+
export declare const USER_IMPACT_TIER: ImpactTier;
|
|
86
|
+
/** Mirrors a reasonable per-user channel count (UserManager has no hard cap; this bounds a
|
|
87
|
+
* hostile peer's flood). */
|
|
88
|
+
export declare const MAX_CHANNELS = 50;
|
|
89
|
+
/** Per-free-text-string clamp for name / each channel identifier / each permission / each
|
|
90
|
+
* free-text profile field. */
|
|
91
|
+
export declare const MAX_FREETEXT_LENGTH = 2000;
|
|
92
|
+
/** A channel `type` / permission is a short slug. */
|
|
93
|
+
export declare const MAX_SLUG_LENGTH = 128;
|
|
94
|
+
/** Permissions cap. */
|
|
95
|
+
export declare const MAX_PERMISSIONS = 50;
|
|
96
|
+
/**
|
|
97
|
+
* Per-kind replication bounds. The user registry is FEW + bounded (a handful of registered
|
|
98
|
+
* principals), so the per-store retention mirrors the pref-record / learning-record siblings
|
|
99
|
+
* (a small window with a few archives). NEVER `rotateKeep: 0` (rotate-but-never-delete would
|
|
100
|
+
* be a compliance defect for any PII kind, REQ-D1). The rate cap COALESCES (latest state per
|
|
101
|
+
* recordKey per interval) so a churny upsert loop does not flood the stream.
|
|
102
|
+
*/
|
|
103
|
+
export declare const USER_RECORD_BOUNDS: ReplicatedKindBounds;
|
|
104
|
+
/**
|
|
105
|
+
* Per-entry size cap RAISED to 64KB for this PII kind. The default
|
|
106
|
+
* APPLIER_MAX_ENTRY_BYTES = 8KB could be smaller than a fat profile (many channels + a long
|
|
107
|
+
* bio), so under it the highest-PII records would never replicate AND would wedge the stream.
|
|
108
|
+
* 64KB is provably above the disclosure-minimized projection's maximum (50 channels ×
|
|
109
|
+
* (128 + 2000) ≈ 106KB worst-case shows why we additionally enforce a HARD post-projection
|
|
110
|
+
* ceiling): a record that STILL exceeds 64KB after projection is REJECTED with a named error
|
|
111
|
+
* (never silent-truncate, never suspect-wedge). See assertProjectionUnderCap.
|
|
112
|
+
*/
|
|
113
|
+
export declare const USER_MAX_ENTRY_BYTES: number;
|
|
114
|
+
/**
|
|
115
|
+
* The store-specific field names the `user-record` VALUE schema OWNS (the unknown-field
|
|
116
|
+
* counter's allowlist). The local `userId` `id` is DELIBERATELY ABSENT — it is per-machine
|
|
117
|
+
* and never replicated (fork #1/#3: the recordKey keys on the channel-set identity surface,
|
|
118
|
+
* not the id). `recordKey`/`hlc`/`op`/`origin`/`observed` are reserved envelope fields, never
|
|
119
|
+
* store fields.
|
|
120
|
+
*/
|
|
121
|
+
export declare const USER_STORE_KNOWN_FIELDS: ReadonlyArray<string>;
|
|
122
|
+
/** The tombstone's store-owned fields beyond the reserved envelope set. `deletedAt`
|
|
123
|
+
* is the only store field a delete carries. */
|
|
124
|
+
export declare const USER_TOMBSTONE_KNOWN_FIELDS: ReadonlyArray<string>;
|
|
125
|
+
/** Is `v` a valid ISO-8601 date string (and ONLY a date — no smuggled markup)? A string
|
|
126
|
+
* Date.parse rejects, or that contains an injection char (`<`, `>`, `"`), is not a clean ISO
|
|
127
|
+
* date. */
|
|
128
|
+
export declare function isIso8601(v: unknown): v is string;
|
|
129
|
+
/**
|
|
130
|
+
* The `user-record` store schema — a DISCRIMINATED UNION on `op`. Strict typed validation on
|
|
131
|
+
* top of the envelope: reject free text beyond the known fields, TYPE-CLAMP every known field
|
|
132
|
+
* (createdAt ISO-8601, telegramUserId finite number, channels/permissions/free text
|
|
133
|
+
* length-clamped + jailed) so markup cannot smuggle through a render slot that bypasses
|
|
134
|
+
* sanitize(). Returns the validated store-specific object (known fields only), or null to
|
|
135
|
+
* reject the WHOLE record. PURE (no I/O, no mutation of `raw`).
|
|
136
|
+
*
|
|
137
|
+
* The envelope validator has ALREADY validated `op` ∈ {put,delete} before calling this. We
|
|
138
|
+
* branch on it so a tombstone `{recordKey, op:'delete', hlc, origin, deletedAt}` passes (only
|
|
139
|
+
* `deletedAt` is a legal store field for a delete) WITHOUT being marked invalid by the rich
|
|
140
|
+
* VALUE schema.
|
|
141
|
+
*/
|
|
142
|
+
export declare const userRecordStoreSchema: StoreFieldSchema;
|
|
143
|
+
/**
|
|
144
|
+
* Normalize one channel into its stable uid form `type:identifier` (lowercased type, trimmed
|
|
145
|
+
* identifier). This is the SAME `${type}:${identifier}` key UserManager.channelIndex uses to
|
|
146
|
+
* resolve a user across platforms.
|
|
147
|
+
*/
|
|
148
|
+
export declare function channelUid(channel: UserChannel): string;
|
|
149
|
+
/**
|
|
150
|
+
* Derive the cross-machine-stable recordKey for a user (fork #1). A user is "the same" across
|
|
151
|
+
* machines by their CHANNEL SET (mirroring UserManager.channelIndex), NOT by the per-machine
|
|
152
|
+
* `userId` — VM-A and VM-B mint different ids for the same human, so an id-keyed record could
|
|
153
|
+
* never collide them (exactly the relationship-UUID trap WS2.3 solved with the channel-set
|
|
154
|
+
* key).
|
|
155
|
+
*
|
|
156
|
+
* The key is a deterministic, collision-resistant hash of the SORTED, de-duplicated
|
|
157
|
+
* channel-uids: `sha256(sorted(channelUids).join('\n'))`, hex-truncated to 32 chars (the same
|
|
158
|
+
* shape UnionReader.conflictId uses). Sorting makes it order-independent (the two machines
|
|
159
|
+
* converge to the SAME key for the same channel set); the hash makes it a bounded,
|
|
160
|
+
* non-path-shaped string (the envelope's recordKey jail accepts it). A user with NO channels
|
|
161
|
+
* (a degenerate local-only record) is NOT replicable — it has no cross-machine identity
|
|
162
|
+
* surface — and is reported as null so the caller skips emission (it can never collide a
|
|
163
|
+
* stranger by an empty key).
|
|
164
|
+
*
|
|
165
|
+
* COLLISION SAFETY: two DIFFERENT users share a key ONLY if they share the EXACT same full
|
|
166
|
+
* channel set — which IS the UserManager's own definition of "the same user" (the channelIndex
|
|
167
|
+
* maps one user per channel-uid and refuses a cross-user collision). SPLIT-IDENTITY SAFETY: the
|
|
168
|
+
* same user derives the SAME key on both machines IFF both hold the same channel set; when the
|
|
169
|
+
* sets differ (one machine learned an extra channel) the keys differ — correct (they are not
|
|
170
|
+
* yet provably the same user on the machine missing the channel).
|
|
171
|
+
*/
|
|
172
|
+
export declare function deriveUserRecordKey(channels: ReadonlyArray<UserChannel>): string | null;
|
|
173
|
+
/** The `data` object a `user-record` journal entry carries. */
|
|
174
|
+
export type UserRecordData = Record<string, unknown>;
|
|
175
|
+
/** Input to buildUserRecordData: the record to emit, the freshly-ticked hlc, this machine's
|
|
176
|
+
* origin id, and the observed-witness (the hlc already merged for THIS recordKey before
|
|
177
|
+
* writing, or absent). */
|
|
178
|
+
export interface BuildUserRecordInput {
|
|
179
|
+
record: UserProfile;
|
|
180
|
+
hlc: HlcTimestamp;
|
|
181
|
+
origin: string;
|
|
182
|
+
observed?: HlcTimestamp;
|
|
183
|
+
}
|
|
184
|
+
/** The named error a record-over-cap surfaces: not silent-truncate, not suspect-wedge. */
|
|
185
|
+
export declare class UserRecordTooLargeError extends Error {
|
|
186
|
+
readonly recordKey: string;
|
|
187
|
+
readonly bytes: number;
|
|
188
|
+
constructor(recordKey: string, bytes: number);
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Build the disclosure-minimized `user-record` envelope `data` for an `op:'put'` (fork #3).
|
|
192
|
+
* Emits ONLY the enumerated resolution + merge-relevant fields — NEVER the raw on-disk blob,
|
|
193
|
+
* NEVER the local `userId` id. recordKey = the derived channel-set identity surface (fork #1).
|
|
194
|
+
*
|
|
195
|
+
* Returns null when the record has NO channels (no cross-machine identity surface ⇒ not
|
|
196
|
+
* replicable — the caller skips emission). Throws UserRecordTooLargeError when the projection
|
|
197
|
+
* STILL exceeds the 64KB per-entry cap (a NAMED, surfaced rejection — never silent-truncate).
|
|
198
|
+
*/
|
|
199
|
+
export declare function buildUserRecordData(input: BuildUserRecordInput): UserRecordData | null;
|
|
200
|
+
/** Throw UserRecordTooLargeError if the projected data serializes over the per-entry cap. The
|
|
201
|
+
* cap is set so a legal disclosure-minimized record can never reach it; this is the
|
|
202
|
+
* belt-and-suspenders named rejection. */
|
|
203
|
+
export declare function assertProjectionUnderCap(recordKey: string, data: UserRecordData): void;
|
|
204
|
+
/** Input to buildUserTombstoneData: the channel set of the deleted user (to derive the
|
|
205
|
+
* recordKey identity surface), the freshly-ticked hlc, the origin, and the deletedAt
|
|
206
|
+
* timestamp. */
|
|
207
|
+
export interface BuildUserTombstoneInput {
|
|
208
|
+
channels: ReadonlyArray<UserChannel>;
|
|
209
|
+
hlc: HlcTimestamp;
|
|
210
|
+
origin: string;
|
|
211
|
+
deletedAt: string;
|
|
212
|
+
observed?: HlcTimestamp;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Build an `op:'delete'` TOMBSTONE `data` for a user removal. recordKey = the SAME channel-set
|
|
216
|
+
* identity surface the value records key on, so the tombstone reaches the same human's record
|
|
217
|
+
* on every machine even though the local ids differ. Returns null when the user has no channels
|
|
218
|
+
* (no identity surface to tombstone).
|
|
219
|
+
*
|
|
220
|
+
* CRITICAL: the UserManager.removeUser() path MUST call this, else a peer re-replicates the
|
|
221
|
+
* locally-removed user forever (resurrection). The delete-resurrection guard lives in the merge
|
|
222
|
+
* (a later `delete` hlc wins over an earlier `put`).
|
|
223
|
+
*/
|
|
224
|
+
export declare function buildUserTombstoneData(input: BuildUserTombstoneInput): UserRecordData | null;
|
|
225
|
+
/** A merged user view entry: the projected record fields PLUS its origin machine id (so a
|
|
226
|
+
* foreign record is rendered inside the untrusted-data envelope). READ-ONLY — NEVER written
|
|
227
|
+
* back into the local store. */
|
|
228
|
+
export interface MergedUserView {
|
|
229
|
+
recordKey: string;
|
|
230
|
+
origin: string;
|
|
231
|
+
/** The validated, type-clamped projection fields (the receive-side schema already ran on
|
|
232
|
+
* apply; here `data` is that validated portion). */
|
|
233
|
+
data: Record<string, unknown>;
|
|
234
|
+
/** True when this view entry is one of ≥2 concurrent variants of an OPEN conflict
|
|
235
|
+
* (append-both — both surface; the read NEVER suppresses a usable view AND NEVER blocks on
|
|
236
|
+
* the unresolved conflict). */
|
|
237
|
+
conflicted: boolean;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Collapse a `Map<recordKey, UnionResult>` into the merged user view.
|
|
241
|
+
* HIGH-impact-at-replication / ADVISORY-at-read contract (fork #2):
|
|
242
|
+
* - A resolved single value ⇒ that one view entry.
|
|
243
|
+
* - An OPEN concurrent conflict ⇒ BOTH (all) `put` variants as separate entries (append-both
|
|
244
|
+
* — both surface as ADVISORY hints; the read NEVER suppresses a usable view AND NEVER
|
|
245
|
+
* BLOCKS waiting on operator resolution — a replicated user is a hint, not authority). A
|
|
246
|
+
* `delete` variant contributes nothing to display.
|
|
247
|
+
* - A delete-resolved key (every origin's latest is a tombstone) ⇒ nothing (the
|
|
248
|
+
* delete-resurrection guard: a later delete wins over an earlier put).
|
|
249
|
+
* The read is READ-ONLY: a replicated record NEVER clobbers a divergent local record — the
|
|
250
|
+
* local store files are never written here.
|
|
251
|
+
*/
|
|
252
|
+
export declare function mergeUnionToUsers(union: Map<string, UnionResult>): MergedUserView[];
|
|
253
|
+
/**
|
|
254
|
+
* Render a FOREIGN (replicated) user record into a session-context block, wrapped in an
|
|
255
|
+
* explicit `<replicated-untrusted-data origin="…">` envelope so the session model treats it as
|
|
256
|
+
* a PEER'S claim to re-ground against, never a directive AND never the authoritative
|
|
257
|
+
* inbound-resolution answer. EVERY rendered field is escaped — there is no "trusted because
|
|
258
|
+
* machine-set" slot. A null `data.name` (a malformed view) yields null.
|
|
259
|
+
*/
|
|
260
|
+
export declare function renderForeignUserContext(view: MergedUserView): string | null;
|
|
261
|
+
/**
|
|
262
|
+
* Build an OriginRecord for the OWN user registry (the single-origin materialization the union
|
|
263
|
+
* reader merges against peer replicas). recordKey = derived channel-set identity surface; the
|
|
264
|
+
* envelope carries a SYNTHETIC own-origin HLC stamp derived deterministically from the
|
|
265
|
+
* record's createdAt (physical) so the own record has a well-formed, stable position relative
|
|
266
|
+
* to peer records. Returns null for a channel-less record (no identity surface). The local
|
|
267
|
+
* `userId` is NEVER carried into the replicated namespace (fork #1/#3).
|
|
268
|
+
*/
|
|
269
|
+
export declare function userToOriginRecord(record: UserProfile, origin: string): OriginRecord | null;
|
|
270
|
+
/** The ReplicatedKindRegistry registration for the `user-record` store. server.ts registers
|
|
271
|
+
* this onto the shared registry; the dual-registry coupling test asserts `kind` is also
|
|
272
|
+
* present in JOURNAL_KINDS. */
|
|
273
|
+
export declare const USER_KIND_REGISTRATION: {
|
|
274
|
+
readonly kind: "user-record";
|
|
275
|
+
readonly store: "userRegistry";
|
|
276
|
+
readonly schema: StoreFieldSchema;
|
|
277
|
+
};
|
|
278
|
+
/** Convenience: the store's contributing journal kinds (for rollback-unmerge's
|
|
279
|
+
* kindsForStore('userRegistry') wiring). */
|
|
280
|
+
export declare function userContributingKinds(): string[];
|
|
281
|
+
/** The store's impact tier resolver, for ReplicatedStoreReader.tierOf. Returns HIGH for the
|
|
282
|
+
* `userRegistry` store (and HIGH for any unknown store — the conservative
|
|
283
|
+
* append-both-and-flag direction, never a silent clobber). */
|
|
284
|
+
export declare function userTierOf(_store: string): ImpactTier;
|
|
285
|
+
/** Re-export the envelope type for callers building/applying user-record envelopes. */
|
|
286
|
+
export type { ReplicatedEnvelope };
|
|
287
|
+
//# sourceMappingURL=UserRegistryReplicatedStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UserRegistryReplicatedStore.d.ts","sourceRoot":"","sources":["../../src/core/UserRegistryReplicatedStore.ts"],"names":[],"mappings":"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"}
|