@ttt-productions/ttt-core 0.79.103 → 0.79.104

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.
@@ -59,4 +59,9 @@ export declare function moderationFailedAuditId(requestId: string, terminalFailu
59
59
  */
60
60
  export declare function chatParkedDeliveryId(targetDo: string, eventId: string, parkedAt: number): Promise<string>;
61
61
  export declare function chatAnonymizeJobId(channelDoId: string, epoch: number, anonymizedUid: string): Promise<string>;
62
+ /**
63
+ * The uid an erased member's chat rows are rewritten to. It depends on the member alone, so the
64
+ * live rows and the stored history of every channel name the same former member.
65
+ */
66
+ export declare function chatAnonTombstoneUid(anonymizedUid: string): Promise<string>;
62
67
  //# sourceMappingURL=chat-ids.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"chat-ids.d.ts","sourceRoot":"","sources":["../../src/ids/chat-ids.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"chat-ids.d.ts","sourceRoot":"","sources":["../../src/ids/chat-ids.ts"],"names":[],"mappings":"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"}
@@ -115,4 +115,11 @@ export function chatParkedDeliveryId(targetDo, eventId, parkedAt) {
115
115
  export function chatAnonymizeJobId(channelDoId, epoch, anonymizedUid) {
116
116
  return hash('chat-anonymize', channelDoId, epoch, anonymizedUid);
117
117
  }
118
+ /**
119
+ * The uid an erased member's chat rows are rewritten to. It depends on the member alone, so the
120
+ * live rows and the stored history of every channel name the same former member.
121
+ */
122
+ export function chatAnonTombstoneUid(anonymizedUid) {
123
+ return hash('chat-anon-tombstone', anonymizedUid);
124
+ }
118
125
  //# sourceMappingURL=chat-ids.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"chat-ids.js","sourceRoot":"","sources":["../../src/ids/chat-ids.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Frozen deterministic ID + eventId formulas for chat realtime and notifications.\n *\n * These ids are computed INDEPENDENTLY by multiple producers/consumers\n * (Cloud Functions, the chat Worker, sometimes the client) and MUST match\n * byte-for-byte, so the construction is frozen here as the single source of\n * truth. Hashing uses `@ttt-productions/edge-protocol-core`'s runtime-neutral\n * WebCrypto SHA-256 (works in Node 24, Cloudflare Workers, and browsers), so\n * every builder is async.\n */\n\nimport { sha256Hex } from '@ttt-productions/edge-protocol-core';\nimport type { ChatConversationRef } from '@ttt-productions/chat-schemas';\n\n/** ASCII unit separator — never appears in uids/doc-ids/collection names/numbers. */\nconst UNIT_SEPARATOR = '\\x1f';\n/** A null/absent part hashes as this byte (distinct from any real value). */\nconst NULL_BYTE = '\\x00';\n\nfunction encodePart(part: string | number | null | undefined): string {\n if (part === null || part === undefined) return NULL_BYTE;\n return typeof part === 'number' ? String(part) : part;\n}\n\n/**\n * Canonical collision-safe hash — every `hash(...)` in the chat/notification\n * doc set uses THIS. `domainTag` then each part, separated by `0x1F`; numbers\n * base-10; a null/absent part becomes the literal byte `0x00`. The full 64-char\n * lowercase-hex SHA-256 is the document id. Two id families can never collide\n * because their `domainTag`s differ.\n */\nexport function hash(\n domainTag: string,\n ...parts: Array<string | number | null | undefined>\n): Promise<string> {\n const input = domainTag + UNIT_SEPARATOR + parts.map(encodePart).join(UNIT_SEPARATOR);\n return sha256Hex(input);\n}\n\n// ── Channel identity ────────────────────────────────────────────────────────\n\n/**\n * The collision-safe key of one conversation, over its neutral reference (build it with\n * `toChatConversationRef`). The kind is hashed as its own part, so two kinds never share a key.\n */\nexport function channelKey(ref: ChatConversationRef): Promise<string> {\n return hash('chat-conversation', ref.kind, ref.id);\n}\n\n/** Per-(conversation, user) projection doc id. */\nexport async function authPairKey(ref: ChatConversationRef, uid: string): Promise<string> {\n return hash('chat-channel-auth', await channelKey(ref), uid);\n}\n\n/** Member-in-work degraded scope key (the `workChannelsForUser` selector blocks per uid×Work). */\nexport function userWorkScopeKey(uid: string, workProjectId: string): Promise<string> {\n return hash('chat-user-work', uid, workProjectId);\n}\n\n/** member-in-work degraded summary doc id. */\nexport function degradedMemberInWorkScopeKey(uid: string, workProjectId: string): Promise<string> {\n return hash('chat-degraded-user-work', uid, workProjectId);\n}\n\n/** Namespaced degraded cause id (`kind` keeps event-derived and job-derived causes from colliding). */\nexport function degradedCauseId(kind: 'syncEvent' | 'fanoutJob', ref: string): Promise<string> {\n return hash('chat-degraded-cause', kind, ref);\n}\n\n// ── chatSyncEvents eventIds ─────────────────────────────────────────────────\n\nexport function channelAuthEventId(\n channelKeyHash: string,\n uid: string,\n channelAuthVersion: number,\n): Promise<string> {\n return hash('channel-auth', channelKeyHash, uid, channelAuthVersion);\n}\nexport function accountAccessEventId(\n uid: string,\n accountAccessVersion: number,\n channelKeyHash: string,\n): Promise<string> {\n return hash('account-access', uid, accountAccessVersion, channelKeyHash);\n}\nexport function configEventId(channelKeyHash: string, configVersion: number): Promise<string> {\n return hash('config', channelKeyHash, configVersion);\n}\n\n/** `chatMessageOutbox` commandId for invite/system messages. */\nexport function serverMessageCommandId(threadRef: string, sourceDocId: string): Promise<string> {\n return hash('server-msg', threadRef, sourceDocId);\n}\n\n// ── chatSyncFanoutJobs ──────────────────────────────────────────────────────\n\nexport type SyncFanoutSelectorKind =\n 'channelMembers' | 'workChannelsForUser' | 'policyEditAffectedUsers';\n\n/**\n * `scopeKey` = `channelKey` for channelMembers/policyEditAffectedUsers, or\n * `userWorkScopeKey(uid, workProjectId)` for workChannelsForUser. `causeVersion`\n * = the channel's post-mutation configVersion, or the user's post-mutation\n * guildAuthInputVersion respectively.\n */\nexport function chatSyncFanoutJobId(\n selectorKind: SyncFanoutSelectorKind,\n scopeKey: string,\n causeVersion: number,\n): Promise<string> {\n return hash('chat-sync-fanout', selectorKind, scopeKey, causeVersion);\n}\n\n// ── Inbox projection eventId ────────────────────────────────────────────────\n\nexport function inboxProjectionEventId(\n channelKeyHash: string,\n recipientUid: string,\n kind: string,\n sourceVersion: number,\n): Promise<string> {\n return hash('chat-inbox-event', channelKeyHash, recipientUid, kind, sourceVersion);\n}\n\n// ── Notification ledger / archive ───────────────────────────────────────────\n\n/** Delivery-ledger row id. Shared-admin occurrences pass `recipientUid = null` (hashed as `'shared'`). */\nexport function notificationDeliveryId(\n recipientUid: string | null,\n notificationType: string,\n eventId: string,\n): Promise<string> {\n return hash('notif-delivery', recipientUid ?? 'shared', notificationType, eventId);\n}\n\n/** Archive history doc id (= `archiveOccurrenceId`). */\nexport function notificationArchiveHistoryId(\n category: string,\n audienceScope: string,\n requestId: string,\n): Promise<string> {\n return hash('notification-archive', category, audienceScope, requestId);\n}\n\n/** Archive replay-vs-conflict discriminator. */\nexport function notificationArchivePayloadHash(\n activeId: string,\n observedActivityGeneration: string,\n category: string,\n audienceScope: string,\n): Promise<string> {\n return hash(\n 'notification-archive-payload',\n activeId,\n observedActivityGeneration,\n category,\n audienceScope,\n );\n}\n\n// ── Moderation audit ids (append-only; create-if-absent) ────────────────────\n\nexport function moderationRequestedAuditId(requestId: string): Promise<string> {\n return hash('chat-moderation-requested', requestId);\n}\nexport function moderationAppliedAuditId(\n requestId: string,\n resultingMessageRevision: number,\n): Promise<string> {\n return hash('chat-moderation-applied', requestId, resultingMessageRevision);\n}\nexport function moderationFailedAuditId(\n requestId: string,\n terminalFailureGeneration: number,\n): Promise<string> {\n return hash('chat-moderation-failed', requestId, terminalFailureGeneration);\n}\n\n// ── A chat room's parked deliveries ──────────────────────────────────────────\n\n/**\n * The `chatParkedDeliveries` row id of one parking of one room outbox row. `parkedAt` is part of\n * the identity: a row the room parks again after a replay is a second occurrence with its own row.\n */\nexport function chatParkedDeliveryId(\n targetDo: string,\n eventId: string,\n parkedAt: number,\n): Promise<string> {\n return hash('chat-parked-delivery', targetDo, eventId, parkedAt);\n}\n\n// ── History anonymization ───────────────────────────────────────────────────\n\nexport function chatAnonymizeJobId(\n channelDoId: string,\n epoch: number,\n anonymizedUid: string,\n): Promise<string> {\n return hash('chat-anonymize', channelDoId, epoch, anonymizedUid);\n}\n"]}
1
+ {"version":3,"file":"chat-ids.js","sourceRoot":"","sources":["../../src/ids/chat-ids.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Frozen deterministic ID + eventId formulas for chat realtime and notifications.\n *\n * These ids are computed INDEPENDENTLY by multiple producers/consumers\n * (Cloud Functions, the chat Worker, sometimes the client) and MUST match\n * byte-for-byte, so the construction is frozen here as the single source of\n * truth. Hashing uses `@ttt-productions/edge-protocol-core`'s runtime-neutral\n * WebCrypto SHA-256 (works in Node 24, Cloudflare Workers, and browsers), so\n * every builder is async.\n */\n\nimport { sha256Hex } from '@ttt-productions/edge-protocol-core';\nimport type { ChatConversationRef } from '@ttt-productions/chat-schemas';\n\n/** ASCII unit separator — never appears in uids/doc-ids/collection names/numbers. */\nconst UNIT_SEPARATOR = '\\x1f';\n/** A null/absent part hashes as this byte (distinct from any real value). */\nconst NULL_BYTE = '\\x00';\n\nfunction encodePart(part: string | number | null | undefined): string {\n if (part === null || part === undefined) return NULL_BYTE;\n return typeof part === 'number' ? String(part) : part;\n}\n\n/**\n * Canonical collision-safe hash — every `hash(...)` in the chat/notification\n * doc set uses THIS. `domainTag` then each part, separated by `0x1F`; numbers\n * base-10; a null/absent part becomes the literal byte `0x00`. The full 64-char\n * lowercase-hex SHA-256 is the document id. Two id families can never collide\n * because their `domainTag`s differ.\n */\nexport function hash(\n domainTag: string,\n ...parts: Array<string | number | null | undefined>\n): Promise<string> {\n const input = domainTag + UNIT_SEPARATOR + parts.map(encodePart).join(UNIT_SEPARATOR);\n return sha256Hex(input);\n}\n\n// ── Channel identity ────────────────────────────────────────────────────────\n\n/**\n * The collision-safe key of one conversation, over its neutral reference (build it with\n * `toChatConversationRef`). The kind is hashed as its own part, so two kinds never share a key.\n */\nexport function channelKey(ref: ChatConversationRef): Promise<string> {\n return hash('chat-conversation', ref.kind, ref.id);\n}\n\n/** Per-(conversation, user) projection doc id. */\nexport async function authPairKey(ref: ChatConversationRef, uid: string): Promise<string> {\n return hash('chat-channel-auth', await channelKey(ref), uid);\n}\n\n/** Member-in-work degraded scope key (the `workChannelsForUser` selector blocks per uid×Work). */\nexport function userWorkScopeKey(uid: string, workProjectId: string): Promise<string> {\n return hash('chat-user-work', uid, workProjectId);\n}\n\n/** member-in-work degraded summary doc id. */\nexport function degradedMemberInWorkScopeKey(uid: string, workProjectId: string): Promise<string> {\n return hash('chat-degraded-user-work', uid, workProjectId);\n}\n\n/** Namespaced degraded cause id (`kind` keeps event-derived and job-derived causes from colliding). */\nexport function degradedCauseId(kind: 'syncEvent' | 'fanoutJob', ref: string): Promise<string> {\n return hash('chat-degraded-cause', kind, ref);\n}\n\n// ── chatSyncEvents eventIds ─────────────────────────────────────────────────\n\nexport function channelAuthEventId(\n channelKeyHash: string,\n uid: string,\n channelAuthVersion: number,\n): Promise<string> {\n return hash('channel-auth', channelKeyHash, uid, channelAuthVersion);\n}\nexport function accountAccessEventId(\n uid: string,\n accountAccessVersion: number,\n channelKeyHash: string,\n): Promise<string> {\n return hash('account-access', uid, accountAccessVersion, channelKeyHash);\n}\nexport function configEventId(channelKeyHash: string, configVersion: number): Promise<string> {\n return hash('config', channelKeyHash, configVersion);\n}\n\n/** `chatMessageOutbox` commandId for invite/system messages. */\nexport function serverMessageCommandId(threadRef: string, sourceDocId: string): Promise<string> {\n return hash('server-msg', threadRef, sourceDocId);\n}\n\n// ── chatSyncFanoutJobs ──────────────────────────────────────────────────────\n\nexport type SyncFanoutSelectorKind =\n 'channelMembers' | 'workChannelsForUser' | 'policyEditAffectedUsers';\n\n/**\n * `scopeKey` = `channelKey` for channelMembers/policyEditAffectedUsers, or\n * `userWorkScopeKey(uid, workProjectId)` for workChannelsForUser. `causeVersion`\n * = the channel's post-mutation configVersion, or the user's post-mutation\n * guildAuthInputVersion respectively.\n */\nexport function chatSyncFanoutJobId(\n selectorKind: SyncFanoutSelectorKind,\n scopeKey: string,\n causeVersion: number,\n): Promise<string> {\n return hash('chat-sync-fanout', selectorKind, scopeKey, causeVersion);\n}\n\n// ── Inbox projection eventId ────────────────────────────────────────────────\n\nexport function inboxProjectionEventId(\n channelKeyHash: string,\n recipientUid: string,\n kind: string,\n sourceVersion: number,\n): Promise<string> {\n return hash('chat-inbox-event', channelKeyHash, recipientUid, kind, sourceVersion);\n}\n\n// ── Notification ledger / archive ───────────────────────────────────────────\n\n/** Delivery-ledger row id. Shared-admin occurrences pass `recipientUid = null` (hashed as `'shared'`). */\nexport function notificationDeliveryId(\n recipientUid: string | null,\n notificationType: string,\n eventId: string,\n): Promise<string> {\n return hash('notif-delivery', recipientUid ?? 'shared', notificationType, eventId);\n}\n\n/** Archive history doc id (= `archiveOccurrenceId`). */\nexport function notificationArchiveHistoryId(\n category: string,\n audienceScope: string,\n requestId: string,\n): Promise<string> {\n return hash('notification-archive', category, audienceScope, requestId);\n}\n\n/** Archive replay-vs-conflict discriminator. */\nexport function notificationArchivePayloadHash(\n activeId: string,\n observedActivityGeneration: string,\n category: string,\n audienceScope: string,\n): Promise<string> {\n return hash(\n 'notification-archive-payload',\n activeId,\n observedActivityGeneration,\n category,\n audienceScope,\n );\n}\n\n// ── Moderation audit ids (append-only; create-if-absent) ────────────────────\n\nexport function moderationRequestedAuditId(requestId: string): Promise<string> {\n return hash('chat-moderation-requested', requestId);\n}\nexport function moderationAppliedAuditId(\n requestId: string,\n resultingMessageRevision: number,\n): Promise<string> {\n return hash('chat-moderation-applied', requestId, resultingMessageRevision);\n}\nexport function moderationFailedAuditId(\n requestId: string,\n terminalFailureGeneration: number,\n): Promise<string> {\n return hash('chat-moderation-failed', requestId, terminalFailureGeneration);\n}\n\n// ── A chat room's parked deliveries ──────────────────────────────────────────\n\n/**\n * The `chatParkedDeliveries` row id of one parking of one room outbox row. `parkedAt` is part of\n * the identity: a row the room parks again after a replay is a second occurrence with its own row.\n */\nexport function chatParkedDeliveryId(\n targetDo: string,\n eventId: string,\n parkedAt: number,\n): Promise<string> {\n return hash('chat-parked-delivery', targetDo, eventId, parkedAt);\n}\n\n// ── History anonymization ───────────────────────────────────────────────────\n\nexport function chatAnonymizeJobId(\n channelDoId: string,\n epoch: number,\n anonymizedUid: string,\n): Promise<string> {\n return hash('chat-anonymize', channelDoId, epoch, anonymizedUid);\n}\n\n/**\n * The uid an erased member's chat rows are rewritten to. It depends on the member alone, so the\n * live rows and the stored history of every channel name the same former member.\n */\nexport function chatAnonTombstoneUid(anonymizedUid: string): Promise<string> {\n return hash('chat-anon-tombstone', anonymizedUid);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttt-productions/ttt-core",
3
- "version": "0.79.103",
3
+ "version": "0.79.104",
4
4
  "description": "Core types, Firestore path constants, and shared constants for TTT Productions",
5
5
  "repository": {
6
6
  "type": "git",