@antiphony/shared 0.3.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.
Files changed (44) hide show
  1. package/README.md +4 -4
  2. package/dist/cjs/api-codecs.cjs +74 -147
  3. package/dist/cjs/api-codecs.d.cts +105 -60
  4. package/dist/cjs/index.cjs +84 -197
  5. package/dist/cjs/index.d.cts +89 -7
  6. package/dist/cjs/nsid.cjs +6 -9
  7. package/dist/cjs/nsid.d.cts +7 -8
  8. package/dist/cjs/types/audio.cjs +60 -124
  9. package/dist/cjs/types/audio.d.cts +226 -185
  10. package/dist/cjs/types/blob.cjs +5 -9
  11. package/dist/cjs/types/blob.d.cts +21 -21
  12. package/dist/cjs/types/records.cjs +0 -45
  13. package/dist/cjs/types/records.d.cts +1 -103
  14. package/dist/esm/api-codecs.d.ts +135 -90
  15. package/dist/esm/api-codecs.js +4 -5
  16. package/dist/esm/chunk-D655OH2I.js +35 -0
  17. package/dist/esm/chunk-RUUHUNZ6.js +37 -0
  18. package/dist/esm/{chunk-6LROFBKK.js → chunk-SBYNIQRZ.js} +7 -9
  19. package/dist/esm/chunk-SMK4OZNU.js +17 -0
  20. package/dist/esm/{chunk-F7IHVM34.js → chunk-WL2GSPGC.js} +64 -12
  21. package/dist/esm/index.d.ts +89 -7
  22. package/dist/esm/index.js +5 -7
  23. package/dist/esm/nsid.d.ts +7 -8
  24. package/dist/esm/nsid.js +1 -1
  25. package/dist/esm/types/audio.d.ts +303 -262
  26. package/dist/esm/types/audio.js +3 -4
  27. package/dist/esm/types/blob.d.ts +21 -21
  28. package/dist/esm/types/blob.js +1 -1
  29. package/dist/esm/types/records.d.ts +1 -103
  30. package/dist/esm/types/records.js +1 -1
  31. package/package.json +90 -26
  32. package/dist/cjs/types/api.cjs +0 -166
  33. package/dist/cjs/types/api.d.cts +0 -242
  34. package/dist/cjs/types/views.cjs +0 -179
  35. package/dist/cjs/types/views.d.cts +0 -726
  36. package/dist/esm/chunk-5EHV73BA.js +0 -20
  37. package/dist/esm/chunk-FDM5FDN4.js +0 -46
  38. package/dist/esm/chunk-IHIBHQBJ.js +0 -78
  39. package/dist/esm/chunk-R6SBR3IG.js +0 -97
  40. package/dist/esm/chunk-Y6HNNRVD.js +0 -12
  41. package/dist/esm/types/api.d.ts +0 -242
  42. package/dist/esm/types/api.js +0 -4
  43. package/dist/esm/types/views.d.ts +0 -726
  44. package/dist/esm/types/views.js +0 -3
package/README.md CHANGED
@@ -24,24 +24,24 @@ Ships both ESM and CommonJS builds with correct type resolution under `node16`/`
24
24
  import { AudioPostRecordSchema, AudioPostViewSchema } from '@antiphony/shared';
25
25
  ```
26
26
 
27
- The root re-exports the most-used pieces (records, views, audio types, API types, codecs, NSIDs, errors, utils, observability). Granular subpaths are available too:
27
+ The root re-exports the most-used pieces (audio records + views, codecs, NSIDs, errors, utils, observability). Granular subpaths are available too:
28
28
 
29
29
  | Subpath | What's in it |
30
30
  | :--- | :--- |
31
- | `@antiphony/shared` | The common surface: records, views, audio + API types, `api-codecs`, `nsid`, `errors`, `utils`, `observability`. |
31
+ | `@antiphony/shared` | The common surface: audio records + views, `api-codecs`, `nsid`, `errors`, `utils`, `observability`. |
32
32
  | `@antiphony/shared/api-codecs` | Request/response Zod codecs for the REST surface. |
33
33
  | `@antiphony/shared/nsid` | The `dev.antiphony.*` NSID constants. |
34
34
  | `@antiphony/shared/errors` | Shared error types and helpers. |
35
35
  | `@antiphony/shared/utils` | Pure shared utilities (projection/date/sanitization helpers). |
36
36
  | `@antiphony/shared/observability` | Logging/error-reporting helpers (`./observability/report-error` for just the reporter). |
