@antiphony/shared 0.1.0 → 0.4.0
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/README.md +4 -4
- package/dist/cjs/api-codecs.cjs +90 -787
- package/dist/cjs/api-codecs.d.cts +117 -290
- package/dist/cjs/index.cjs +102 -947
- package/dist/cjs/index.d.cts +89 -7
- package/dist/cjs/nsid.cjs +8 -18
- package/dist/cjs/nsid.d.cts +8 -17
- package/dist/cjs/types/audio.cjs +77 -662
- package/dist/cjs/types/audio.d.cts +285 -203
- package/dist/cjs/types/blob.cjs +5 -9
- package/dist/cjs/types/blob.d.cts +21 -21
- package/dist/cjs/types/records.cjs +0 -370
- package/dist/cjs/types/records.d.cts +1 -825
- package/dist/esm/api-codecs.d.ts +117 -290
- package/dist/esm/api-codecs.js +5 -6
- package/dist/esm/{chunk-ORMEWXMH.js → chunk-5JBD5THX.js} +1 -16
- package/dist/esm/{chunk-F2CANZZ7.js → chunk-BNNLHRH7.js} +1 -1
- package/dist/esm/chunk-D655OH2I.js +35 -0
- package/dist/esm/chunk-RUUHUNZ6.js +37 -0
- package/dist/esm/chunk-SBYNIQRZ.js +23 -0
- package/dist/esm/chunk-SMK4OZNU.js +17 -0
- package/dist/esm/{chunk-BUNMR4ZO.js → chunk-WL2GSPGC.js} +81 -12
- package/dist/esm/errors/index.js +1 -1
- package/dist/esm/index.d.ts +89 -7
- package/dist/esm/index.js +7 -9
- package/dist/esm/nsid.d.ts +8 -17
- package/dist/esm/nsid.js +2 -2
- package/dist/esm/observability/index.js +2 -2
- package/dist/esm/observability/report-error.js +2 -2
- package/dist/esm/types/audio.d.ts +285 -203
- package/dist/esm/types/audio.js +4 -5
- package/dist/esm/types/blob.d.ts +21 -21
- package/dist/esm/types/blob.js +2 -2
- package/dist/esm/types/records.d.ts +1 -825
- package/dist/esm/types/records.js +2 -3
- package/dist/esm/utils/index.js +1 -1
- package/package.json +90 -26
- package/dist/cjs/types/api.cjs +0 -726
- package/dist/cjs/types/api.d.cts +0 -494
- package/dist/cjs/types/channels.cjs +0 -170
- package/dist/cjs/types/channels.d.cts +0 -262
- package/dist/cjs/types/storage.cjs +0 -414
- package/dist/cjs/types/storage.d.cts +0 -197
- package/dist/cjs/types/views.cjs +0 -820
- package/dist/cjs/types/views.d.cts +0 -9806
- package/dist/esm/chunk-3WZJXJNU.js +0 -378
- package/dist/esm/chunk-5EHV73BA.js +0 -20
- package/dist/esm/chunk-7V44CPRR.js +0 -132
- package/dist/esm/chunk-EA4OONDV.js +0 -380
- package/dist/esm/chunk-TIZRJORN.js +0 -24
- package/dist/esm/chunk-XDBKR6LW.js +0 -32
- package/dist/esm/types/api.d.ts +0 -494
- package/dist/esm/types/api.js +0 -5
- package/dist/esm/types/channels.d.ts +0 -262
- package/dist/esm/types/channels.js +0 -162
- package/dist/esm/types/storage.d.ts +0 -197
- package/dist/esm/types/storage.js +0 -26
- package/dist/esm/types/views.d.ts +0 -9806
- package/dist/esm/types/views.js +0 -4
package/dist/cjs/index.cjs
CHANGED
|
@@ -3,8 +3,6 @@
|
|
|
3
3
|
var zod = require('zod');
|
|
4
4
|
|
|
5
5
|
var __defProp = Object.defineProperty;
|
|
6
|
-
var __defProps = Object.defineProperties;
|
|
7
|
-
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
8
6
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
9
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
10
8
|
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
@@ -20,41 +18,18 @@ var __spreadValues = (a, b) => {
|
|
|
20
18
|
}
|
|
21
19
|
return a;
|
|
22
20
|
};
|
|
23
|
-
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
24
|
-
var __objRest = (source, exclude) => {
|
|
25
|
-
var target = {};
|
|
26
|
-
for (var prop in source)
|
|
27
|
-
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
28
|
-
target[prop] = source[prop];
|
|
29
|
-
if (source != null && __getOwnPropSymbols)
|
|
30
|
-
for (var prop of __getOwnPropSymbols(source)) {
|
|
31
|
-
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
32
|
-
target[prop] = source[prop];
|
|
33
|
-
}
|
|
34
|
-
return target;
|
|
35
|
-
};
|
|
36
21
|
var BlobRefSchema = zod.z.object({
|
|
37
22
|
/** Discriminator for AT Protocol type system */
|
|
38
23
|
$type: zod.z.literal("blob"),
|
|
39
|
-
/**
|
|
40
|
-
ref: zod.z.
|
|
24
|
+
/** IPLD link to the blob bytes: the content CID. */
|
|
25
|
+
ref: zod.z.object({
|
|
26
|
+
$link: zod.z.string().min(1)
|
|
27
|
+
}),
|
|
41
28
|
/** MIME type of the blob (e.g., 'audio/webm') */
|
|
42
29
|
mimeType: zod.z.string(),
|
|
43
30
|
/** Size of the blob in bytes */
|
|
44
|
-
size: zod.z.number()
|
|
31
|
+
size: zod.z.number().int().min(0)
|
|
45
32
|
});
|
|
46
|
-
function resolveAudioUrl(record) {
|
|
47
|
-
var _a;
|
|
48
|
-
if ((_a = record.audio) == null ? void 0 : _a.ref) return record.audio.ref;
|
|
49
|
-
return record.audioUrl;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// types/records.ts
|
|
53
|
-
function httpsUrl() {
|
|
54
|
-
return zod.z.string().trim().url().refine((u) => /^https?:\/\//i.test(u), {
|
|
55
|
-
message: "URL must use the http or https scheme"
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
33
|
var FirestoreTimestampSchema = zod.z.union([
|
|
59
34
|
zod.z.custom((data) => {
|
|
60
35
|
return data && typeof data === "object" && (typeof data.toDate === "function" || "seconds" in data && "nanoseconds" in data);
|
|
@@ -85,717 +60,21 @@ var FirestoreTimestampSchema = zod.z.union([
|
|
|
85
60
|
}
|
|
86
61
|
return date;
|
|
87
62
|
});
|
|
88
|
-
var
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
handle: zod.z.string().min(3).max(20).regex(/^[a-zA-Z0-9_]+$/).nullable().optional(),
|
|
93
|
-
/** User stated intent (e.g. "Podcaster", "Listener") */
|
|
94
|
-
usageIntent: zod.z.string().nullable().optional(),
|
|
95
|
-
/**
|
|
96
|
-
* Domain for federated handle support.
|
|
97
|
-
* Defaults to 'voxpop.com'.
|
|
98
|
-
*/
|
|
99
|
-
domain: zod.z.string().default("voxpop.com"),
|
|
100
|
-
/**
|
|
101
|
-
* Display Name (e.g. "Brad Thorson"). Nullable: Firestore stores `null`
|
|
102
|
-
* when the user clears this field via the settings form, and the schema
|
|
103
|
-
* must match storage reality or `UserRecordSchema.parse` (in
|
|
104
|
-
* `getUserRecordByUid`) will throw.
|
|
105
|
-
*/
|
|
106
|
-
displayName: zod.z.string().max(50).nullable().optional(),
|
|
107
|
-
/** Short bio/description — nullable for the same reason as displayName. */
|
|
108
|
-
bio: zod.z.string().max(160).nullable().optional(),
|
|
109
|
-
/** URL to avatar image — nullable for the same reason as displayName. */
|
|
110
|
-
avatarUrl: zod.z.string().url().nullable().optional(),
|
|
111
|
-
/** Optional personal website surfaced on the public profile. */
|
|
112
|
-
website: httpsUrl().nullable().optional(),
|
|
113
|
-
/** Up to 5 additional public links (label + URL) shown under the bio. */
|
|
114
|
-
links: zod.z.array(zod.z.object({
|
|
115
|
-
label: zod.z.string().min(1).max(40),
|
|
116
|
-
url: httpsUrl()
|
|
117
|
-
})).max(5).optional(),
|
|
118
|
-
/** When true and a Bluesky identity is linked, surfaces it on the public profile. */
|
|
119
|
-
showBlueskyPublicly: zod.z.boolean().optional(),
|
|
120
|
-
/** Server timestamp of creation */
|
|
121
|
-
createdAt: FirestoreTimestampSchema,
|
|
122
|
-
/** Individual account tier — free or creator_pro */
|
|
123
|
-
tier: zod.z.enum(["free", "creator_pro"]).default("free"),
|
|
124
|
-
/** Account status. Deactivated accounts retain data but are excluded from lookups. */
|
|
125
|
-
status: zod.z.enum(["active", "deactivated"]).default("active"),
|
|
126
|
-
/** Timestamp when the account was deactivated (soft deleted) */
|
|
127
|
-
deactivatedAt: FirestoreTimestampSchema.optional(),
|
|
128
|
-
/**
|
|
129
|
-
* Denormalized org memberships — { orgId: role } for fast lookup.
|
|
130
|
-
* Source of truth is organizations/{orgId}/members/{userId}.
|
|
131
|
-
* Kept in sync by Cloud Function trigger.
|
|
132
|
-
*/
|
|
133
|
-
orgMemberships: zod.z.record(zod.z.string(), zod.z.enum(["owner", "admin", "member"])).optional()
|
|
134
|
-
});
|
|
135
|
-
var PromptRecordSchema = zod.z.object({
|
|
136
|
-
/** Unique Prompt ID */
|
|
137
|
-
id: zod.z.string(),
|
|
138
|
-
/** ID of the User who created this prompt. Always a user ID, never an org ID. @see UserRecord */
|
|
139
|
-
authorId: zod.z.string(),
|
|
140
|
-
/** Organization context this prompt belongs to (null = personal/no org) */
|
|
141
|
-
orgId: zod.z.string().nullable().optional(),
|
|
142
|
-
/** The main text of the question/prompt */
|
|
143
|
-
title: zod.z.string().min(3),
|
|
144
|
-
/** Optional extra context */
|
|
145
|
-
description: zod.z.string().nullable().optional(),
|
|
146
|
-
/** User who created this prompt (differs from authorId when org-owned) */
|
|
147
|
-
createdBy: zod.z.string().optional(),
|
|
148
|
-
/** URL to the recorded audio file (GCS) */
|
|
149
|
-
audioUrl: zod.z.string().url().or(zod.z.literal("")),
|
|
150
|
-
/** AT Protocol blob reference (future replacement for audioUrl) */
|
|
151
|
-
audio: BlobRefSchema.optional(),
|
|
152
|
-
/**
|
|
153
|
-
* AT Protocol URI returned by the publisher after a successful
|
|
154
|
-
* `repo.putRecord` against the author's PDS — e.g.
|
|
155
|
-
* `at://did:plc:abc123/com.voxpop.audio.prompt/3kj4...`. Optional,
|
|
156
|
-
* no migration: existing rows leave it unset. Format-validated so
|
|
157
|
-
* malformed strings surface at the schema-parse boundary rather than
|
|
158
|
-
* being silently stored.
|
|
159
|
-
*/
|
|
160
|
-
atprotoUri: zod.z.string().regex(/^at:\/\/.+/).optional(),
|
|
161
|
-
/** Server timestamp of creation */
|
|
162
|
-
createdAt: FirestoreTimestampSchema,
|
|
163
|
-
/**
|
|
164
|
-
* Life-cycle status.
|
|
165
|
-
* - `live`: Visible and accepting replies.
|
|
166
|
-
* - `archived`: Visible but closed for new replies.
|
|
167
|
-
* - `deleted`: Soft deleted.
|
|
168
|
-
*/
|
|
169
|
-
status: zod.z.enum(["live", "archived", "deleted"]).default("live"),
|
|
170
|
-
/** AI Enrichment Fields */
|
|
171
|
-
aiStatus: zod.z.enum(["pending", "complete", "error"]).optional(),
|
|
172
|
-
aiError: zod.z.string().optional(),
|
|
173
|
-
aiSummary: zod.z.string().optional(),
|
|
174
|
-
aiLabels: zod.z.array(zod.z.string()).optional(),
|
|
175
|
-
transcription: zod.z.string().optional(),
|
|
176
|
-
/** Pre-computed waveform peaks (normalized 0–1) for instant audio visualization */
|
|
177
|
-
waveformPeaks: zod.z.array(zod.z.number()).optional(),
|
|
178
|
-
/** Social Share Video Fields */
|
|
179
|
-
socialVideoUrl: zod.z.string().url().optional(),
|
|
180
|
-
socialVideoStoragePath: zod.z.string().optional(),
|
|
181
|
-
socialVideoStatus: zod.z.enum(["pending", "complete", "error"]).optional(),
|
|
182
|
-
socialVideoError: zod.z.string().optional(),
|
|
183
|
-
/** The audio URL/path used to generate the current video (for cache invalidation) */
|
|
184
|
-
socialVideoSourceAudio: zod.z.string().optional()
|
|
185
|
-
});
|
|
186
|
-
var ReplyRecordSchema = zod.z.object({
|
|
187
|
-
/** Unique Reply ID */
|
|
188
|
-
id: zod.z.string(),
|
|
189
|
-
/** The Prompt being replied to. @see PromptRecord */
|
|
190
|
-
promptId: zod.z.string(),
|
|
191
|
-
/** The User who replied. @see UserRecord */
|
|
192
|
-
authorId: zod.z.string(),
|
|
193
|
-
/** URL to the recorded audio file (GCS) */
|
|
194
|
-
audioUrl: zod.z.string().url(),
|
|
195
|
-
/** AT Protocol blob reference (future replacement for audioUrl) */
|
|
196
|
-
audio: BlobRefSchema.optional(),
|
|
197
|
-
/** Server timestamp of creation */
|
|
198
|
-
createdAt: FirestoreTimestampSchema,
|
|
199
|
-
/**
|
|
200
|
-
* Life-cycle status.
|
|
201
|
-
* - `live`: Visible and accepting replies.
|
|
202
|
-
* - `archived`: Visible but closed for new replies.
|
|
203
|
-
* - `deleted`: Soft deleted.
|
|
204
|
-
*/
|
|
205
|
-
status: zod.z.enum(["live", "archived", "deleted"]).default("live"),
|
|
206
|
-
/**
|
|
207
|
-
* Pre-computed waveform peaks (normalized 0–1) for instant audio
|
|
208
|
-
* visualization. **Stays on canonical** (does NOT move to the
|
|
209
|
-
* enrichment doc) — produced by a plain ffmpeg pass at ingestion,
|
|
210
|
-
* not an AI step; a self-hoster without paid-tier AI still needs
|
|
211
|
-
* this on every reply for the audio player. See
|
|
212
|
-
* `specs/ai-enrichment-split.md` § 5.
|
|
213
|
-
*/
|
|
214
|
-
waveformPeaks: zod.z.array(zod.z.number()).optional(),
|
|
215
|
-
/**
|
|
216
|
-
* Duration of the audio in seconds, computed server-side from
|
|
217
|
-
* ffmpeg. **Stays on canonical** (same reasoning as `waveformPeaks`
|
|
218
|
-
* above — ingestion ffmpeg output, not an AI enrichment). See
|
|
219
|
-
* `specs/ai-enrichment-split.md` § 5.
|
|
220
|
-
*/
|
|
221
|
-
audioDurationSec: zod.z.number().optional()
|
|
222
|
-
});
|
|
223
|
-
var ReplyEnrichmentRecordSchema = zod.z.object({
|
|
224
|
-
id: zod.z.string(),
|
|
225
|
-
/** Private notes by the prompt author about this reply. */
|
|
226
|
-
notes: zod.z.string().optional(),
|
|
227
|
-
// === AI-enrichment fields (sole source of truth post Stage 4) ===
|
|
228
|
-
//
|
|
229
|
-
// These lifted off canonical in Stage 4 of `specs/ai-enrichment-split.md`.
|
|
230
|
-
// Writers (`functions/`) route AI updates here via the split-write
|
|
231
|
-
// helper in `functions/src/services/replyEnrichmentDualWrite.ts`;
|
|
232
|
-
// readers source them via the hydrator's enrichment branch (see
|
|
233
|
-
// `packages/core/services/hydration.ts`).
|
|
234
|
-
// --- AI core (Gemini-generated) ---
|
|
235
|
-
aiStatus: zod.z.enum(["pending", "complete", "error", "skipped_too_short"]).optional(),
|
|
236
|
-
aiError: zod.z.string().optional(),
|
|
237
|
-
aiSummary: zod.z.string().optional(),
|
|
238
|
-
aiLabels: zod.z.array(zod.z.string()).optional(),
|
|
239
|
-
transcription: zod.z.string().optional(),
|
|
240
|
-
sentiment: zod.z.enum(["Positive", "Negative", "Neutral"]).optional(),
|
|
241
|
-
/** Must match the widened enum in `ReplyRecordSchema.energyLevel`. */
|
|
242
|
-
energyLevel: zod.z.enum(["High", "Low", "Neutral"]).optional(),
|
|
243
|
-
engagementScore: zod.z.number().min(1).max(10).optional(),
|
|
244
|
-
// --- Voice isolation (ElevenLabs, paid tier) ---
|
|
245
|
-
/** Noise-reduced audio URL — replaces `audioUrl` for downstream players when present. PUBLIC. */
|
|
246
|
-
enhancedAudioUrl: zod.z.string().url().optional(),
|
|
247
|
-
/** Storage path companion to `enhancedAudioUrl` — private. */
|
|
248
|
-
enhancedStoragePath: zod.z.string().optional(),
|
|
249
|
-
// --- Social-share video (paid tier) ---
|
|
250
|
-
//
|
|
251
|
-
// All `socialVideo*` fields are creator-only. The URL points at the
|
|
252
|
-
// generated artifact (a video file the creator can download and post
|
|
253
|
-
// to social media); the reply detail page does NOT render it.
|
|
254
|
-
socialVideoUrl: zod.z.string().url().optional(),
|
|
255
|
-
socialVideoStoragePath: zod.z.string().optional(),
|
|
256
|
-
socialVideoStatus: zod.z.enum(["pending", "complete", "error"]).optional(),
|
|
257
|
-
socialVideoError: zod.z.string().optional(),
|
|
258
|
-
/** The audio URL/path used to generate the current video (for cache invalidation). */
|
|
259
|
-
socialVideoSourceAudio: zod.z.string().optional()
|
|
260
|
-
});
|
|
261
|
-
var PersonEnrichmentRecordSchema = zod.z.object({
|
|
262
|
-
/** Composite key `${viewerUid}_${targetUid}`. */
|
|
263
|
-
id: zod.z.string(),
|
|
264
|
-
/** Per-viewer CRM notes about the target. */
|
|
265
|
-
notes: zod.z.string().optional(),
|
|
266
|
-
/** Per-viewer freeform tags about the target. */
|
|
267
|
-
tags: zod.z.array(zod.z.string()).optional(),
|
|
268
|
-
// === Identity-merge: alias set ===
|
|
269
|
-
//
|
|
270
|
-
// Other identifiers the viewer has declared to be the SAME person as
|
|
271
|
-
// this entry's `targetUid`. vCard/URI-aligned: each entry is a
|
|
272
|
-
// scheme-prefixed identifier, so one field generalizes across networks
|
|
273
|
-
// AND across the future contact-sync import (which carries phone/email):
|
|
274
|
-
// "uid:<firebaseUid>" | "did:plc:…" | "handle:bob.bsky.social"
|
|
275
|
-
// | "tel:+15551234567" | "mailto:x@example.com"
|
|
276
|
-
// Mirrors vCard 4.0's `UID` + `CLIENTPIDMAP`/`PID` source-tracking
|
|
277
|
-
// (RFC 6350) — the standard answer to "the same person from multiple
|
|
278
|
-
// sources". See `specs/people-lexicon-prior-art.md`. The People
|
|
279
|
-
// read-path collapses any replier whose "uid:<uid>" appears here into
|
|
280
|
-
// this primary entry. Empty until the merge feature is used.
|
|
281
|
-
aliases: zod.z.array(zod.z.string()).optional(),
|
|
282
|
-
lastUpdated: FirestoreTimestampSchema.optional()
|
|
283
|
-
});
|
|
284
|
-
var SipEnrichmentSchema = zod.z.object({
|
|
285
|
-
sipUri: zod.z.string(),
|
|
286
|
-
sipUsername: zod.z.string(),
|
|
287
|
-
sipSecret: zod.z.string(),
|
|
288
|
-
provider: zod.z.enum(["twilio", "plivo", "internal"])
|
|
63
|
+
var ProcessingStageStatusSchema = zod.z.enum(["pending", "ready", "failed", "skipped"]);
|
|
64
|
+
var ProcessingRequestSchema = zod.z.object({
|
|
65
|
+
transcribe: zod.z.boolean().optional(),
|
|
66
|
+
denoise: zod.z.boolean().optional()
|
|
289
67
|
});
|
|
290
|
-
var
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
/**
|
|
294
|
-
|
|
295
|
-
/** Carrier name from Twilio Lookup v2 */
|
|
296
|
-
carrier: zod.z.string().nullable(),
|
|
297
|
-
/** free = shared Twilio number (ForwardedFrom routing), paid = dedicated number */
|
|
298
|
-
tier: zod.z.enum(["free", "paid"]),
|
|
299
|
-
/** The VoxPop Twilio number calls forward to (E.164) */
|
|
300
|
-
voxpopNumber: zod.z.string(),
|
|
301
|
-
/** Twilio Phone Number SID (paid tier only) */
|
|
302
|
-
twilioNumberSid: zod.z.string().nullable().optional(),
|
|
303
|
-
/** Forwarding verification state */
|
|
304
|
-
verificationStatus: zod.z.enum(["pending", "verifying", "verified", "failed"]).default("pending"),
|
|
305
|
-
/** Last verification attempt timestamp */
|
|
306
|
-
lastVerificationAt: FirestoreTimestampSchema.optional(),
|
|
307
|
-
/** Number of verification attempts */
|
|
308
|
-
verificationAttempts: zod.z.number().default(0),
|
|
309
|
-
/** Reason for verification failure */
|
|
310
|
-
failureReason: zod.z.string().nullable().optional(),
|
|
311
|
-
/** Whether call forwarding is active */
|
|
312
|
-
enabled: zod.z.boolean().default(false),
|
|
313
|
-
createdAt: FirestoreTimestampSchema,
|
|
68
|
+
var ProcessingStateSchema = zod.z.object({
|
|
69
|
+
transcribe: ProcessingStageStatusSchema.optional(),
|
|
70
|
+
denoise: ProcessingStageStatusSchema.optional(),
|
|
71
|
+
/** Content CID of the denoised audio variant, once `denoise === 'ready'`. */
|
|
72
|
+
denoisedBlobCid: zod.z.string().optional(),
|
|
314
73
|
updatedAt: FirestoreTimestampSchema
|
|
315
74
|
});
|
|
316
|
-
var
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
* connector-specific knowledge. */
|
|
320
|
-
state: zod.z.enum(["unconfigured", "pending", "active", "error", "disabled"]).default("unconfigured"),
|
|
321
|
-
detail: zod.z.string().nullable().optional(),
|
|
322
|
-
/** Opaque, connector-specific status detail (e.g. telephony's
|
|
323
|
-
* `{ verificationStatus, verificationAttempts, failureReason }`). Connector-
|
|
324
|
-
* owned like the rest of `status` — never user-writable. Nullable so a doc
|
|
325
|
-
* that stored `data: null` round-trips without a parse error. */
|
|
326
|
-
data: zod.z.record(zod.z.unknown()).nullable().optional(),
|
|
327
|
-
updatedAt: FirestoreTimestampSchema.optional()
|
|
328
|
-
});
|
|
329
|
-
var ConnectorConfigRecordSchema = zod.z.object({
|
|
330
|
-
connectorType: ConnectorTypeSchema,
|
|
331
|
-
/** The owning user. Org-scoping (ownerId as an orgId) is a later step. */
|
|
332
|
-
ownerId: zod.z.string(),
|
|
333
|
-
/** Opaque, connector-specific blob. Core does not interpret this. */
|
|
334
|
-
settings: zod.z.record(zod.z.unknown()).default({}),
|
|
335
|
-
/** Reference into a secret store (e.g. Secret Manager key). Never a raw secret. */
|
|
336
|
-
secretRef: zod.z.string().nullable().optional(),
|
|
337
|
-
enabled: zod.z.boolean().default(false),
|
|
338
|
-
status: ConnectorStatusSchema.default({ state: "unconfigured" }),
|
|
339
|
-
createdAt: FirestoreTimestampSchema,
|
|
340
|
-
updatedAt: FirestoreTimestampSchema
|
|
341
|
-
});
|
|
342
|
-
var ScreeningRuleRecordSchema = zod.z.object({
|
|
343
|
-
id: zod.z.string(),
|
|
344
|
-
ownerId: zod.z.string(),
|
|
345
|
-
/** The caller number this rule matches (E.164). Format-enforced at the
|
|
346
|
-
* record level so any writer (API, future contact-sync/callback) can't
|
|
347
|
-
* persist a malformed number. */
|
|
348
|
-
e164: zod.z.string().regex(/^\+[1-9]\d{6,14}$/, "Must be an E.164 phone number"),
|
|
349
|
-
/** Display label, e.g. "Mom" / "Delta Airlines". null = unlabeled. */
|
|
350
|
-
label: zod.z.string().nullable().optional(),
|
|
351
|
-
/** `allow` = ring through; `screen` = async voicemail. */
|
|
352
|
-
action: zod.z.enum(["allow", "screen"]),
|
|
353
|
-
/** Provenance. `manual` = user-created; the others are future writers. */
|
|
354
|
-
source: zod.z.enum(["manual", "contact-sync", "callback"]),
|
|
355
|
-
/** null = permanent; a date = self-expiring exception. */
|
|
356
|
-
expiresAt: FirestoreTimestampSchema.nullable().optional(),
|
|
357
|
-
createdAt: FirestoreTimestampSchema
|
|
358
|
-
});
|
|
359
|
-
var OrganizationRecordSchema = zod.z.object({
|
|
360
|
-
id: zod.z.string(),
|
|
361
|
-
/** Display name of the organization */
|
|
362
|
-
name: zod.z.string().min(3).max(50),
|
|
363
|
-
/**
|
|
364
|
-
* Unique handle for the organization (e.g. voxpop.com/@mypodcast).
|
|
365
|
-
* Used for public URLs.
|
|
366
|
-
*/
|
|
367
|
-
slug: zod.z.string().min(3).max(30).regex(/^[a-z0-9-]+$/),
|
|
368
|
-
/** URL to avatar/logo */
|
|
369
|
-
avatarUrl: zod.z.string().url().optional(),
|
|
370
|
-
/** URL to the podcast RSS feed */
|
|
371
|
-
rssFeedUrl: zod.z.string().url().optional(),
|
|
372
|
-
/** External website URL */
|
|
373
|
-
websiteUrl: httpsUrl().optional(),
|
|
374
|
-
/** Description or tagline */
|
|
375
|
-
description: zod.z.string().optional(),
|
|
376
|
-
/** Owner ID (User ID) */
|
|
377
|
-
ownerId: zod.z.string(),
|
|
378
|
-
/** Server timestamp of creation */
|
|
379
|
-
createdAt: FirestoreTimestampSchema,
|
|
380
|
-
/** Verified domain (e.g., "acme.com") — enables auto-join, enterprise features */
|
|
381
|
-
domain: zod.z.string().nullable().optional(),
|
|
382
|
-
/** Whether the domain has been verified via DNS TXT record */
|
|
383
|
-
domainVerified: zod.z.boolean().default(false),
|
|
384
|
-
/** DNS verification token (stored server-side until verification completes) */
|
|
385
|
-
domainVerificationToken: zod.z.string().optional(),
|
|
386
|
-
/** Billing email — required for paid orgs, where invoices go */
|
|
387
|
-
billingEmail: zod.z.string().email().nullable().optional(),
|
|
388
|
-
/**
|
|
389
|
-
* Tier determines isolation and feature set. Orgs are meant to be paid
|
|
390
|
-
* (business or enterprise); free/pro exist on the enum for the individual track.
|
|
391
|
-
* Default is provisionally `business` (the entry paid tier) — it's assigned at
|
|
392
|
-
* creation with no subscription behind it yet, so it stays provisional until billing
|
|
393
|
-
* promotes/reconciles the org. See docs/tech-debt.md "Org tier billing reconciliation".
|
|
394
|
-
*/
|
|
395
|
-
tier: zod.z.enum(["free", "pro", "business", "enterprise"]).default("business"),
|
|
396
|
-
/** Stripe Customer ID */
|
|
397
|
-
stripeCustomerId: zod.z.string().optional(),
|
|
398
|
-
/** Subscription Status */
|
|
399
|
-
subscriptionStatus: zod.z.enum(["active", "trialing", "past_due", "canceled", "unpaid"]).optional()
|
|
400
|
-
});
|
|
401
|
-
var OrganizationMemberRecordSchema = zod.z.object({
|
|
402
|
-
orgId: zod.z.string(),
|
|
403
|
-
userId: zod.z.string(),
|
|
404
|
-
/** Role in the organization */
|
|
405
|
-
role: zod.z.enum(["owner", "admin", "member"]),
|
|
406
|
-
/** Server timestamp of joining */
|
|
407
|
-
joinedAt: FirestoreTimestampSchema,
|
|
408
|
-
invitedBy: zod.z.string().optional()
|
|
409
|
-
});
|
|
410
|
-
var OrgInviteRecordSchema = zod.z.object({
|
|
411
|
-
id: zod.z.string(),
|
|
412
|
-
orgId: zod.z.string(),
|
|
413
|
-
/** Email the invite was sent to */
|
|
414
|
-
email: zod.z.string().email(),
|
|
415
|
-
/** Role to assign on acceptance */
|
|
416
|
-
role: zod.z.enum(["admin", "member"]),
|
|
417
|
-
/** User ID of who sent the invite */
|
|
418
|
-
invitedBy: zod.z.string(),
|
|
419
|
-
/** Invite lifecycle status */
|
|
420
|
-
status: zod.z.enum(["pending", "accepted", "expired", "revoked"]).default("pending"),
|
|
421
|
-
/** Server timestamp of creation */
|
|
422
|
-
createdAt: FirestoreTimestampSchema,
|
|
423
|
-
/** When this invite expires */
|
|
424
|
-
expiresAt: FirestoreTimestampSchema
|
|
425
|
-
});
|
|
426
|
-
var ProfileViewBasicSchema = zod.z.object({
|
|
427
|
-
id: zod.z.string(),
|
|
428
|
-
handle: zod.z.string().nullable().optional(),
|
|
429
|
-
// `displayName` and `bio` are `.nullable()` — Firestore stores `null` for
|
|
430
|
-
// empty values on these fields (see users-dependencies.ts), and Zod's
|
|
431
|
-
// `.optional()` alone rejects `null`. This hit dashboard rendering on the
|
|
432
|
-
// Phase 3.1 HTTP cutover, when transport-layer Zod validation started
|
|
433
|
-
// actually exercising the wire shape. Consumers already use truthy
|
|
434
|
-
// checks / `??` / `||`, so widening the type to include `null` is safe.
|
|
435
|
-
displayName: zod.z.string().nullable().optional(),
|
|
436
|
-
avatarUrl: zod.z.string().nullable().optional(),
|
|
437
|
-
bio: zod.z.string().nullable().optional(),
|
|
438
|
-
/** Personal website link surfaced on the public profile. */
|
|
439
|
-
website: zod.z.string().nullable().optional(),
|
|
440
|
-
/** Public links (label + URL) shown under the bio. */
|
|
441
|
-
links: zod.z.array(zod.z.object({
|
|
442
|
-
label: zod.z.string(),
|
|
443
|
-
url: zod.z.string()
|
|
444
|
-
})).optional(),
|
|
445
|
-
/**
|
|
446
|
-
* AT Protocol identity, surfaced on the public profile only when the user
|
|
447
|
-
* opts in (`UserRecord.showBlueskyPublicly === true`). Projection happens
|
|
448
|
-
* in the user dependency layer; this schema simply allows the field.
|
|
449
|
-
*/
|
|
450
|
-
bluesky: zod.z.object({
|
|
451
|
-
handle: zod.z.string(),
|
|
452
|
-
did: zod.z.string()
|
|
453
|
-
}).optional(),
|
|
454
|
-
stats: zod.z.object({
|
|
455
|
-
followers: zod.z.number().default(0),
|
|
456
|
-
following: zod.z.number().default(0),
|
|
457
|
-
prompts: zod.z.number().default(0)
|
|
458
|
-
}).optional(),
|
|
459
|
-
badges: zod.z.array(zod.z.string()).optional(),
|
|
460
|
-
isVerified: zod.z.boolean().optional(),
|
|
461
|
-
createdAt: FirestoreTimestampSchema.optional()
|
|
462
|
-
});
|
|
463
|
-
function toProfileViewBasic(profile) {
|
|
464
|
-
const { id, handle, displayName, avatarUrl, bio, website, links, bluesky, showBlueskyPublicly, stats, badges, isVerified, createdAt } = profile;
|
|
465
|
-
return {
|
|
466
|
-
id,
|
|
467
|
-
handle,
|
|
468
|
-
displayName,
|
|
469
|
-
avatarUrl,
|
|
470
|
-
bio,
|
|
471
|
-
website,
|
|
472
|
-
links,
|
|
473
|
-
bluesky: showBlueskyPublicly ? bluesky : void 0,
|
|
474
|
-
stats,
|
|
475
|
-
badges,
|
|
476
|
-
isVerified,
|
|
477
|
-
createdAt
|
|
478
|
-
};
|
|
479
|
-
}
|
|
480
|
-
var ProfileViewDetailedSchema = ProfileViewBasicSchema.extend({
|
|
481
|
-
/** AT Protocol Identity link */
|
|
482
|
-
bluesky: zod.z.object({
|
|
483
|
-
handle: zod.z.string(),
|
|
484
|
-
did: zod.z.string()
|
|
485
|
-
}).optional(),
|
|
486
|
-
usageIntent: zod.z.string().nullable().optional(),
|
|
487
|
-
/** Hydrated RSS Data (fetched from sub-collection) */
|
|
488
|
-
rssSummary: zod.z.object({
|
|
489
|
-
title: zod.z.string().optional(),
|
|
490
|
-
description: zod.z.string().optional(),
|
|
491
|
-
items: zod.z.array(zod.z.object({
|
|
492
|
-
title: zod.z.string().optional(),
|
|
493
|
-
link: zod.z.string().optional(),
|
|
494
|
-
content: zod.z.string().optional(),
|
|
495
|
-
pubDate: zod.z.string().optional()
|
|
496
|
-
})).optional(),
|
|
497
|
-
lastFetchedAt: FirestoreTimestampSchema.optional()
|
|
498
|
-
}).optional(),
|
|
499
|
-
promptAudioUrl: zod.z.string().optional(),
|
|
500
|
-
/** @deprecated Use stats.prompts from ProfileViewBasic instead */
|
|
501
|
-
totalPrompts: zod.z.number().optional(),
|
|
502
|
-
totalReplies: zod.z.number().optional(),
|
|
503
|
-
favoritePromptId: zod.z.string().optional()
|
|
504
|
-
});
|
|
505
|
-
var ProfileViewSelfSchema = ProfileViewDetailedSchema.extend({
|
|
506
|
-
phoneNumber: zod.z.string().nullable().optional(),
|
|
507
|
-
email: zod.z.string().optional(),
|
|
508
|
-
lastSeenAt: FirestoreTimestampSchema.optional(),
|
|
509
|
-
lastActiveAt: FirestoreTimestampSchema.optional(),
|
|
510
|
-
unreadReplyCount: zod.z.number().default(0),
|
|
511
|
-
newReplierCount: zod.z.number().default(0),
|
|
512
|
-
/**
|
|
513
|
-
* Account tier from UserRecord — surfaced on the self profile so the
|
|
514
|
-
* client can gate paid features (e.g. the Performance dashboard tab).
|
|
515
|
-
* Optional for legacy docs without the field; consumers should treat
|
|
516
|
-
* missing as `'free'`.
|
|
517
|
-
*/
|
|
518
|
-
tier: zod.z.enum(["free", "creator_pro"]).optional(),
|
|
519
|
-
/**
|
|
520
|
-
* Surfaces the linked Bluesky identity (handle + DID) on the public profile
|
|
521
|
-
* when true. Persisted on UserRecord; exposed in self/detailed views so the
|
|
522
|
-
* settings form can render the toggle's current state.
|
|
523
|
-
*/
|
|
524
|
-
showBlueskyPublicly: zod.z.boolean().optional(),
|
|
525
|
-
settings: zod.z.object({
|
|
526
|
-
notifications: zod.z.boolean().optional(),
|
|
527
|
-
theme: zod.z.string().optional()
|
|
528
|
-
}).optional()
|
|
529
|
-
});
|
|
530
|
-
var ProfileViewAdminSchema = ProfileViewSelfSchema.extend({
|
|
531
|
-
blockedUsers: zod.z.array(zod.z.string()).optional(),
|
|
532
|
-
followers: zod.z.array(zod.z.string()).optional(),
|
|
533
|
-
following: zod.z.array(zod.z.string()).optional(),
|
|
534
|
-
reportCount: zod.z.number().optional(),
|
|
535
|
-
isBanned: zod.z.boolean().optional()
|
|
536
|
-
});
|
|
537
|
-
var ProfileViewSchema = ProfileViewAdminSchema;
|
|
538
|
-
var PromptViewSchema = zod.z.object({
|
|
539
|
-
/** AT Protocol URI (e.g. at://did:plc.../app.../123) */
|
|
540
|
-
uri: zod.z.string().optional(),
|
|
541
|
-
/** IPFS Content ID */
|
|
542
|
-
cid: zod.z.string().optional(),
|
|
543
|
-
/** The raw prompt data */
|
|
544
|
-
record: PromptRecordSchema,
|
|
545
|
-
/** The hydrated author profile */
|
|
546
|
-
author: ProfileViewSchema,
|
|
547
|
-
/** Total number of replies */
|
|
548
|
-
replyCount: zod.z.number().default(0),
|
|
549
|
-
likeCount: zod.z.number().default(0),
|
|
550
|
-
updatedAt: FirestoreTimestampSchema.optional(),
|
|
551
|
-
lastReplyAt: FirestoreTimestampSchema.optional(),
|
|
552
|
-
tags: zod.z.array(zod.z.string()).optional(),
|
|
553
|
-
visibility: zod.z.enum(["public", "private", "unlisted", "archived"]).default("public"),
|
|
554
|
-
analytics: zod.z.object({
|
|
555
|
-
views: zod.z.number().default(0),
|
|
556
|
-
listens: zod.z.number().default(0),
|
|
557
|
-
/**
|
|
558
|
-
* Mean engagementScore (1–10) across this prompt's `status: 'live'`
|
|
559
|
-
* replies that completed AI enrichment. `null` when no such replies
|
|
560
|
-
* exist (0 would alias a valid bottom-of-range score). Derived in
|
|
561
|
-
* hydration from the prompt doc's `engagementScoreSum / Count`.
|
|
562
|
-
*/
|
|
563
|
-
avgEngagementScore: zod.z.number().nullable().optional(),
|
|
564
|
-
/**
|
|
565
|
-
* Counts of `status: 'live'` AI-enriched replies grouped by sentiment.
|
|
566
|
-
* Keys lowercase by convention; source enum
|
|
567
|
-
* (`Positive | Neutral | Negative`) is mapped at the write site.
|
|
568
|
-
*/
|
|
569
|
-
sentimentBreakdown: zod.z.object({
|
|
570
|
-
positive: zod.z.number(),
|
|
571
|
-
neutral: zod.z.number(),
|
|
572
|
-
negative: zod.z.number()
|
|
573
|
-
}).optional()
|
|
574
|
-
}).optional(),
|
|
575
|
-
moderation: zod.z.object({
|
|
576
|
-
flagged: zod.z.boolean().default(false),
|
|
577
|
-
reason: zod.z.string().optional()
|
|
578
|
-
}).optional(),
|
|
579
|
-
// AI Enrichment Fields (Hydrated from Record but hidden from Record Schema)
|
|
580
|
-
aiLabels: zod.z.array(zod.z.string()).optional(),
|
|
581
|
-
aiSummary: zod.z.string().optional(),
|
|
582
|
-
aiStatus: zod.z.enum(["pending", "complete", "error"]).optional(),
|
|
583
|
-
aiError: zod.z.string().optional(),
|
|
584
|
-
transcription: zod.z.string().optional()
|
|
585
|
-
});
|
|
586
|
-
var PromptViewPublicSchema = PromptViewSchema.omit({
|
|
587
|
-
analytics: true,
|
|
588
|
-
moderation: true,
|
|
589
|
-
aiLabels: true,
|
|
590
|
-
aiSummary: true,
|
|
591
|
-
aiStatus: true,
|
|
592
|
-
aiError: true,
|
|
593
|
-
transcription: true
|
|
594
|
-
}).extend({
|
|
595
|
-
author: ProfileViewBasicSchema
|
|
596
|
-
});
|
|
597
|
-
function toPromptViewPublic(prompt) {
|
|
598
|
-
const _a = prompt, { analytics, moderation, aiLabels, aiSummary, aiStatus, aiError, transcription } = _a, rest = __objRest(_a, ["analytics", "moderation", "aiLabels", "aiSummary", "aiStatus", "aiError", "transcription"]);
|
|
599
|
-
return __spreadProps(__spreadValues({}, rest), {
|
|
600
|
-
author: toProfileViewBasic(rest.author)
|
|
601
|
-
});
|
|
602
|
-
}
|
|
603
|
-
var ReplyViewSchema = zod.z.object({
|
|
604
|
-
record: ReplyRecordSchema,
|
|
605
|
-
author: ProfileViewSchema,
|
|
606
|
-
recipient: ProfileViewSchema,
|
|
607
|
-
/** GCS Storage Path for audio file */
|
|
608
|
-
storagePath: zod.z.string().optional(),
|
|
609
|
-
duration: zod.z.number().optional(),
|
|
610
|
-
updatedAt: FirestoreTimestampSchema.optional(),
|
|
611
|
-
isRead: zod.z.boolean(),
|
|
612
|
-
readBy: zod.z.array(zod.z.string()).default([]),
|
|
613
|
-
isDeleted: zod.z.boolean().default(false),
|
|
614
|
-
reactions: zod.z.record(zod.z.string(), zod.z.number()).optional(),
|
|
615
|
-
moderation: zod.z.object({
|
|
616
|
-
flagged: zod.z.boolean().default(false),
|
|
617
|
-
reason: zod.z.string().optional()
|
|
618
|
-
}).optional(),
|
|
619
|
-
// AI Enrichment Fields (Hydrated from Record but hidden from Record Schema)
|
|
620
|
-
aiLabels: zod.z.array(zod.z.string()).optional(),
|
|
621
|
-
aiSummary: zod.z.string().optional(),
|
|
622
|
-
aiStatus: zod.z.enum(["pending", "complete", "error", "skipped_too_short"]).optional(),
|
|
623
|
-
aiError: zod.z.string().optional(),
|
|
624
|
-
transcription: zod.z.string().optional(),
|
|
625
|
-
sentiment: zod.z.enum(["Positive", "Negative", "Neutral"]).optional(),
|
|
626
|
-
/** Must match the widened enum in `ReplyRecordSchema.energyLevel`. */
|
|
627
|
-
energyLevel: zod.z.enum(["High", "Low", "Neutral"]).optional(),
|
|
628
|
-
engagementScore: zod.z.number().min(1).max(10).optional(),
|
|
629
|
-
// === Voice-isolation enrichment (lifted; see specs/ai-enrichment-split.md) ===
|
|
630
|
-
//
|
|
631
|
-
// `enhancedAudioUrl` is the only one of these the public view keeps —
|
|
632
|
-
// it replaces `audioUrl` for downstream players when present.
|
|
633
|
-
// `enhancedStoragePath` is private (storage paths are server-side
|
|
634
|
-
// bookkeeping).
|
|
635
|
-
enhancedAudioUrl: zod.z.string().url().optional(),
|
|
636
|
-
enhancedStoragePath: zod.z.string().optional(),
|
|
637
|
-
// === Social-share video enrichment (lifted; creator-only) ===
|
|
638
|
-
//
|
|
639
|
-
// All `socialVideo*` fields are stripped by `toReplyViewPublic` —
|
|
640
|
-
// the URL points at a generated artifact the creator may share to
|
|
641
|
-
// social media, NOT at content the reply page should render. Status /
|
|
642
|
-
// error / source-audio are job-tracking state.
|
|
643
|
-
socialVideoUrl: zod.z.string().url().optional(),
|
|
644
|
-
socialVideoStoragePath: zod.z.string().optional(),
|
|
645
|
-
socialVideoStatus: zod.z.enum(["pending", "complete", "error"]).optional(),
|
|
646
|
-
socialVideoError: zod.z.string().optional(),
|
|
647
|
-
socialVideoSourceAudio: zod.z.string().optional(),
|
|
648
|
-
/** @private Confirmed listener phone number (never exposed publicly) */
|
|
649
|
-
listenerPhoneNumber: zod.z.string().regex(/^\+[1-9]\d{1,14}$/).optional(),
|
|
650
|
-
/**
|
|
651
|
-
* @private Per-viewer private notes about this reply (CRM enrichment).
|
|
652
|
-
* Lifted into the view from `enrichments/replies/{id}.notes` by the
|
|
653
|
-
* hydrator when the viewer is the prompt author. Never populated for
|
|
654
|
-
* non-author viewers; defensively stripped by `toReplyViewPublic`.
|
|
655
|
-
*/
|
|
656
|
-
notes: zod.z.string().optional()
|
|
657
|
-
});
|
|
658
|
-
var ReplyViewPublicSchema = ReplyViewSchema.omit({
|
|
659
|
-
listenerPhoneNumber: true,
|
|
660
|
-
notes: true,
|
|
661
|
-
// AI cluster — only `transcription` survives.
|
|
662
|
-
aiStatus: true,
|
|
663
|
-
aiError: true,
|
|
664
|
-
aiSummary: true,
|
|
665
|
-
aiLabels: true,
|
|
666
|
-
sentiment: true,
|
|
667
|
-
energyLevel: true,
|
|
668
|
-
engagementScore: true,
|
|
669
|
-
// Voice isolation — keep enhancedAudioUrl, strip the path.
|
|
670
|
-
enhancedStoragePath: true,
|
|
671
|
-
// Social-video — entire cluster is creator-only.
|
|
672
|
-
socialVideoUrl: true,
|
|
673
|
-
socialVideoStoragePath: true,
|
|
674
|
-
socialVideoStatus: true,
|
|
675
|
-
socialVideoError: true,
|
|
676
|
-
socialVideoSourceAudio: true
|
|
677
|
-
});
|
|
678
|
-
function toReplyViewPublic(reply) {
|
|
679
|
-
const _a = reply, {
|
|
680
|
-
listenerPhoneNumber,
|
|
681
|
-
notes,
|
|
682
|
-
aiStatus: aiStatus,
|
|
683
|
-
aiError,
|
|
684
|
-
aiSummary,
|
|
685
|
-
aiLabels,
|
|
686
|
-
sentiment,
|
|
687
|
-
energyLevel,
|
|
688
|
-
engagementScore,
|
|
689
|
-
enhancedStoragePath: enhancedStoragePath,
|
|
690
|
-
socialVideoUrl: socialVideoUrl,
|
|
691
|
-
socialVideoStoragePath,
|
|
692
|
-
socialVideoStatus,
|
|
693
|
-
socialVideoError,
|
|
694
|
-
socialVideoSourceAudio
|
|
695
|
-
} = _a, publicReply = __objRest(_a, [
|
|
696
|
-
"listenerPhoneNumber",
|
|
697
|
-
"notes",
|
|
698
|
-
// AI cluster (only transcription stays public)
|
|
699
|
-
"aiStatus",
|
|
700
|
-
"aiError",
|
|
701
|
-
"aiSummary",
|
|
702
|
-
"aiLabels",
|
|
703
|
-
"sentiment",
|
|
704
|
-
"energyLevel",
|
|
705
|
-
"engagementScore",
|
|
706
|
-
// Voice isolation (only enhancedAudioUrl stays public)
|
|
707
|
-
"enhancedStoragePath",
|
|
708
|
-
// Social-video (entire cluster is creator-only)
|
|
709
|
-
"socialVideoUrl",
|
|
710
|
-
"socialVideoStoragePath",
|
|
711
|
-
"socialVideoStatus",
|
|
712
|
-
"socialVideoError",
|
|
713
|
-
"socialVideoSourceAudio"
|
|
714
|
-
]);
|
|
715
|
-
return publicReply;
|
|
716
|
-
}
|
|
717
|
-
var OrganizationViewSchema = zod.z.object({
|
|
718
|
-
record: OrganizationRecordSchema,
|
|
719
|
-
memberCount: zod.z.number().default(1),
|
|
720
|
-
currentUserRole: zod.z.enum(["owner", "admin", "member"]).optional()
|
|
721
|
-
});
|
|
722
|
-
var OrganizationMemberViewSchema = zod.z.object({
|
|
723
|
-
record: OrganizationMemberRecordSchema,
|
|
724
|
-
profile: ProfileViewBasicSchema
|
|
725
|
-
});
|
|
726
|
-
var OrgInviteViewSchema = zod.z.object({
|
|
727
|
-
record: OrgInviteRecordSchema,
|
|
728
|
-
/** Display name of the user who sent the invite */
|
|
729
|
-
inviterName: zod.z.string().optional(),
|
|
730
|
-
/** Name of the organization */
|
|
731
|
-
orgName: zod.z.string()
|
|
732
|
-
});
|
|
733
|
-
var PromptRepliersSchema = zod.z.object({
|
|
734
|
-
promptId: zod.z.string(),
|
|
735
|
-
repliers: zod.z.record(zod.z.string(), zod.z.object({
|
|
736
|
-
firstReplyAt: FirestoreTimestampSchema,
|
|
737
|
-
lastReplyAt: FirestoreTimestampSchema,
|
|
738
|
-
replyCount: zod.z.number()
|
|
739
|
-
}))
|
|
740
|
-
});
|
|
741
|
-
var PromptWithRepliesSchema = PromptViewSchema.extend({
|
|
742
|
-
replies: zod.z.array(ReplyViewSchema)
|
|
743
|
-
});
|
|
744
|
-
var ReplierSchema = zod.z.object({
|
|
745
|
-
handle: zod.z.string(),
|
|
746
|
-
/** ISO date string */
|
|
747
|
-
lastReplyDate: zod.z.string(),
|
|
748
|
-
/** ISO date string */
|
|
749
|
-
firstReplyAt: zod.z.string(),
|
|
750
|
-
totalReplies: zod.z.number()
|
|
751
|
-
});
|
|
752
|
-
var HandleResolutionSchema = zod.z.discriminatedUnion("type", [
|
|
753
|
-
// Public endpoint (`GET /resolve/:handle`) — project to the basic shape so
|
|
754
|
-
// PII/admin fields (email, phoneNumber, settings, blockedUsers, …) never
|
|
755
|
-
// cross the public API boundary. See `toProfileViewBasic`.
|
|
756
|
-
zod.z.object({ type: zod.z.literal("user"), profile: ProfileViewBasicSchema }),
|
|
757
|
-
zod.z.object({ type: zod.z.literal("org"), org: OrganizationViewSchema })
|
|
758
|
-
]);
|
|
759
|
-
var UserProfileDataSchema = zod.z.object({
|
|
760
|
-
// Public endpoint (`GET /users/:handle/profile`) — basic shape only, so the
|
|
761
|
-
// owner's PII/admin fields never serialize to anonymous callers.
|
|
762
|
-
profileUser: ProfileViewBasicSchema,
|
|
763
|
-
// Each prompt's nested `author` is the profile owner, hydrated from the
|
|
764
|
-
// wide admin profile (`getPromptsForUser` prefetches via getUserDataByUid).
|
|
765
|
-
// Use the PUBLIC prompt/reply shapes so that nested author PII (email,
|
|
766
|
-
// phoneNumber, settings, …) and owner-only prompt enrichment never leak.
|
|
767
|
-
allPromptsWithReplies: zod.z.array(PromptViewPublicSchema.extend({
|
|
768
|
-
replies: zod.z.array(ReplyViewPublicSchema)
|
|
769
|
-
})),
|
|
770
|
-
repliers: zod.z.array(ReplierSchema)
|
|
771
|
-
});
|
|
772
|
-
var RssSummarySchema = zod.z.object({
|
|
773
|
-
title: zod.z.string().optional(),
|
|
774
|
-
description: zod.z.string().optional(),
|
|
775
|
-
image: zod.z.string().optional(),
|
|
776
|
-
link: zod.z.string().optional(),
|
|
777
|
-
items: zod.z.array(zod.z.object({
|
|
778
|
-
title: zod.z.string().optional(),
|
|
779
|
-
link: zod.z.string().optional(),
|
|
780
|
-
content: zod.z.string().optional(),
|
|
781
|
-
pubDate: zod.z.string().optional()
|
|
782
|
-
})).optional(),
|
|
783
|
-
lastFetchedAt: FirestoreTimestampSchema.optional()
|
|
784
|
-
});
|
|
785
|
-
var OrgProfileDataSchema = zod.z.object({
|
|
786
|
-
org: OrganizationViewSchema,
|
|
787
|
-
prompts: zod.z.array(PromptViewSchema),
|
|
788
|
-
rssSummary: RssSummarySchema.nullable()
|
|
789
|
-
});
|
|
790
|
-
var EnrichedReplierSchema = zod.z.object({
|
|
791
|
-
profile: ProfileViewBasicSchema,
|
|
792
|
-
totalReplies: zod.z.number(),
|
|
793
|
-
/** ISO date string */
|
|
794
|
-
lastReplyDate: zod.z.string(),
|
|
795
|
-
/** ISO date string */
|
|
796
|
-
firstReplyAt: zod.z.string(),
|
|
797
|
-
/** Phone number for anonymous repliers (from Firebase Auth, only visible to prompt author) */
|
|
798
|
-
phoneNumber: zod.z.string().optional()
|
|
75
|
+
var ProcessingViewSchema = zod.z.object({
|
|
76
|
+
transcribe: ProcessingStageStatusSchema.optional(),
|
|
77
|
+
denoise: ProcessingStageStatusSchema.optional()
|
|
799
78
|
});
|
|
800
79
|
|
|
801
80
|
// types/audio.ts
|
|
@@ -809,7 +88,7 @@ var ReplyRefSchema = zod.z.object({
|
|
|
809
88
|
});
|
|
810
89
|
var AudioEmbedSchema = zod.z.object({
|
|
811
90
|
$type: zod.z.literal("dev.antiphony.embed.audio"),
|
|
812
|
-
/** The audio bytes as a content-addressed
|
|
91
|
+
/** The audio bytes as a content-addressed blob ref (`ref.$link` = CID). */
|
|
813
92
|
audio: BlobRefSchema,
|
|
814
93
|
/** Duration in MILLISECONDS (platform-wide unit; not seconds). */
|
|
815
94
|
durationMs: zod.z.number().int().min(0).optional(),
|
|
@@ -839,11 +118,26 @@ var AudioEmbedViewSchema = zod.z.object({
|
|
|
839
118
|
alt: zod.z.string().max(1e4).optional(),
|
|
840
119
|
waveform: zod.z.array(zod.z.number().int().min(0).max(100)).max(1e3).optional(),
|
|
841
120
|
/** Lifted from the transcript enrichment record; absent until transcription completes. */
|
|
842
|
-
transcript: TimedTranscriptSchema.optional()
|
|
121
|
+
transcript: TimedTranscriptSchema.optional(),
|
|
122
|
+
/**
|
|
123
|
+
* Per-stage audio-processing status (transcribe / denoise), when the app
|
|
124
|
+
* opted into processing on create. Absent otherwise. A `pending` stage
|
|
125
|
+
* means the client should poll (or re-render) for the result. When
|
|
126
|
+
* `denoise === 'ready'`, `url` above already resolves to the cleaned
|
|
127
|
+
* audio variant. See `types/processing.ts`.
|
|
128
|
+
*/
|
|
129
|
+
processing: ProcessingViewSchema.optional()
|
|
843
130
|
});
|
|
844
131
|
var AudioPostRecordSchema = zod.z.object({
|
|
845
132
|
/** Storage id (rkey/doc id). */
|
|
846
133
|
id: zod.z.string(),
|
|
134
|
+
/**
|
|
135
|
+
* Content CID of the canonical lexicon record (CIDv1, dag-cbor, sha2-256
|
|
136
|
+
* — the AT Protocol record-CID rule). Computed at write time over the
|
|
137
|
+
* lexicon projection (public fields only, NOT the storage/tenancy fields
|
|
138
|
+
* below), so StrongRefs built from it are verifiable content addresses.
|
|
139
|
+
*/
|
|
140
|
+
cid: zod.z.string(),
|
|
847
141
|
// --- Tenancy + facets (storage-indexed; NOT in the lexicon) ---
|
|
848
142
|
/** Origin app that created this record — the multi-tenant isolation key. */
|
|
849
143
|
originAppId: zod.z.string(),
|
|
@@ -855,6 +149,30 @@ var AudioPostRecordSchema = zod.z.object({
|
|
|
855
149
|
orgId: zod.z.string().nullable().optional(),
|
|
856
150
|
/** Denormalized from `reply` presence: `reply` set ⇒ 'reply', else 'prompt'. */
|
|
857
151
|
kind: zod.z.enum(["prompt", "reply"]),
|
|
152
|
+
/**
|
|
153
|
+
* Branch participant pair (author ids) for reply gating — the parties to a
|
|
154
|
+
* reply's sub-thread: the creator (thread-root author) + the responder who
|
|
155
|
+
* opened the branch. Set on replies (deduped, 1–2 ids); absent on prompts
|
|
156
|
+
* (a prompt's repliers are the app's audience policy, not a fixed pair).
|
|
157
|
+
* Inherited down the branch so reply gating is an O(1) field check, never a
|
|
158
|
+
* thread walk.
|
|
159
|
+
*/
|
|
160
|
+
threadParticipants: zod.z.array(zod.z.string()).optional(),
|
|
161
|
+
/**
|
|
162
|
+
* Author of this reply's thread ROOT (the prompt) — the reply's recipient,
|
|
163
|
+
* the person whose "replies to me" feed it lands in. Denormalized at write
|
|
164
|
+
* time so "replies whose root author is X" is a cheap composite-index query
|
|
165
|
+
* (see `queryByRootAuthor`). Set on replies (`kind === 'reply'`); absent on
|
|
166
|
+
* prompts. Storage-layer facet, NOT in the public lexicon or the record CID.
|
|
167
|
+
*/
|
|
168
|
+
rootAuthorId: zod.z.string().optional(),
|
|
169
|
+
/**
|
|
170
|
+
* Async audio-processing state (transcribe / denoise), present iff the app
|
|
171
|
+
* opted into processing on create. Mutated by the processing worker after
|
|
172
|
+
* the post is created — storage-layer, NOT in the lexicon or the record
|
|
173
|
+
* CID. See `types/processing.ts`.
|
|
174
|
+
*/
|
|
175
|
+
processing: ProcessingStateSchema.optional(),
|
|
858
176
|
// --- Lexicon fields (public contract) ---
|
|
859
177
|
/** User-authored text (bsky-semantic). May be empty for pure-audio posts. NEVER the transcript. */
|
|
860
178
|
text: zod.z.string().max(3e3),
|
|
@@ -873,10 +191,11 @@ var AudioPostRecordSchema = zod.z.object({
|
|
|
873
191
|
}).refine(
|
|
874
192
|
// `kind` is denormalized from `reply` presence at write time; enforce the
|
|
875
193
|
// invariant so an inconsistent record can't be written or read silently.
|
|
876
|
-
// A reply has `reply
|
|
877
|
-
|
|
194
|
+
// A reply has `reply`, no `title`, and a stamped `rootAuthorId` (its
|
|
195
|
+
// recipient facet); a prompt has none of those.
|
|
196
|
+
(r) => r.kind === "reply" ? !!r.reply && r.title === void 0 && r.rootAuthorId !== void 0 : !r.reply && r.rootAuthorId === void 0,
|
|
878
197
|
{
|
|
879
|
-
message: "kind must match reply presence: 'reply' \u21D2 reply set
|
|
198
|
+
message: "kind must match reply presence: 'reply' \u21D2 reply set, no title, rootAuthorId set; 'prompt' \u21D2 no reply, no rootAuthorId",
|
|
880
199
|
path: ["kind"]
|
|
881
200
|
}
|
|
882
201
|
);
|
|
@@ -898,7 +217,15 @@ var ActorProfileRecordSchema = zod.z.object({
|
|
|
898
217
|
});
|
|
899
218
|
var ViewerStateSchema = zod.z.object({
|
|
900
219
|
/** True when the authenticated caller authored this post. */
|
|
901
|
-
isAuthor: zod.z.boolean().default(false)
|
|
220
|
+
isAuthor: zod.z.boolean().default(false),
|
|
221
|
+
/**
|
|
222
|
+
* Whether the caller may reply to this post (reply gating, §6). A prompt is
|
|
223
|
+
* repliable by any authenticated viewer (the app's audience-policy default);
|
|
224
|
+
* a reply only by its branch participants (`{ creator, branch responder }`).
|
|
225
|
+
*/
|
|
226
|
+
canReply: zod.z.boolean().default(false),
|
|
227
|
+
/** Why `canReply` is false, when it is (omitted when the caller can reply). */
|
|
228
|
+
replyDisabledReason: zod.z.enum(["unauthenticated", "not_a_participant"]).optional()
|
|
902
229
|
});
|
|
903
230
|
var PostRecordPublicSchema = zod.z.object({
|
|
904
231
|
text: zod.z.string(),
|
|
@@ -911,9 +238,13 @@ var PostRecordPublicSchema = zod.z.object({
|
|
|
911
238
|
var AudioPostViewSchema = zod.z.object({
|
|
912
239
|
/** at:// URI (or internal ref) identifying the post. */
|
|
913
240
|
uri: zod.z.string(),
|
|
914
|
-
|
|
241
|
+
/** Content CID of the canonical record (see `AudioPostRecordSchema.cid`). */
|
|
242
|
+
cid: zod.z.string(),
|
|
915
243
|
kind: zod.z.enum(["prompt", "reply"]),
|
|
916
|
-
|
|
244
|
+
/** The acting actor's app-scoped id — an opaque attribution ref, not a profile. */
|
|
245
|
+
authorId: zod.z.string(),
|
|
246
|
+
/** The author's app-asserted AT Protocol DID, when the caller provided one. */
|
|
247
|
+
authorDid: zod.z.string().optional(),
|
|
917
248
|
record: PostRecordPublicSchema,
|
|
918
249
|
/** Hydrated audio embed (signed URL + lifted transcript). */
|
|
919
250
|
embed: AudioEmbedViewSchema.optional(),
|
|
@@ -933,7 +264,14 @@ var CreateAudioPostRequestSchema = zod.z.object({
|
|
|
933
264
|
/** BCP-47 language tags. */
|
|
934
265
|
langs: zod.z.array(zod.z.string()).max(3).optional(),
|
|
935
266
|
/** Author self-label values (content warnings). */
|
|
936
|
-
selfLabels: zod.z.array(zod.z.string()).optional()
|
|
267
|
+
selfLabels: zod.z.array(zod.z.string()).optional(),
|
|
268
|
+
/**
|
|
269
|
+
* Opt-in audio processing for this post's audio (transcribe / denoise).
|
|
270
|
+
* Both default off. Stages the deployment can't provide come back marked
|
|
271
|
+
* `skipped` on the view rather than failing the create. See
|
|
272
|
+
* `types/processing.ts`.
|
|
273
|
+
*/
|
|
274
|
+
processing: ProcessingRequestSchema.optional()
|
|
937
275
|
}).refine((d) => !(d.reply && d.title), {
|
|
938
276
|
message: "Replies cannot have a title",
|
|
939
277
|
path: ["title"]
|
|
@@ -941,141 +279,22 @@ var CreateAudioPostRequestSchema = zod.z.object({
|
|
|
941
279
|
message: "Post must have text or an audio embed",
|
|
942
280
|
path: ["text"]
|
|
943
281
|
});
|
|
944
|
-
var
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
// (Record-level schema stays unbounded so any pre-existing longer values
|
|
949
|
-
// still read cleanly — this only gates new writes.)
|
|
950
|
-
title: zod.z.string().min(3).max(80),
|
|
951
|
-
description: zod.z.string().max(200).optional(),
|
|
952
|
-
audioUrl: zod.z.string().url().or(zod.z.literal("")),
|
|
953
|
-
setAsGreeting: zod.z.union([zod.z.boolean(), zod.z.string().transform((val) => val === "true")]).optional(),
|
|
954
|
-
/** Explicit org context override (normally inferred from auth.currentOrg) */
|
|
955
|
-
orgId: zod.z.string().nullable().optional()
|
|
956
|
-
});
|
|
957
|
-
var UpdateProfileRequestSchema = zod.z.object({
|
|
958
|
-
handle: zod.z.string().min(3).max(20).regex(/^[a-zA-Z0-9_]+$/).optional(),
|
|
959
|
-
displayName: zod.z.string().max(50).optional(),
|
|
960
|
-
bio: zod.z.string().max(160).optional(),
|
|
961
|
-
avatarUrl: zod.z.string().url().nullable().optional(),
|
|
962
|
-
usageIntent: zod.z.string().max(200).nullable().optional(),
|
|
963
|
-
/**
|
|
964
|
-
* Personal website surfaced on the public profile. Accepts a URL, empty
|
|
965
|
-
* string, or null from the client; normalizes empty string → null so the
|
|
966
|
-
* value stored on `UserRecord` (which requires `.url() | null`) round-trips
|
|
967
|
-
* cleanly through `UserRecordSchema.parse` on subsequent reads.
|
|
968
|
-
*/
|
|
969
|
-
website: zod.z.union([zod.z.string().url(), zod.z.literal(""), zod.z.null()]).optional().transform((v) => v === "" ? null : v),
|
|
970
|
-
/** Up to 5 public links (label + URL) shown under the bio. */
|
|
971
|
-
links: zod.z.array(zod.z.object({
|
|
972
|
-
label: zod.z.string().min(1).max(40),
|
|
973
|
-
url: zod.z.string().url()
|
|
974
|
-
})).max(5).optional(),
|
|
975
|
-
/** When true, surfaces the linked Bluesky identity on the public profile. */
|
|
976
|
-
showBlueskyPublicly: zod.z.boolean().optional()
|
|
977
|
-
});
|
|
978
|
-
var FcmTokenRequestSchema = zod.z.object({
|
|
979
|
-
// FCM registration tokens are typically ~163–200 chars; Google's docs
|
|
980
|
-
// don't publish a hard max but 4096 is a safe upper bound that prevents
|
|
981
|
-
// multi-MB payloads while accommodating any plausible FCM token format.
|
|
982
|
-
token: zod.z.string().min(1).max(4096)
|
|
983
|
-
});
|
|
984
|
-
var BadgeResetRequestSchema = zod.z.object({
|
|
985
|
-
type: zod.z.enum(["new_replier", "unread_reply"])
|
|
986
|
-
});
|
|
987
|
-
var CreateOrgRequestSchema = zod.z.object({
|
|
988
|
-
name: zod.z.string().min(3).max(50),
|
|
989
|
-
slug: zod.z.string().min(3).max(30).regex(/^[a-z0-9-]+$/),
|
|
990
|
-
avatarUrl: zod.z.string().url().optional(),
|
|
991
|
-
rssFeedUrl: zod.z.string().url().optional(),
|
|
992
|
-
websiteUrl: zod.z.string().url().optional(),
|
|
993
|
-
// 500 chars — enough for a multi-sentence blurb, prevents multi-MB writes.
|
|
994
|
-
description: zod.z.string().max(500).optional()
|
|
282
|
+
var PatchAudioPostRequestSchema = zod.z.object({
|
|
283
|
+
/** Opt-in audio processing to (re)run for this post's audio. Required — a
|
|
284
|
+
* PATCH with no processing request is a no-op and rejected as invalid. */
|
|
285
|
+
processing: ProcessingRequestSchema
|
|
995
286
|
});
|
|
996
|
-
var UpdateOrgRequestSchema = zod.z.object({
|
|
997
|
-
name: zod.z.string().min(3).max(50).optional(),
|
|
998
|
-
slug: zod.z.string().min(3).max(30).regex(/^[a-z0-9-]+$/).optional(),
|
|
999
|
-
// 500 chars — matches CreateOrgRequestSchema.description.
|
|
1000
|
-
description: zod.z.string().max(500).optional(),
|
|
1001
|
-
avatarUrl: zod.z.string().url().nullable().optional(),
|
|
1002
|
-
rssFeedUrl: zod.z.string().url().nullable().optional(),
|
|
1003
|
-
websiteUrl: zod.z.string().url().nullable().optional(),
|
|
1004
|
-
billingEmail: zod.z.string().email().nullable().optional(),
|
|
1005
|
-
// 253 chars — the DNS spec maximum for a fully-qualified domain name.
|
|
1006
|
-
domain: zod.z.string().max(253).nullable().optional()
|
|
1007
|
-
});
|
|
1008
|
-
var CreateOrgInviteRequestSchema = zod.z.object({
|
|
1009
|
-
email: zod.z.string().email(),
|
|
1010
|
-
role: zod.z.enum(["admin", "member"])
|
|
1011
|
-
});
|
|
1012
|
-
var UpdateMemberRoleRequestSchema = zod.z.object({
|
|
1013
|
-
role: zod.z.enum(["admin", "member"])
|
|
1014
|
-
});
|
|
1015
|
-
var SwitchOrgRequestSchema = zod.z.object({
|
|
1016
|
-
/** orgId to switch to, or null to switch to personal context */
|
|
1017
|
-
orgId: zod.z.string().nullable()
|
|
1018
|
-
});
|
|
1019
|
-
var ConnectorConfigInputSchema = ConnectorConfigRecordSchema.omit({
|
|
1020
|
-
connectorType: true,
|
|
1021
|
-
ownerId: true,
|
|
1022
|
-
status: true,
|
|
1023
|
-
createdAt: true,
|
|
1024
|
-
updatedAt: true
|
|
1025
|
-
});
|
|
1026
|
-
var ConnectorConfigUpdateSchema = ConnectorConfigInputSchema.partial();
|
|
1027
|
-
var PersonNotesUpdateSchema = zod.z.object({
|
|
1028
|
-
notes: zod.z.string().max(1e4).optional(),
|
|
1029
|
-
tags: zod.z.array(zod.z.string().max(64)).max(50).optional()
|
|
1030
|
-
});
|
|
1031
|
-
var PersonMergeRequestSchema = zod.z.object({
|
|
1032
|
-
alternateUid: zod.z.string().min(1)
|
|
1033
|
-
});
|
|
1034
|
-
var ScreeningRuleInputSchema = zod.z.object({
|
|
1035
|
-
e164: zod.z.string().regex(/^\+[1-9]\d{6,14}$/, "Must be an E.164 phone number"),
|
|
1036
|
-
label: zod.z.string().max(120).nullable().optional(),
|
|
1037
|
-
action: zod.z.enum(["allow", "screen"]),
|
|
1038
|
-
expiresAt: zod.z.union([zod.z.string(), zod.z.number()]).nullable().optional().refine((v) => v == null || !Number.isNaN(new Date(v).getTime()), {
|
|
1039
|
-
message: "Must be a valid ISO date string or epoch-ms timestamp"
|
|
1040
|
-
})
|
|
1041
|
-
});
|
|
1042
|
-
var ScreeningRuleUpdateSchema = ScreeningRuleInputSchema.partial();
|
|
1043
|
-
var UpdateReplyStatusRequestSchema = zod.z.object({
|
|
1044
|
-
status: zod.z.enum(["live", "archived", "deleted"])
|
|
1045
|
-
});
|
|
1046
|
-
var BulkReplyActionRequestSchema = zod.z.object({
|
|
1047
|
-
replyIds: zod.z.array(zod.z.string()).min(1).max(100),
|
|
1048
|
-
action: zod.z.enum(["markRead", "archive", "delete", "restore"])
|
|
1049
|
-
});
|
|
1050
|
-
var PublicProfileDtoSchema = ProfileViewBasicSchema.extend({
|
|
1051
|
-
bluesky: zod.z.object({
|
|
1052
|
-
handle: zod.z.string(),
|
|
1053
|
-
did: zod.z.string()
|
|
1054
|
-
}).optional(),
|
|
1055
|
-
rssFeedUrl: zod.z.string().nullable().optional()
|
|
1056
|
-
});
|
|
1057
|
-
var PublicReplyDtoSchema = zod.z.object({
|
|
1058
|
-
id: zod.z.string(),
|
|
1059
|
-
audioUrl: zod.z.string().url(),
|
|
1060
|
-
duration: zod.z.number().optional(),
|
|
1061
|
-
createdAt: FirestoreTimestampSchema,
|
|
1062
|
-
transcription: zod.z.string().optional(),
|
|
1063
|
-
sentiment: zod.z.enum(["Positive", "Negative", "Neutral"]).optional(),
|
|
1064
|
-
aiSummary: zod.z.string().optional(),
|
|
1065
|
-
author: PublicProfileDtoSchema
|
|
1066
|
-
});
|
|
1067
|
-
var ActorViewSchema = ProfileViewSelfSchema;
|
|
1068
287
|
|
|
1069
288
|
// nsid.ts
|
|
1070
289
|
var NSID = {
|
|
1071
|
-
//
|
|
1072
|
-
|
|
1073
|
-
Reply: "com.voxpop.audio.reply",
|
|
1074
|
-
Profile: "com.voxpop.actor.profile",
|
|
1075
|
-
// Antiphony canonical record types (dev.antiphony.*). Added additively in
|
|
1076
|
-
// Stream 1; see lexicons/dev/antiphony/ + packages/shared/types/audio.ts.
|
|
290
|
+
// Antiphony canonical record types (dev.antiphony.*).
|
|
291
|
+
// See lexicons/dev/antiphony/ + packages/shared/types/audio.ts.
|
|
1077
292
|
AudioPost: "dev.antiphony.audio.post",
|
|
1078
293
|
AudioTranscript: "dev.antiphony.audio.transcript",
|
|
294
|
+
// Portable lexicon only — the core never stores actor profiles; the
|
|
295
|
+
// caller BFF is the sole authority for profile data (see
|
|
296
|
+
// specs/core-bff-boundary.md, "actor.profile lexicon"). Hence no
|
|
297
|
+
// COLLECTIONS entry below.
|
|
1079
298
|
ActorProfile: "dev.antiphony.actor.profile"
|
|
1080
299
|
};
|
|
1081
300
|
var EMBED_NSID = {
|
|
@@ -1083,19 +302,10 @@ var EMBED_NSID = {
|
|
|
1083
302
|
RecordWithAudio: "dev.antiphony.embed.recordWithAudio"
|
|
1084
303
|
};
|
|
1085
304
|
var COLLECTIONS = {
|
|
1086
|
-
|
|
1087
|
-
[NSID.Reply]: "replies",
|
|
1088
|
-
[NSID.Profile]: "users",
|
|
1089
|
-
// Antiphony: one post collection + the transcript enrichment namespace.
|
|
305
|
+
// One post collection + the transcript enrichment namespace.
|
|
1090
306
|
[NSID.AudioPost]: "posts",
|
|
1091
|
-
[NSID.AudioTranscript]: "audio_transcripts"
|
|
1092
|
-
[NSID.ActorProfile]: "users"
|
|
307
|
+
[NSID.AudioTranscript]: "audio_transcripts"
|
|
1093
308
|
};
|
|
1094
|
-
function nsidForCollection(collection) {
|
|
1095
|
-
const entries = Object.entries(COLLECTIONS);
|
|
1096
|
-
const match = entries.find(([, col]) => col === collection);
|
|
1097
|
-
return match == null ? void 0 : match[0];
|
|
1098
|
-
}
|
|
1099
309
|
|
|
1100
310
|
// errors/index.ts
|
|
1101
311
|
var ServiceError = class extends Error {
|
|
@@ -1187,90 +397,35 @@ function reportError(err, context) {
|
|
|
1187
397
|
}
|
|
1188
398
|
|
|
1189
399
|
exports.ActorProfileRecordSchema = ActorProfileRecordSchema;
|
|
1190
|
-
exports.ActorViewSchema = ActorViewSchema;
|
|
1191
400
|
exports.AudioEmbedSchema = AudioEmbedSchema;
|
|
1192
401
|
exports.AudioEmbedViewSchema = AudioEmbedViewSchema;
|
|
1193
402
|
exports.AudioPostRecordSchema = AudioPostRecordSchema;
|
|
1194
403
|
exports.AudioPostViewSchema = AudioPostViewSchema;
|
|
1195
|
-
exports.BadgeResetRequestSchema = BadgeResetRequestSchema;
|
|
1196
404
|
exports.BlobRefSchema = BlobRefSchema;
|
|
1197
|
-
exports.BulkReplyActionRequestSchema = BulkReplyActionRequestSchema;
|
|
1198
405
|
exports.COLLECTIONS = COLLECTIONS;
|
|
1199
|
-
exports.CallForwardingConfigSchema = CallForwardingConfigSchema;
|
|
1200
406
|
exports.ConflictError = ConflictError;
|
|
1201
|
-
exports.ConnectorConfigInputSchema = ConnectorConfigInputSchema;
|
|
1202
|
-
exports.ConnectorConfigRecordSchema = ConnectorConfigRecordSchema;
|
|
1203
|
-
exports.ConnectorConfigUpdateSchema = ConnectorConfigUpdateSchema;
|
|
1204
|
-
exports.ConnectorStatusSchema = ConnectorStatusSchema;
|
|
1205
|
-
exports.ConnectorTypeSchema = ConnectorTypeSchema;
|
|
1206
407
|
exports.CreateAudioPostRequestSchema = CreateAudioPostRequestSchema;
|
|
1207
|
-
exports.CreateOrgInviteRequestSchema = CreateOrgInviteRequestSchema;
|
|
1208
|
-
exports.CreateOrgRequestSchema = CreateOrgRequestSchema;
|
|
1209
|
-
exports.CreatePromptRequestSchema = CreatePromptRequestSchema;
|
|
1210
408
|
exports.EMBED_NSID = EMBED_NSID;
|
|
1211
|
-
exports.EnrichedReplierSchema = EnrichedReplierSchema;
|
|
1212
|
-
exports.FcmTokenRequestSchema = FcmTokenRequestSchema;
|
|
1213
409
|
exports.FirestoreTimestampSchema = FirestoreTimestampSchema;
|
|
1214
410
|
exports.ForbiddenError = ForbiddenError;
|
|
1215
|
-
exports.HandleResolutionSchema = HandleResolutionSchema;
|
|
1216
411
|
exports.NSID = NSID;
|
|
1217
412
|
exports.NotFoundError = NotFoundError;
|
|
1218
|
-
exports.
|
|
1219
|
-
exports.OrgInviteViewSchema = OrgInviteViewSchema;
|
|
1220
|
-
exports.OrgProfileDataSchema = OrgProfileDataSchema;
|
|
1221
|
-
exports.OrganizationMemberRecordSchema = OrganizationMemberRecordSchema;
|
|
1222
|
-
exports.OrganizationMemberViewSchema = OrganizationMemberViewSchema;
|
|
1223
|
-
exports.OrganizationRecordSchema = OrganizationRecordSchema;
|
|
1224
|
-
exports.OrganizationViewSchema = OrganizationViewSchema;
|
|
1225
|
-
exports.PersonEnrichmentRecordSchema = PersonEnrichmentRecordSchema;
|
|
1226
|
-
exports.PersonMergeRequestSchema = PersonMergeRequestSchema;
|
|
1227
|
-
exports.PersonNotesUpdateSchema = PersonNotesUpdateSchema;
|
|
413
|
+
exports.PatchAudioPostRequestSchema = PatchAudioPostRequestSchema;
|
|
1228
414
|
exports.PostRecordPublicSchema = PostRecordPublicSchema;
|
|
1229
|
-
exports.
|
|
1230
|
-
exports.
|
|
1231
|
-
exports.
|
|
1232
|
-
exports.
|
|
1233
|
-
exports.ProfileViewSelfSchema = ProfileViewSelfSchema;
|
|
1234
|
-
exports.PromptRecordSchema = PromptRecordSchema;
|
|
1235
|
-
exports.PromptRepliersSchema = PromptRepliersSchema;
|
|
1236
|
-
exports.PromptViewPublicSchema = PromptViewPublicSchema;
|
|
1237
|
-
exports.PromptViewSchema = PromptViewSchema;
|
|
1238
|
-
exports.PromptWithRepliesSchema = PromptWithRepliesSchema;
|
|
1239
|
-
exports.PublicProfileDtoSchema = PublicProfileDtoSchema;
|
|
1240
|
-
exports.PublicReplyDtoSchema = PublicReplyDtoSchema;
|
|
415
|
+
exports.ProcessingRequestSchema = ProcessingRequestSchema;
|
|
416
|
+
exports.ProcessingStageStatusSchema = ProcessingStageStatusSchema;
|
|
417
|
+
exports.ProcessingStateSchema = ProcessingStateSchema;
|
|
418
|
+
exports.ProcessingViewSchema = ProcessingViewSchema;
|
|
1241
419
|
exports.RateLimitError = RateLimitError;
|
|
1242
|
-
exports.ReplierSchema = ReplierSchema;
|
|
1243
|
-
exports.ReplyEnrichmentRecordSchema = ReplyEnrichmentRecordSchema;
|
|
1244
|
-
exports.ReplyRecordSchema = ReplyRecordSchema;
|
|
1245
420
|
exports.ReplyRefSchema = ReplyRefSchema;
|
|
1246
|
-
exports.ReplyViewPublicSchema = ReplyViewPublicSchema;
|
|
1247
|
-
exports.ReplyViewSchema = ReplyViewSchema;
|
|
1248
|
-
exports.RssSummarySchema = RssSummarySchema;
|
|
1249
|
-
exports.ScreeningRuleInputSchema = ScreeningRuleInputSchema;
|
|
1250
|
-
exports.ScreeningRuleRecordSchema = ScreeningRuleRecordSchema;
|
|
1251
|
-
exports.ScreeningRuleUpdateSchema = ScreeningRuleUpdateSchema;
|
|
1252
421
|
exports.ServiceError = ServiceError;
|
|
1253
|
-
exports.SipEnrichmentSchema = SipEnrichmentSchema;
|
|
1254
422
|
exports.StrongRefSchema = StrongRefSchema;
|
|
1255
|
-
exports.SwitchOrgRequestSchema = SwitchOrgRequestSchema;
|
|
1256
423
|
exports.TimedTranscriptSchema = TimedTranscriptSchema;
|
|
1257
424
|
exports.TranscriptEnrichmentRecordSchema = TranscriptEnrichmentRecordSchema;
|
|
1258
425
|
exports.TranscriptSegmentSchema = TranscriptSegmentSchema;
|
|
1259
426
|
exports.UnauthorizedError = UnauthorizedError;
|
|
1260
|
-
exports.UpdateMemberRoleRequestSchema = UpdateMemberRoleRequestSchema;
|
|
1261
|
-
exports.UpdateOrgRequestSchema = UpdateOrgRequestSchema;
|
|
1262
|
-
exports.UpdateProfileRequestSchema = UpdateProfileRequestSchema;
|
|
1263
|
-
exports.UpdateReplyStatusRequestSchema = UpdateReplyStatusRequestSchema;
|
|
1264
|
-
exports.UserProfileDataSchema = UserProfileDataSchema;
|
|
1265
|
-
exports.UserRecordSchema = UserRecordSchema;
|
|
1266
427
|
exports.ValidationError = ValidationError;
|
|
1267
428
|
exports.ViewerStateSchema = ViewerStateSchema;
|
|
1268
429
|
exports.buildReportedErrorEvent = buildReportedErrorEvent;
|
|
1269
|
-
exports.httpsUrl = httpsUrl;
|
|
1270
430
|
exports.isFirestoreTimestamp = isFirestoreTimestamp;
|
|
1271
|
-
exports.nsidForCollection = nsidForCollection;
|
|
1272
431
|
exports.reportError = reportError;
|
|
1273
|
-
exports.resolveAudioUrl = resolveAudioUrl;
|
|
1274
|
-
exports.toProfileViewBasic = toProfileViewBasic;
|
|
1275
|
-
exports.toPromptViewPublic = toPromptViewPublic;
|
|
1276
|
-
exports.toReplyViewPublic = toReplyViewPublic;
|