37
- | `@antiphony/shared/types/*` | Individual type modules: `records`, `views`, `audio`, `blob`, `api`, `channels`, `storage`. |
37
+ | `@antiphony/shared/types/*` | Individual type modules: `audio`, `blob`, `processing`, `records`. |
38
38
 
39
39
  ## The records this models
40
40
 
41
41
  - **`dev.antiphony.audio.post`** — the single canonical content record. A post without a `reply` is a prompt; with a `reply` it's a reply.
42
42
  - **`dev.antiphony.embed.audio`** — the audio attachment (stored record + hydrated view with a signed playback URL).
43
43
  - **`dev.antiphony.audio.transcript`** — platform-enrichment transcript, lifted into the embed view at read time.
44
- - **`dev.antiphony.actor.profile`** — the actor profile.
44
+ - **`dev.antiphony.actor.profile`** — the portable actor-profile shape. Lexicon-only: the core never stores it; the calling app owns profile data.
45
45
 
46
46
  See the [lexicon reference](https://docs.antiphony.dev/lexicons/overview/) for the full contract.
47
47
 
@@ -6,18 +6,15 @@ var zod = require('zod');
6
6
  var BlobRefSchema = zod.z.object({
7
7
  /** Discriminator for AT Protocol type system */
8
8
  $type: zod.z.literal("blob"),
9
- /** Content Identifier (CID) or URL pointing to the blob */
10
- ref: zod.z.string(),
9
+ /** IPLD link to the blob bytes: the content CID. */
10
+ ref: zod.z.object({
11
+ $link: zod.z.string().min(1)
12
+ }),
11
13
  /** MIME type of the blob (e.g., 'audio/webm') */
12
14
  mimeType: zod.z.string(),
13
15
  /** Size of the blob in bytes */
14
- size: zod.z.number()
16
+ size: zod.z.number().int().min(0)
15
17
  });
16
- function httpsUrl() {
17
- return zod.z.string().trim().url().refine((u) => /^https?:\/\//i.test(u), {
18
- message: "URL must use the http or https scheme"
19
- });
20
- }
21
18
  var FirestoreTimestampSchema = zod.z.union([
22
19
  zod.z.custom((data) => {
23
20
  return data && typeof data === "object" && (typeof data.toDate === "function" || "seconds" in data && "nanoseconds" in data);
@@ -48,117 +45,21 @@ var FirestoreTimestampSchema = zod.z.union([
48
45
  }
49
46
  return date;
50
47
  });
51
- zod.z.object({
52
- /** Unique Firebase UID */
53
- id: zod.z.string(),
54
- /** Public handle (e.g. @brad). Optional for Lite Users. */
55
- handle: zod.z.string().min(3).max(20).regex(/^[a-zA-Z0-9_]+$/).nullable().optional(),
56
- /** User stated intent (e.g. "Podcaster", "Listener") */
57
- usageIntent: zod.z.string().nullable().optional(),
58
- /** Domain for federated handle support. */
59
- domain: zod.z.string().default("antiphony.dev"),
60
- /**
61
- * Display Name (e.g. "Brad Thorson"). Nullable: Firestore stores `null`
62
- * when the user clears this field via the settings form, and the schema
63
- * must match storage reality or `UserRecordSchema.parse` (in
64
- * `getUserRecordByUid`) will throw.
65
- */
66
- displayName: zod.z.string().max(50).nullable().optional(),
67
- /** Short bio/description — nullable for the same reason as displayName. */
68
- bio: zod.z.string().max(160).nullable().optional(),
69
- /** URL to avatar image — nullable for the same reason as displayName. */
70
- avatarUrl: zod.z.string().url().nullable().optional(),
71
- /** Optional personal website surfaced on the public profile. */
72
- website: httpsUrl().nullable().optional(),
73
- /** Up to 5 additional public links (label + URL) shown under the bio. */
74
- links: zod.z.array(zod.z.object({
75
- label: zod.z.string().min(1).max(40),
76
- url: httpsUrl()
77
- })).max(5).optional(),
78
- /** When true and a Bluesky identity is linked, surfaces it on the public profile. */
79
- showBlueskyPublicly: zod.z.boolean().optional(),
80
- /** Server timestamp of creation */
81
- createdAt: FirestoreTimestampSchema,
82
- /** Individual account tier — free or creator_pro */
83
- tier: zod.z.enum(["free", "creator_pro"]).default("free"),
84
- /** Account status. Deactivated accounts retain data but are excluded from lookups. */
85
- status: zod.z.enum(["active", "deactivated"]).default("active"),
86
- /** Timestamp when the account was deactivated (soft deleted) */
87
- deactivatedAt: FirestoreTimestampSchema.optional()
48
+ var ProcessingStageStatusSchema = zod.z.enum(["pending", "ready", "failed", "skipped"]);
49
+ var ProcessingRequestSchema = zod.z.object({
50
+ transcribe: zod.z.boolean().optional(),
51
+ denoise: zod.z.boolean().optional()
88
52
  });
89
- var ProfileViewBasicSchema = zod.z.object({
90
- id: zod.z.string(),
91
- handle: zod.z.string().nullable().optional(),
92
- // `displayName` and `bio` are `.nullable()` Firestore stores `null` for
93
- // empty values on these fields (see users-dependencies.ts), and Zod's
94
- // `.optional()` alone rejects `null`. Consumers already use truthy
95
- // checks / `??` / `||`, so widening the type to include `null` is safe.
96
- displayName: zod.z.string().nullable().optional(),
97
- avatarUrl: zod.z.string().nullable().optional(),
98
- bio: zod.z.string().nullable().optional(),
99
- /** Personal website link surfaced on the public profile. */
100
- website: zod.z.string().nullable().optional(),
101
- /** Public links (label + URL) shown under the bio. */
102
- links: zod.z.array(zod.z.object({
103
- label: zod.z.string(),
104
- url: zod.z.string()
105
- })).optional(),
106
- /**
107
- * AT Protocol identity, surfaced on the public profile only when the user
108
- * opts in (`UserRecord.showBlueskyPublicly === true`). Projection happens
109
- * in the user dependency layer; this schema simply allows the field.
110
- */
111
- bluesky: zod.z.object({
112
- handle: zod.z.string(),
113
- did: zod.z.string()
114
- }).optional(),
115
- stats: zod.z.object({
116
- followers: zod.z.number().default(0),
117
- following: zod.z.number().default(0),
118
- prompts: zod.z.number().default(0)
119
- }).optional(),
120
- badges: zod.z.array(zod.z.string()).optional(),
121
- isVerified: zod.z.boolean().optional(),
122
- createdAt: FirestoreTimestampSchema.optional()
53
+ var ProcessingStateSchema = zod.z.object({
54
+ transcribe: ProcessingStageStatusSchema.optional(),
55
+ denoise: ProcessingStageStatusSchema.optional(),
56
+ /** Content CID of the denoised audio variant, once `denoise === 'ready'`. */
57
+ denoisedBlobCid: zod.z.string().optional(),
58
+ updatedAt: FirestoreTimestampSchema
123
59
  });
124
- var ProfileViewDetailedSchema = ProfileViewBasicSchema.extend({
125
- /** AT Protocol Identity link */
126
- bluesky: zod.z.object({
127
- handle: zod.z.string(),
128
- did: zod.z.string()
129
- }).optional(),
130
- usageIntent: zod.z.string().nullable().optional()
131
- });
132
- var ProfileViewSelfSchema = ProfileViewDetailedSchema.extend({
133
- phoneNumber: zod.z.string().nullable().optional(),
134
- email: zod.z.string().optional(),
135
- lastSeenAt: FirestoreTimestampSchema.optional(),
136
- lastActiveAt: FirestoreTimestampSchema.optional(),
137
- unreadReplyCount: zod.z.number().default(0),
138
- newReplierCount: zod.z.number().default(0),
139
- /**
140
- * Account tier from UserRecord — surfaced on the self profile so the
141
- * client can gate paid features. Optional for legacy docs without the
142
- * field; consumers should treat missing as `'free'`.
143
- */
144
- tier: zod.z.enum(["free", "creator_pro"]).optional(),
145
- /**
146
- * Surfaces the linked Bluesky identity (handle + DID) on the public profile
147
- * when true. Persisted on UserRecord; exposed in self/detailed views so the
148
- * settings form can render the toggle's current state.
149
- */
150
- showBlueskyPublicly: zod.z.boolean().optional(),
151
- settings: zod.z.object({
152
- notifications: zod.z.boolean().optional(),
153
- theme: zod.z.string().optional()
154
- }).optional()
155
- });
156
- ProfileViewSelfSchema.extend({
157
- blockedUsers: zod.z.array(zod.z.string()).optional(),
158
- followers: zod.z.array(zod.z.string()).optional(),
159
- following: zod.z.array(zod.z.string()).optional(),
160
- reportCount: zod.z.number().optional(),
161
- isBanned: zod.z.boolean().optional()
60
+ var ProcessingViewSchema = zod.z.object({
61
+ transcribe: ProcessingStageStatusSchema.optional(),
62
+ denoise: ProcessingStageStatusSchema.optional()
162
63
  });
163
64
 
164
65
  // types/audio.ts
@@ -172,7 +73,7 @@ var ReplyRefSchema = zod.z.object({
172
73
  });
173
74
  var AudioEmbedSchema = zod.z.object({
174
75
  $type: zod.z.literal("dev.antiphony.embed.audio"),
175
- /** The audio bytes as a content-addressed storage ref (CID/path). */
76
+ /** The audio bytes as a content-addressed blob ref (`ref.$link` = CID). */
176
77
  audio: BlobRefSchema,
177
78
  /** Duration in MILLISECONDS (platform-wide unit; not seconds). */
178
79
  durationMs: zod.z.number().int().min(0).optional(),
@@ -202,11 +103,26 @@ var AudioEmbedViewSchema = zod.z.object({
202
103
  alt: zod.z.string().max(1e4).optional(),
203
104
  waveform: zod.z.array(zod.z.number().int().min(0).max(100)).max(1e3).optional(),
204
105
  /** Lifted from the transcript enrichment record; absent until transcription completes. */
205
- transcript: TimedTranscriptSchema.optional()
106
+ transcript: TimedTranscriptSchema.optional(),
107
+ /**
108
+ * Per-stage audio-processing status (transcribe / denoise), when the app
109
+ * opted into processing on create. Absent otherwise. A `pending` stage
110
+ * means the client should poll (or re-render) for the result. When
111
+ * `denoise === 'ready'`, `url` above already resolves to the cleaned
112
+ * audio variant. See `types/processing.ts`.
113
+ */
114
+ processing: ProcessingViewSchema.optional()
206
115
  });
207
116
  zod.z.object({
208
117
  /** Storage id (rkey/doc id). */
209
118
  id: zod.z.string(),
119
+ /**
120
+ * Content CID of the canonical lexicon record (CIDv1, dag-cbor, sha2-256
121
+ * — the AT Protocol record-CID rule). Computed at write time over the
122
+ * lexicon projection (public fields only, NOT the storage/tenancy fields
123
+ * below), so StrongRefs built from it are verifiable content addresses.
124
+ */
125
+ cid: zod.z.string(),
210
126
  // --- Tenancy + facets (storage-indexed; NOT in the lexicon) ---
211
127
  /** Origin app that created this record — the multi-tenant isolation key. */
212
128
  originAppId: zod.z.string(),
@@ -224,9 +140,24 @@ zod.z.object({
224
140
  * opened the branch. Set on replies (deduped, 1–2 ids); absent on prompts
225
141
  * (a prompt's repliers are the app's audience policy, not a fixed pair).
226
142
  * Inherited down the branch so reply gating is an O(1) field check, never a
227
- * thread walk. See `specs/antiphony-data-model.md` §6 "Reply gating".
143
+ * thread walk.
228
144
  */
229
145
  threadParticipants: zod.z.array(zod.z.string()).optional(),
146
+ /**
147
+ * Author of this reply's thread ROOT (the prompt) — the reply's recipient,
148
+ * the person whose "replies to me" feed it lands in. Denormalized at write
149
+ * time so "replies whose root author is X" is a cheap composite-index query
150
+ * (see `queryByRootAuthor`). Set on replies (`kind === 'reply'`); absent on
151
+ * prompts. Storage-layer facet, NOT in the public lexicon or the record CID.
152
+ */
153
+ rootAuthorId: zod.z.string().optional(),
154
+ /**
155
+ * Async audio-processing state (transcribe / denoise), present iff the app
156
+ * opted into processing on create. Mutated by the processing worker after
157
+ * the post is created — storage-layer, NOT in the lexicon or the record
158
+ * CID. See `types/processing.ts`.
159
+ */
160
+ processing: ProcessingStateSchema.optional(),
230
161
  // --- Lexicon fields (public contract) ---
231
162
  /** User-authored text (bsky-semantic). May be empty for pure-audio posts. NEVER the transcript. */
232
163
  text: zod.z.string().max(3e3),
@@ -245,10 +176,11 @@ zod.z.object({
245
176
  }).refine(
246
177
  // `kind` is denormalized from `reply` presence at write time; enforce the
247
178
  // invariant so an inconsistent record can't be written or read silently.
248
- // A reply has `reply` and no `title`; a prompt has neither a `reply`.
249
- (r) => r.kind === "reply" ? !!r.reply && r.title === void 0 : !r.reply,
179
+ // A reply has `reply`, no `title`, and a stamped `rootAuthorId` (its
180
+ // recipient facet); a prompt has none of those.
181
+ (r) => r.kind === "reply" ? !!r.reply && r.title === void 0 && r.rootAuthorId !== void 0 : !r.reply && r.rootAuthorId === void 0,
250
182
  {
251
- message: "kind must match reply presence: 'reply' \u21D2 reply set & no title; 'prompt' \u21D2 no reply",
183
+ message: "kind must match reply presence: 'reply' \u21D2 reply set, no title, rootAuthorId set; 'prompt' \u21D2 no reply, no rootAuthorId",
252
184
  path: ["kind"]
253
185
  }
254
186
  );
@@ -291,9 +223,13 @@ var PostRecordPublicSchema = zod.z.object({
291
223
  zod.z.object({
292
224
  /** at:// URI (or internal ref) identifying the post. */
293
225
  uri: zod.z.string(),
294
- cid: zod.z.string().optional(),
226
+ /** Content CID of the canonical record (see `AudioPostRecordSchema.cid`). */
227
+ cid: zod.z.string(),
295
228
  kind: zod.z.enum(["prompt", "reply"]),
296
- author: ProfileViewBasicSchema,
229
+ /** The acting actor's app-scoped id — an opaque attribution ref, not a profile. */
230
+ authorId: zod.z.string(),
231
+ /** The author's app-asserted AT Protocol DID, when the caller provided one. */
232
+ authorDid: zod.z.string().optional(),
297
233
  record: PostRecordPublicSchema,
298
234
  /** Hydrated audio embed (signed URL + lifted transcript). */
299
235
  embed: AudioEmbedViewSchema.optional(),
@@ -313,7 +249,14 @@ var CreateAudioPostRequestSchema = zod.z.object({
313
249
  /** BCP-47 language tags. */
314
250
  langs: zod.z.array(zod.z.string()).max(3).optional(),
315
251
  /** Author self-label values (content warnings). */
316
- selfLabels: zod.z.array(zod.z.string()).optional()
252
+ selfLabels: zod.z.array(zod.z.string()).optional(),
253
+ /**
254
+ * Opt-in audio processing for this post's audio (transcribe / denoise).
255
+ * Both default off. Stages the deployment can't provide come back marked
256
+ * `skipped` on the view rather than failing the create. See
257
+ * `types/processing.ts`.
258
+ */
259
+ processing: ProcessingRequestSchema.optional()
317
260
  }).refine((d) => !(d.reply && d.title), {
318
261
  message: "Replies cannot have a title",
319
262
  path: ["title"]
@@ -321,27 +264,11 @@ var CreateAudioPostRequestSchema = zod.z.object({
321
264
  message: "Post must have text or an audio embed",
322
265
  path: ["text"]
323
266
  });
324
- var UpdateProfileRequestSchema = zod.z.object({
325
- handle: zod.z.string().min(3).max(20).regex(/^[a-zA-Z0-9_]+$/).optional(),
326
- displayName: zod.z.string().max(50).optional(),
327
- bio: zod.z.string().max(160).optional(),
328
- avatarUrl: zod.z.string().url().nullable().optional(),
329
- usageIntent: zod.z.string().max(200).nullable().optional(),
330
- /**
331
- * Personal website surfaced on the public profile. Accepts a URL, empty
332
- * string, or null from the client; normalizes empty string → null so the
333
- * value stored on `UserRecord` (which requires `.url() | null`) round-trips
334
- * cleanly through `UserRecordSchema.parse` on subsequent reads.
335
- */
336
- website: zod.z.union([zod.z.string().url(), zod.z.literal(""), zod.z.null()]).optional().transform((v) => v === "" ? null : v),
337
- /** Up to 5 public links (label + URL) shown under the bio. */
338
- links: zod.z.array(zod.z.object({
339
- label: zod.z.string().min(1).max(40),
340
- url: zod.z.string().url()
341
- })).max(5).optional(),
342
- /** When true, surfaces the linked Bluesky identity on the public profile. */
343
- showBlueskyPublicly: zod.z.boolean().optional()
267
+ var PatchAudioPostRequestSchema = zod.z.object({
268
+ /** Opt-in audio processing to (re)run for this post's audio. Required — a
269
+ * PATCH with no processing request is a no-op and rejected as invalid. */
270
+ processing: ProcessingRequestSchema
344
271
  });
345
272
 
346
273
  exports.CreateAudioPostRequestSchema = CreateAudioPostRequestSchema;
347
- exports.UpdateProfileRequestSchema = UpdateProfileRequestSchema;
274
+ exports.PatchAudioPostRequestSchema = PatchAudioPostRequestSchema;
@@ -16,17 +16,27 @@ declare const CreateAudioPostRequestSchema: z.ZodEffects<z.ZodEffects<z.ZodObjec
16
16
  $type: z.ZodLiteral<"dev.antiphony.embed.audio">;
17
17
  audio: z.ZodObject<{
18
18
  $type: z.ZodLiteral<"blob">;
19
- ref: z.ZodString;
19
+ ref: z.ZodObject<{
20
+ $link: z.ZodString;
21
+ }, "strip", z.ZodTypeAny, {
22
+ $link: string;
23
+ }, {
24
+ $link: string;
25
+ }>;
20
26
  mimeType: z.ZodString;
21
27
  size: z.ZodNumber;
22
28
  }, "strip", z.ZodTypeAny, {
23
29
  $type: "blob";
24
- ref: string;
30
+ ref: {
31
+ $link: string;
32
+ };
25
33
  mimeType: string;
26
34
  size: number;
27
35
  }, {
28
36
  $type: "blob";
29
- ref: string;
37
+ ref: {
38
+ $link: string;
39
+ };
30
40
  mimeType: string;
31
41
  size: number;
32
42
  }>;
@@ -37,7 +47,9 @@ declare const CreateAudioPostRequestSchema: z.ZodEffects<z.ZodEffects<z.ZodObjec
37
47
  $type: "dev.antiphony.embed.audio";
38
48
  audio: {
39
49
  $type: "blob";
40
- ref: string;
50
+ ref: {
51
+ $link: string;
52
+ };
41
53
  mimeType: string;
42
54
  size: number;
43
55
  };
@@ -48,7 +60,9 @@ declare const CreateAudioPostRequestSchema: z.ZodEffects<z.ZodEffects<z.ZodObjec
48
60
  $type: "dev.antiphony.embed.audio";
49
61
  audio: {
50
62
  $type: "blob";
51
- ref: string;
63
+ ref: {
64
+ $link: string;
65
+ };
52
66
  mimeType: string;
53
67
  size: number;
54
68
  };
@@ -101,8 +115,28 @@ declare const CreateAudioPostRequestSchema: z.ZodEffects<z.ZodEffects<z.ZodObjec
101
115
  langs: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
102
116
  /** Author self-label values (content warnings). */
103
117
  selfLabels: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
118
+ /**
119
+ * Opt-in audio processing for this post's audio (transcribe / denoise).
120
+ * Both default off. Stages the deployment can't provide come back marked
121
+ * `skipped` on the view rather than failing the create. See
122
+ * `types/processing.ts`.
123
+ */
124
+ processing: z.ZodOptional<z.ZodObject<{
125
+ transcribe: z.ZodOptional<z.ZodBoolean>;
126
+ denoise: z.ZodOptional<z.ZodBoolean>;
127
+ }, "strip", z.ZodTypeAny, {
128
+ transcribe?: boolean | undefined;
129
+ denoise?: boolean | undefined;
130
+ }, {
131
+ transcribe?: boolean | undefined;
132
+ denoise?: boolean | undefined;
133
+ }>>;
104
134
  }, "strip", z.ZodTypeAny, {
105
135
  text: string;
136
+ processing?: {
137
+ transcribe?: boolean | undefined;
138
+ denoise?: boolean | undefined;
139
+ } | undefined;
106
140
  reply?: {
107
141
  root: {
108
142
  uri: string;
@@ -118,7 +152,9 @@ declare const CreateAudioPostRequestSchema: z.ZodEffects<z.ZodEffects<z.ZodObjec
118
152
  $type: "dev.antiphony.embed.audio";
119
153
  audio: {
120
154
  $type: "blob";
121
- ref: string;
155
+ ref: {
156
+ $link: string;
157
+ };
122
158
  mimeType: string;
123
159
  size: number;
124
160
  };
@@ -130,6 +166,10 @@ declare const CreateAudioPostRequestSchema: z.ZodEffects<z.ZodEffects<z.ZodObjec
130
166
  selfLabels?: string[] | undefined;
131
167
  }, {
132
168
  text?: string | undefined;
169
+ processing?: {
170
+ transcribe?: boolean | undefined;
171
+ denoise?: boolean | undefined;
172
+ } | undefined;
133
173
  reply?: {
134
174
  root: {
135
175
  uri: string;
@@ -145,7 +185,9 @@ declare const CreateAudioPostRequestSchema: z.ZodEffects<z.ZodEffects<z.ZodObjec
145
185
  $type: "dev.antiphony.embed.audio";
146
186
  audio: {
147
187
  $type: "blob";
148
- ref: string;
188
+ ref: {
189
+ $link: string;
190
+ };
149
191
  mimeType: string;
150
192
  size: number;
151
193
  };
@@ -157,6 +199,10 @@ declare const CreateAudioPostRequestSchema: z.ZodEffects<z.ZodEffects<z.ZodObjec
157
199
  selfLabels?: string[] | undefined;
158
200
  }>, {
159
201
  text: string;
202
+ processing?: {
203
+ transcribe?: boolean | undefined;
204
+ denoise?: boolean | undefined;
205
+ } | undefined;
160
206
  reply?: {
161
207
  root: {
162
208
  uri: string;
@@ -172,7 +218,9 @@ declare const CreateAudioPostRequestSchema: z.ZodEffects<z.ZodEffects<z.ZodObjec
172
218
  $type: "dev.antiphony.embed.audio";
173
219
  audio: {
174
220
  $type: "blob";
175
- ref: string;
221
+ ref: {
222
+ $link: string;
223
+ };
176
224
  mimeType: string;
177
225
  size: number;
178
226
  };
@@ -184,6 +232,10 @@ declare const CreateAudioPostRequestSchema: z.ZodEffects<z.ZodEffects<z.ZodObjec
184
232
  selfLabels?: string[] | undefined;
185
233
  }, {
186
234
  text?: string | undefined;
235
+ processing?: {
236
+ transcribe?: boolean | undefined;
237
+ denoise?: boolean | undefined;
238
+ } | undefined;
187
239
  reply?: {
188
240
  root: {
189
241
  uri: string;
@@ -199,7 +251,9 @@ declare const CreateAudioPostRequestSchema: z.ZodEffects<z.ZodEffects<z.ZodObjec
199
251
  $type: "dev.antiphony.embed.audio";
200
252
  audio: {
201
253
  $type: "blob";
202
- ref: string;
254
+ ref: {
255
+ $link: string;
256
+ };
203
257
  mimeType: string;
204
258
  size: number;
205
259
  };
@@ -211,6 +265,10 @@ declare const CreateAudioPostRequestSchema: z.ZodEffects<z.ZodEffects<z.ZodObjec
211
265
  selfLabels?: string[] | undefined;
212
266
  }>, {
213
267
  text: string;
268
+ processing?: {
269
+ transcribe?: boolean | undefined;
270
+ denoise?: boolean | undefined;
271
+ } | undefined;
214
272
  reply?: {
215
273
  root: {
216
274
  uri: string;
@@ -226,7 +284,9 @@ declare const CreateAudioPostRequestSchema: z.ZodEffects<z.ZodEffects<z.ZodObjec
226
284
  $type: "dev.antiphony.embed.audio";
227
285
  audio: {
228
286
  $type: "blob";
229
- ref: string;
287
+ ref: {
288
+ $link: string;
289
+ };
230
290
  mimeType: string;
231
291
  size: number;
232
292
  };
@@ -238,6 +298,10 @@ declare const CreateAudioPostRequestSchema: z.ZodEffects<z.ZodEffects<z.ZodObjec
238
298
  selfLabels?: string[] | undefined;
239
299
  }, {
240
300
  text?: string | undefined;
301
+ processing?: {
302
+ transcribe?: boolean | undefined;
303
+ denoise?: boolean | undefined;
304
+ } | undefined;
241
305
  reply?: {
242
306
  root: {
243
307
  uri: string;
@@ -253,7 +317,9 @@ declare const CreateAudioPostRequestSchema: z.ZodEffects<z.ZodEffects<z.ZodObjec
253
317
  $type: "dev.antiphony.embed.audio";
254
318
  audio: {
255
319
  $type: "blob";
256
- ref: string;
320
+ ref: {
321
+ $link: string;
322
+ };
257
323
  mimeType: string;
258
324
  size: number;
259
325
  };
@@ -266,59 +332,38 @@ declare const CreateAudioPostRequestSchema: z.ZodEffects<z.ZodEffects<z.ZodObjec
266
332
  }>;
267
333
  type CreateAudioPostRequest = z.infer<typeof CreateAudioPostRequestSchema>;
268
334
  /**
269
- * Update-request codec for the authenticated actor's own profile
270
- * (`PATCH /api/v1/users/me`). Partial-update of identity fields only.
335
+ * Patch-request codec for the canonical Antiphony `dev.antiphony.audio.post`
336
+ * model. **Processing opt-in is the ONLY thing a PATCH may change** — it
337
+ * re-triggers async audio enrichment (transcribe / denoise) on an existing
338
+ * post. No lexicon fields are editable here: those feed the record CID (its
339
+ * content address / identity), so a content edit would mint a different record.
340
+ * Processing state is storage-layer, so this changes no CID. See
341
+ * `types/processing.ts`.
271
342
  */
272
- declare const UpdateProfileRequestSchema: z.ZodObject<{
273
- handle: z.ZodOptional<z.ZodString>;
274
- displayName: z.ZodOptional<z.ZodString>;
275
- bio: z.ZodOptional<z.ZodString>;
276
- avatarUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
277
- usageIntent: z.ZodOptional<z.ZodNullable<z.ZodString>>;
278
- /**
279
- * Personal website surfaced on the public profile. Accepts a URL, empty
280
- * string, or null from the client; normalizes empty string → null so the
281
- * value stored on `UserRecord` (which requires `.url() | null`) round-trips
282
- * cleanly through `UserRecordSchema.parse` on subsequent reads.
283
- */
284
- website: z.ZodEffects<z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodLiteral<"">, z.ZodNull]>>, string | null | undefined, string | null | undefined>;
285
- /** Up to 5 public links (label + URL) shown under the bio. */
286
- links: z.ZodOptional<z.ZodArray<z.ZodObject<{
287
- label: z.ZodString;
288
- url: z.ZodString;
343
+ declare const PatchAudioPostRequestSchema: z.ZodObject<{
344
+ /** Opt-in audio processing to (re)run for this post's audio. Required — a
345
+ * PATCH with no processing request is a no-op and rejected as invalid. */
346
+ processing: z.ZodObject<{
347
+ transcribe: z.ZodOptional<z.ZodBoolean>;
348
+ denoise: z.ZodOptional<z.ZodBoolean>;
289
349
  }, "strip", z.ZodTypeAny, {
290
- label: string;
291
- url: string;
350
+ transcribe?: boolean | undefined;
351
+ denoise?: boolean | undefined;
292
352
  }, {
293
- label: string;
294
- url: string;
295
- }>, "many">>;
296
- /** When true, surfaces the linked Bluesky identity on the public profile. */
297
- showBlueskyPublicly: z.ZodOptional<z.ZodBoolean>;
353
+ transcribe?: boolean | undefined;
354
+ denoise?: boolean | undefined;
355
+ }>;
298
356
  }, "strip", z.ZodTypeAny, {
299
- handle?: string | undefined;
300
- usageIntent?: string | null | undefined;
301
- displayName?: string | undefined;
302
- bio?: string | undefined;
303
- avatarUrl?: string | null | undefined;
304
- website?: string | null | undefined;
305
- links?: {
306
- label: string;
307
- url: string;
308
- }[] | undefined;
309
- showBlueskyPublicly?: boolean | undefined;
357
+ processing: {
358
+ transcribe?: boolean | undefined;
359
+ denoise?: boolean | undefined;
360
+ };
310
361
  }, {
311
- handle?: string | undefined;
312
- usageIntent?: string | null | undefined;
313
- displayName?: string | undefined;
314
- bio?: string | undefined;
315
- avatarUrl?: string | null | undefined;
316
- website?: string | null | undefined;
317
- links?: {
318
- label: string;
319
- url: string;
320
- }[] | undefined;
321
- showBlueskyPublicly?: boolean | undefined;
362
+ processing: {
363
+ transcribe?: boolean | undefined;
364
+ denoise?: boolean | undefined;
365
+ };
322
366
  }>;
367
+ type PatchAudioPostRequest = z.infer<typeof PatchAudioPostRequestSchema>;
323
368
 
324
- export { type CreateAudioPostRequest, CreateAudioPostRequestSchema, UpdateProfileRequestSchema };
369
+ export { type CreateAudioPostRequest, CreateAudioPostRequestSchema, type PatchAudioPostRequest, PatchAudioPostRequestSchema };