vidspotai-shared 1.0.114 → 1.0.115

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 (53) hide show
  1. package/lib/globals/types.d.ts +8 -0
  2. package/lib/globals/types.d.ts.map +1 -1
  3. package/lib/globals/types.js +9 -0
  4. package/lib/libs/storage/MediaStorage.d.ts +67 -30
  5. package/lib/libs/storage/MediaStorage.d.ts.map +1 -1
  6. package/lib/libs/storage/MediaStorage.js +51 -39
  7. package/lib/libs/storage/R2Backend.d.ts +21 -2
  8. package/lib/libs/storage/R2Backend.d.ts.map +1 -1
  9. package/lib/libs/storage/R2Backend.js +31 -12
  10. package/lib/libs/storage/cdnUrl.d.ts +27 -0
  11. package/lib/libs/storage/cdnUrl.d.ts.map +1 -0
  12. package/lib/libs/storage/cdnUrl.js +48 -0
  13. package/lib/libs/storage/index.d.ts +1 -0
  14. package/lib/libs/storage/index.d.ts.map +1 -1
  15. package/lib/libs/storage/index.js +1 -0
  16. package/lib/models/agent.model.d.ts +27 -0
  17. package/lib/models/agent.model.d.ts.map +1 -1
  18. package/lib/models/index.d.ts +1 -0
  19. package/lib/models/index.d.ts.map +1 -1
  20. package/lib/models/index.js +1 -0
  21. package/lib/models/outreach.model.d.ts +7 -1
  22. package/lib/models/outreach.model.d.ts.map +1 -1
  23. package/lib/models/outreachIntegration.model.d.ts +42 -0
  24. package/lib/models/outreachIntegration.model.d.ts.map +1 -0
  25. package/lib/models/outreachIntegration.model.js +8 -0
  26. package/lib/models/video.model.d.ts +7 -1
  27. package/lib/models/video.model.d.ts.map +1 -1
  28. package/lib/schemas/videoPlan.schema.d.ts +1 -0
  29. package/lib/schemas/videoPlan.schema.d.ts.map +1 -1
  30. package/lib/schemas/videoPlan.schema.js +10 -0
  31. package/lib/services/agent/tools/planVideo.tool.d.ts +1 -0
  32. package/lib/services/agent/tools/planVideo.tool.d.ts.map +1 -1
  33. package/lib/services/avatarGen/IAvatarVideoProvider.d.ts +25 -3
  34. package/lib/services/avatarGen/IAvatarVideoProvider.d.ts.map +1 -1
  35. package/lib/services/avatarGen/IAvatarVideoProvider.js +2 -1
  36. package/lib/services/avatarGen/providers/heygenAvatarProvider.d.ts +23 -2
  37. package/lib/services/avatarGen/providers/heygenAvatarProvider.d.ts.map +1 -1
  38. package/lib/services/avatarGen/providers/heygenAvatarProvider.js +71 -0
  39. package/lib/services/avatarGen/providers/tavusAvatarProvider.d.ts +3 -4
  40. package/lib/services/avatarGen/providers/tavusAvatarProvider.d.ts.map +1 -1
  41. package/lib/services/avatarGen/providers/tavusAvatarProvider.js +17 -0
  42. package/lib/services/editor/planToProject.d.ts.map +1 -1
  43. package/lib/services/editor/planToProject.js +29 -1
  44. package/lib/services/firestore.service.d.ts +3 -0
  45. package/lib/services/firestore.service.d.ts.map +1 -1
  46. package/lib/services/firestore.service.js +7 -0
  47. package/lib/services/index.d.ts +1 -0
  48. package/lib/services/index.d.ts.map +1 -1
  49. package/lib/services/index.js +1 -0
  50. package/lib/services/outreachWebhooks.service.d.ts +24 -0
  51. package/lib/services/outreachWebhooks.service.d.ts.map +1 -0
  52. package/lib/services/outreachWebhooks.service.js +41 -0
  53. package/package.json +1 -1
@@ -152,6 +152,14 @@ export declare enum ERedisQueues {
152
152
  * repairs, and writes the report back. See notes/SAAS_DEMO_GENERATOR_PLAN.md §12.
153
153
  */
154
154
  VIDEO_QA_JOBS = "video-qa-job-queue",
155
+ /**
156
+ * VidSpot Reach — Phase 7 self-serve API integration. One job per outbound
157
+ * webhook delivery attempt (campaign.completed / video.ready /
158
+ * recipient.viewed). BullMQ's own attempts+backoff drive the retry — the
159
+ * dispatcher enqueues once per active subscriber per event, the worker owns
160
+ * the signed HTTP POST.
161
+ */
162
+ WEBHOOK_DELIVERY_JOBS = "webhook-delivery-job-queue",
155
163
  /**
156
164
  * R2 cutover — mirrors a resumable-upload object (already in GCS, up to
157
165
  * 1 GiB) into R2 off the request path. `completeUploadSessionController`
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/globals/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/globals/types.ts"],"names":[],"mappings":"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"}
@@ -153,6 +153,14 @@ var ERedisQueues;
153
153
  * repairs, and writes the report back. See notes/SAAS_DEMO_GENERATOR_PLAN.md §12.
154
154
  */
155
155
  ERedisQueues["VIDEO_QA_JOBS"] = "video-qa-job-queue";
156
+ /**
157
+ * VidSpot Reach — Phase 7 self-serve API integration. One job per outbound
158
+ * webhook delivery attempt (campaign.completed / video.ready /
159
+ * recipient.viewed). BullMQ's own attempts+backoff drive the retry — the
160
+ * dispatcher enqueues once per active subscriber per event, the worker owns
161
+ * the signed HTTP POST.
162
+ */
163
+ ERedisQueues["WEBHOOK_DELIVERY_JOBS"] = "webhook-delivery-job-queue";
156
164
  /**
157
165
  * R2 cutover — mirrors a resumable-upload object (already in GCS, up to
158
166
  * 1 GiB) into R2 off the request path. `completeUploadSessionController`
@@ -180,6 +188,7 @@ exports.REDIS_QUEUES = [
180
188
  ERedisQueues.DEMO_VIDEO_JOBS,
181
189
  ERedisQueues.OUTREACH_PERSONALIZE_JOBS,
182
190
  ERedisQueues.VIDEO_QA_JOBS,
191
+ ERedisQueues.WEBHOOK_DELIVERY_JOBS,
183
192
  ERedisQueues.MEDIA_MIRROR_JOBS,
184
193
  ];
185
194
  /** X8 Social Suite — connected social platforms. Value = stable storage key. */
@@ -8,28 +8,48 @@
8
8
  * is stored — swapping backends, or flipping which one is primary, never touches
9
9
  * the ~30 call sites.
10
10
  *
11
- * Today's composition:
12
- * • PRIMARY = GCS (system-of-record + pipeline source; returns the delivery URL)
13
- * • MIRROR = R2, best-effort, only when `R2_WRITE_ENABLED=true`
11
+ * Stage 2 composition (flipped 2026-09-22 — full reasoning in
12
+ * notes/R2_MEDIA_MIGRATION_PLAN.md §9 "Stage 2 decision log — R2-primary flip"):
13
+ * • BYTES = R2 — the only place object bytes are written, read, or
14
+ * deleted for anything going through `put`/`putFromFile`/`delete` below.
15
+ * • URL MINTER = GCS — used ONLY to mint the V4-signed URL *shape* that
16
+ * the `cdn.vidspotai.com` Worker already recognizes, including its
17
+ * private-access gate (which just checks the signature param is
18
+ * present — see worker.js `privateRequestAllowed()`, it never
19
+ * cryptographically verifies it). V4 signing is a local crypto
20
+ * operation against the service-account key: no network call, and the
21
+ * object does NOT need to exist in the GCS bucket for a valid-shaped
22
+ * URL to be minted. So this eliminates real GCS *storage* (and its
23
+ * cost) while keeping one small, cost-free GCS *credential*
24
+ * dependency purely for the URL shape — a deliberate, documented
25
+ * trade-off, not an oversight. Building a fully GCS-independent
26
+ * signed-URL scheme (HMAC tokens + Worker verification) was considered
27
+ * and explicitly deferred — see the notes doc.
14
28
  *
15
- * Delivery flips to free egress automatically: the `cdn.vidspotai.com` Worker is
16
- * R2-first, so once an object is mirrored it serves from R2; until then the
17
- * Worker falls back to GCS. See notes/R2_MEDIA_MIGRATION_PLAN.md (Phase 2).
18
- *
19
- * FUTURE SWAP (Stage 2 — decommission GCS): make R2 the primary and return its
20
- * CDN read URL. That is an edit to THIS FILE ONLY — every caller keeps calling
21
- * `mediaStorage.put(...)` unchanged.
29
+ * NOT covered by this flip — a few bespoke pipeline paths write bytes
30
+ * directly to GCS via their own streaming/integrity logic instead of
31
+ * routing through `put`/`putFromFile` (direct multipart uploads in
32
+ * handleUploadFile.ts, resumable-upload completion in
33
+ * mediaUploadSession.controller.ts, the google.service.ts moov-atom guard,
34
+ * mediaMirrorQueueProcessor), then call `mirrorBytes`/`mirrorFromFile`/
35
+ * `mirrorFromReadable` below for a best-effort R2 copy. Those still write
36
+ * real bytes to GCS today — converting them is a separate, larger effort
37
+ * (see the notes doc §9).
22
38
  */
23
39
  import type { Readable } from "stream";
24
40
  import type { IStorageBackend } from "./StorageBackend";
25
- /** R2 mirror-writes are opt-in; off = today's GCS-only behavior, exactly. */
41
+ /**
42
+ * Legacy pipeline mirror-writes (see NOT COVERED above) stay opt-in behind
43
+ * this flag; unrelated to the `put`/`putFromFile`/`delete` R2-primary path,
44
+ * which is unconditional since 2026-09-22.
45
+ */
26
46
  export declare function isR2WriteEnabled(): boolean;
27
47
  export declare class MediaStorage {
28
- /** Store-of-record + delivery-URL source. */
29
- private readonly primary;
30
- /** Zero-egress mirror; written best-effort when enabled. */
31
- private readonly mirror;
32
- constructor(primary: IStorageBackend, mirror: IStorageBackend);
48
+ /** Actual byte store — reads/writes/deletes real object data. */
49
+ private readonly bytes;
50
+ /** URL-shape minter only — never written to, never read from directly. */
51
+ private readonly urlMinter;
52
+ constructor(bytes: IStorageBackend, urlMinter: IStorageBackend);
33
53
  /**
34
54
  * Write in-memory bytes and return a durable delivery URL. Drop-in for the
35
55
  * ubiquitous `file.save(buf, { contentType })` + `getSignedUrl({ expires })`
@@ -49,32 +69,49 @@ export declare class MediaStorage {
49
69
  size: number;
50
70
  }>;
51
71
  /**
52
- * Best-effort R2 mirror of an object ALREADY written to the primary through a
53
- * bespoke path (a specialized streaming/integrity write we don't want to route
54
- * through `put`). No-op when disabled; never throws.
72
+ * Best-effort R2 copy of an object ALREADY written to GCS by one of the
73
+ * bespoke pipeline paths listed in the class doc (a specialized
74
+ * streaming/integrity write that doesn't route through `put`). Distinct
75
+ * from `put`'s unconditional R2 write above: these callers still write
76
+ * their real/primary copy to GCS themselves, so this R2 copy is genuinely
77
+ * best-effort and stays flag-gated. No-op when disabled; never throws.
55
78
  */
56
79
  mirrorBytes(objectPath: string, body: Buffer, contentType: string): Promise<void>;
57
80
  /**
58
- * Best-effort R2 mirror of a LOCAL FILE already written to the primary through
59
- * a bespoke streaming/integrity path (e.g. the google scene-download moov-atom
60
- * guard). Reads the file only when mirroring is enabled; never throws.
81
+ * Best-effort R2 copy of a LOCAL FILE already written to GCS through a
82
+ * bespoke streaming/integrity path (e.g. the google scene-download
83
+ * moov-atom guard). Reads the file only when mirroring is enabled; never
84
+ * throws.
61
85
  */
62
86
  mirrorFromFile(objectPath: string, localPath: string, contentType: string): Promise<void>;
63
87
  /**
64
- * Best-effort R2 mirror of an object ALREADY written to the primary,
65
- * streamed straight through from an open Readable (e.g. a GCS read stream)
66
- * without buffering it whole — for objects too large to safely hold in
67
- * process memory (resumable uploads, up to 1 GiB). No-op when disabled, when
68
- * the mirror backend doesn't implement streaming writes, or on failure.
88
+ * Best-effort R2 copy of an object ALREADY written to GCS, streamed
89
+ * straight through from an open Readable (e.g. a GCS read stream) without
90
+ * buffering it whole — for objects too large to safely hold in process
91
+ * memory (resumable uploads, up to 1 GiB). No-op when disabled, when the
92
+ * backend doesn't implement streaming writes, or on failure.
69
93
  */
70
94
  mirrorFromReadable(objectPath: string, stream: Readable, contentType: string, size: number): Promise<void>;
71
95
  /** Delivery URL for an object already stored. */
72
96
  signedReadUrl(objectPath: string): Promise<string>;
73
- /** Delete from both stores (mirror delete best-effort). */
97
+ /**
98
+ * Delete the object's bytes from R2. Does NOT touch GCS — since 2026-09-22
99
+ * new writes never land there, so there's nothing of record to delete. Any
100
+ * pre-flip object that still has a GCS copy becomes orphaned bytes there;
101
+ * acceptable, since GCS bulk cleanup is its own explicitly user-gated step
102
+ * (see notes/R2_MEDIA_MIGRATION_PLAN.md) — this doesn't make that step
103
+ * harder, just means it'll find a few objects Firestore no longer
104
+ * references.
105
+ */
74
106
  delete(objectPath: string): Promise<void>;
75
- /** Run a mirror op, swallowing failures — the primary write already stands. */
107
+ /**
108
+ * Run a legacy bespoke-pipeline mirror op, swallowing failures — the
109
+ * caller's own direct GCS write already stands regardless. Used only by
110
+ * mirrorBytes/mirrorFromFile/mirrorFromReadable above, never by
111
+ * put/putFromFile/delete (those need R2 to actually succeed).
112
+ */
76
113
  private bestEffortMirror;
77
114
  }
78
- /** App-wide singleton: GCS primary today, R2 mirror when enabled. */
115
+ /** App-wide singleton: R2 is the byte store, GCS mints the URL shape only. */
79
116
  export declare const mediaStorage: MediaStorage;
80
117
  //# sourceMappingURL=MediaStorage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"MediaStorage.d.ts","sourceRoot":"","sources":["../../../src/libs/storage/MediaStorage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAGvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGxD,6EAA6E;AAC7E,wBAAgB,gBAAgB,IAAI,OAAO,CAE1C;AAED,qBAAa,YAAY;IACvB,6CAA6C;IAC7C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkB;IAC1C,4DAA4D;IAC5D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;gBAE7B,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,eAAe;IAK7D;;;;;;OAMG;IACG,GAAG,CACP,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC;IAWlB;;;;;OAKG;IACG,WAAW,CACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAYzC;;;;OAIG;IACG,WAAW,CACf,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC;IAQhB;;;;OAIG;IACG,cAAc,CAClB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC;IAQhB;;;;;;OAMG;IACG,kBAAkB,CACtB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,QAAQ,EAChB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC;IAShB,iDAAiD;IACjD,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIlD,2DAA2D;IACrD,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO/C,+EAA+E;YACjE,gBAAgB;CAa/B;AAED,qEAAqE;AACrE,eAAO,MAAM,YAAY,cAAsD,CAAC"}
1
+ {"version":3,"file":"MediaStorage.d.ts","sourceRoot":"","sources":["../../../src/libs/storage/MediaStorage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAGvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGxD;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAE1C;AAED,qBAAa,YAAY;IACvB,iEAAiE;IACjE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkB;IACxC,0EAA0E;IAC1E,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAkB;gBAEhC,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,eAAe;IAK9D;;;;;;OAMG;IACG,GAAG,CACP,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC;IAKlB;;;;;OAKG;IACG,WAAW,CACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAMzC;;;;;;;OAOG;IACG,WAAW,CACf,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC;IAQhB;;;;;OAKG;IACG,cAAc,CAClB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC;IAQhB;;;;;;OAMG;IACG,kBAAkB,CACtB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,QAAQ,EAChB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC;IAShB,iDAAiD;IACjD,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIlD;;;;;;;;OAQG;IACG,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/C;;;;;OAKG;YACW,gBAAgB;CAa/B;AAED,8EAA8E;AAC9E,eAAO,MAAM,YAAY,cAAsD,CAAC"}
@@ -5,14 +5,18 @@ exports.isR2WriteEnabled = isR2WriteEnabled;
5
5
  const GcsBackend_1 = require("./GcsBackend");
6
6
  const R2Backend_1 = require("./R2Backend");
7
7
  const logger_1 = require("../../utils/logger");
8
- /** R2 mirror-writes are opt-in; off = today's GCS-only behavior, exactly. */
8
+ /**
9
+ * Legacy pipeline mirror-writes (see NOT COVERED above) stay opt-in behind
10
+ * this flag; unrelated to the `put`/`putFromFile`/`delete` R2-primary path,
11
+ * which is unconditional since 2026-09-22.
12
+ */
9
13
  function isR2WriteEnabled() {
10
14
  return process.env.R2_WRITE_ENABLED === "true";
11
15
  }
12
16
  class MediaStorage {
13
- constructor(primary, mirror) {
14
- this.primary = primary;
15
- this.mirror = mirror;
17
+ constructor(bytes, urlMinter) {
18
+ this.bytes = bytes;
19
+ this.urlMinter = urlMinter;
16
20
  }
17
21
  /**
18
22
  * Write in-memory bytes and return a durable delivery URL. Drop-in for the
@@ -22,11 +26,8 @@ class MediaStorage {
22
26
  * @param objectPath canonical object key, e.g. "final_videos/<id>.mp4"
23
27
  */
24
28
  async put(objectPath, body, contentType) {
25
- await this.primary.write(objectPath, body, contentType);
26
- if (isR2WriteEnabled()) {
27
- await this.bestEffortMirror(() => this.mirror.write(objectPath, body, contentType), objectPath);
28
- }
29
- return this.primary.signedReadUrl(objectPath);
29
+ await this.bytes.write(objectPath, body, contentType);
30
+ return this.urlMinter.signedReadUrl(objectPath);
30
31
  }
31
32
  /**
32
33
  * Stream a local file to the primary (no whole-file buffering) and return the
@@ -35,65 +36,76 @@ class MediaStorage {
35
36
  * scene-download moov-atom guard).
36
37
  */
37
38
  async putFromFile(objectPath, localPath, contentType) {
38
- const size = await this.primary.writeFromFile(objectPath, localPath, contentType);
39
- if (isR2WriteEnabled()) {
40
- await this.bestEffortMirror(() => this.mirror.writeFromFile(objectPath, localPath, contentType), objectPath);
41
- }
42
- const url = await this.primary.signedReadUrl(objectPath);
39
+ const size = await this.bytes.writeFromFile(objectPath, localPath, contentType);
40
+ const url = await this.urlMinter.signedReadUrl(objectPath);
43
41
  return { url, size };
44
42
  }
45
43
  /**
46
- * Best-effort R2 mirror of an object ALREADY written to the primary through a
47
- * bespoke path (a specialized streaming/integrity write we don't want to route
48
- * through `put`). No-op when disabled; never throws.
44
+ * Best-effort R2 copy of an object ALREADY written to GCS by one of the
45
+ * bespoke pipeline paths listed in the class doc (a specialized
46
+ * streaming/integrity write that doesn't route through `put`). Distinct
47
+ * from `put`'s unconditional R2 write above: these callers still write
48
+ * their real/primary copy to GCS themselves, so this R2 copy is genuinely
49
+ * best-effort and stays flag-gated. No-op when disabled; never throws.
49
50
  */
50
51
  async mirrorBytes(objectPath, body, contentType) {
51
52
  if (!isR2WriteEnabled())
52
53
  return;
53
- await this.bestEffortMirror(() => this.mirror.write(objectPath, body, contentType), objectPath);
54
+ await this.bestEffortMirror(() => this.bytes.write(objectPath, body, contentType), objectPath);
54
55
  }
55
56
  /**
56
- * Best-effort R2 mirror of a LOCAL FILE already written to the primary through
57
- * a bespoke streaming/integrity path (e.g. the google scene-download moov-atom
58
- * guard). Reads the file only when mirroring is enabled; never throws.
57
+ * Best-effort R2 copy of a LOCAL FILE already written to GCS through a
58
+ * bespoke streaming/integrity path (e.g. the google scene-download
59
+ * moov-atom guard). Reads the file only when mirroring is enabled; never
60
+ * throws.
59
61
  */
60
62
  async mirrorFromFile(objectPath, localPath, contentType) {
61
63
  if (!isR2WriteEnabled())
62
64
  return;
63
- await this.bestEffortMirror(() => this.mirror.writeFromFile(objectPath, localPath, contentType), objectPath);
65
+ await this.bestEffortMirror(() => this.bytes.writeFromFile(objectPath, localPath, contentType), objectPath);
64
66
  }
65
67
  /**
66
- * Best-effort R2 mirror of an object ALREADY written to the primary,
67
- * streamed straight through from an open Readable (e.g. a GCS read stream)
68
- * without buffering it whole — for objects too large to safely hold in
69
- * process memory (resumable uploads, up to 1 GiB). No-op when disabled, when
70
- * the mirror backend doesn't implement streaming writes, or on failure.
68
+ * Best-effort R2 copy of an object ALREADY written to GCS, streamed
69
+ * straight through from an open Readable (e.g. a GCS read stream) without
70
+ * buffering it whole — for objects too large to safely hold in process
71
+ * memory (resumable uploads, up to 1 GiB). No-op when disabled, when the
72
+ * backend doesn't implement streaming writes, or on failure.
71
73
  */
72
74
  async mirrorFromReadable(objectPath, stream, contentType, size) {
73
75
  if (!isR2WriteEnabled())
74
76
  return;
75
- if (!this.mirror.writeFromReadable)
77
+ if (!this.bytes.writeFromReadable)
76
78
  return;
77
- await this.bestEffortMirror(() => this.mirror.writeFromReadable(objectPath, stream, contentType, size), objectPath);
79
+ await this.bestEffortMirror(() => this.bytes.writeFromReadable(objectPath, stream, contentType, size), objectPath);
78
80
  }
79
81
  /** Delivery URL for an object already stored. */
80
82
  signedReadUrl(objectPath) {
81
- return this.primary.signedReadUrl(objectPath);
83
+ return this.urlMinter.signedReadUrl(objectPath);
82
84
  }
83
- /** Delete from both stores (mirror delete best-effort). */
85
+ /**
86
+ * Delete the object's bytes from R2. Does NOT touch GCS — since 2026-09-22
87
+ * new writes never land there, so there's nothing of record to delete. Any
88
+ * pre-flip object that still has a GCS copy becomes orphaned bytes there;
89
+ * acceptable, since GCS bulk cleanup is its own explicitly user-gated step
90
+ * (see notes/R2_MEDIA_MIGRATION_PLAN.md) — this doesn't make that step
91
+ * harder, just means it'll find a few objects Firestore no longer
92
+ * references.
93
+ */
84
94
  async delete(objectPath) {
85
- await this.primary.delete(objectPath);
86
- if (isR2WriteEnabled()) {
87
- await this.bestEffortMirror(() => this.mirror.delete(objectPath), objectPath);
88
- }
95
+ await this.bytes.delete(objectPath);
89
96
  }
90
- /** Run a mirror op, swallowing failures — the primary write already stands. */
97
+ /**
98
+ * Run a legacy bespoke-pipeline mirror op, swallowing failures — the
99
+ * caller's own direct GCS write already stands regardless. Used only by
100
+ * mirrorBytes/mirrorFromFile/mirrorFromReadable above, never by
101
+ * put/putFromFile/delete (those need R2 to actually succeed).
102
+ */
91
103
  async bestEffortMirror(op, objectPath) {
92
104
  try {
93
105
  await op();
94
106
  }
95
107
  catch (err) {
96
- logger_1.logger.error("MediaStorage: R2 mirror failed (primary write stands)", {
108
+ logger_1.logger.error("MediaStorage: R2 mirror failed (GCS write stands)", {
97
109
  objectPath,
98
110
  err: err instanceof Error ? err.stack ?? err.message : String(err),
99
111
  });
@@ -101,5 +113,5 @@ class MediaStorage {
101
113
  }
102
114
  }
103
115
  exports.MediaStorage = MediaStorage;
104
- /** App-wide singleton: GCS primary today, R2 mirror when enabled. */
105
- exports.mediaStorage = new MediaStorage(new GcsBackend_1.GcsBackend(), new R2Backend_1.R2Backend());
116
+ /** App-wide singleton: R2 is the byte store, GCS mints the URL shape only. */
117
+ exports.mediaStorage = new MediaStorage(new R2Backend_1.R2Backend(), new GcsBackend_1.GcsBackend());
@@ -4,8 +4,20 @@ export declare class R2Backend implements IStorageBackend {
4
4
  readonly name = "r2";
5
5
  private client;
6
6
  private init;
7
- /** True once creds+endpoint are present; a missing config is logged once. */
7
+ /**
8
+ * True once creds+endpoint are present. Since R2 became the sole byte
9
+ * store for `MediaStorage.put`/`putFromFile`/`delete` (2026-09-22), a
10
+ * missing config can no longer silently no-op here — that used to be safe
11
+ * when R2 was only a best-effort mirror (GCS's write still stood), but
12
+ * would now mean a `put()` returns a delivery URL for an object that was
13
+ * never actually written anywhere. `write`/`writeFromFile`/
14
+ * `writeFromReadable`/`delete` below throw when this returns null;
15
+ * `MediaStorage`'s legacy bespoke-pipeline mirror calls
16
+ * (mirrorBytes/mirrorFromFile/mirrorFromReadable) already wrap those in a
17
+ * try/catch, so the throw is caught and stays best-effort there.
18
+ */
8
19
  private getClient;
20
+ private requireClient;
9
21
  write(key: string, body: Buffer, contentType: string): Promise<void>;
10
22
  writeFromFile(key: string, localPath: string, contentType: string): Promise<number>;
11
23
  /**
@@ -16,7 +28,14 @@ export declare class R2Backend implements IStorageBackend {
16
28
  * up to 5GiB without multipart, comfortably covering our upload ceiling.
17
29
  */
18
30
  writeFromReadable(key: string, stream: Readable, contentType: string, size: number): Promise<void>;
19
- /** Delivery URL once R2 is primary: the CDN host + clean key. */
31
+ /**
32
+ * Bare CDN read URL (no signature/access-control). Not used as the actual
33
+ * delivery-URL source today — `MediaStorage` mints via `GcsBackend`
34
+ * instead, since the Worker doesn't recognize this bare-key shape and it
35
+ * carries no access control for private content (see MediaStorage.ts's
36
+ * class doc, "Stage 2 composition"). Kept for interface completeness /
37
+ * future use once a real signed-URL scheme exists for this shape.
38
+ */
20
39
  signedReadUrl(key: string): Promise<string>;
21
40
  delete(key: string): Promise<void>;
22
41
  }
@@ -1 +1 @@
1
- {"version":3,"file":"R2Backend.d.ts","sourceRoot":"","sources":["../../../src/libs/storage/R2Backend.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAIvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAyBxD,qBAAa,SAAU,YAAW,eAAe;IAC/C,QAAQ,CAAC,IAAI,QAAQ;IAGrB,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,IAAI,CAAyC;IAErD,6EAA6E;YAC/D,SAAS;IAoBjB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBpE,aAAa,CACjB,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC;IAQlB;;;;;;OAMG;IACG,iBAAiB,CACrB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,QAAQ,EAChB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC;IAiBhB,iEAAiE;IAC3D,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAI3C,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAQzC"}
1
+ {"version":3,"file":"R2Backend.d.ts","sourceRoot":"","sources":["../../../src/libs/storage/R2Backend.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAIvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAyBxD,qBAAa,SAAU,YAAW,eAAe;IAC/C,QAAQ,CAAC,IAAI,QAAQ;IAGrB,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,IAAI,CAAyC;IAErD;;;;;;;;;;;OAWG;YACW,SAAS;YAoBT,aAAa;IAQrB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAepE,aAAa,CACjB,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC;IAQlB;;;;;;OAMG;IACG,iBAAiB,CACrB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,QAAQ,EAChB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC;IAgBhB;;;;;;;OAOG;IACG,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAI3C,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAOzC"}
@@ -76,7 +76,18 @@ class R2Backend {
76
76
  this.client = null;
77
77
  this.init = null;
78
78
  }
79
- /** True once creds+endpoint are present; a missing config is logged once. */
79
+ /**
80
+ * True once creds+endpoint are present. Since R2 became the sole byte
81
+ * store for `MediaStorage.put`/`putFromFile`/`delete` (2026-09-22), a
82
+ * missing config can no longer silently no-op here — that used to be safe
83
+ * when R2 was only a best-effort mirror (GCS's write still stood), but
84
+ * would now mean a `put()` returns a delivery URL for an object that was
85
+ * never actually written anywhere. `write`/`writeFromFile`/
86
+ * `writeFromReadable`/`delete` below throw when this returns null;
87
+ * `MediaStorage`'s legacy bespoke-pipeline mirror calls
88
+ * (mirrorBytes/mirrorFromFile/mirrorFromReadable) already wrap those in a
89
+ * try/catch, so the throw is caught and stays best-effort there.
90
+ */
80
91
  async getClient() {
81
92
  if (this.client)
82
93
  return this.client;
@@ -85,7 +96,7 @@ class R2Backend {
85
96
  this.init = (async () => {
86
97
  const { accessKeyId, secretAccessKey, endpoint } = r2Config();
87
98
  if (!accessKeyId || !secretAccessKey || !endpoint) {
88
- logger_1.logger.warn("R2Backend: creds/endpoint missing — R2 ops will no-op");
99
+ logger_1.logger.warn("R2Backend: creds/endpoint missing — R2 ops will fail");
89
100
  return null;
90
101
  }
91
102
  const { S3Client: Client } = await Promise.resolve().then(() => __importStar(require("@aws-sdk/client-s3")));
@@ -98,10 +109,15 @@ class R2Backend {
98
109
  })();
99
110
  return this.init;
100
111
  }
101
- async write(key, body, contentType) {
112
+ async requireClient() {
102
113
  const client = await this.getClient();
103
- if (!client)
104
- return;
114
+ if (!client) {
115
+ throw new Error("R2Backend: creds/endpoint missing — cannot write/delete");
116
+ }
117
+ return client;
118
+ }
119
+ async write(key, body, contentType) {
120
+ const client = await this.requireClient();
105
121
  const { PutObjectCommand } = await Promise.resolve().then(() => __importStar(require("@aws-sdk/client-s3")));
106
122
  const r2Key = (0, r2KeyMap_1.toR2Key)(key);
107
123
  await client.send(new PutObjectCommand({
@@ -127,9 +143,7 @@ class R2Backend {
127
143
  * up to 5GiB without multipart, comfortably covering our upload ceiling.
128
144
  */
129
145
  async writeFromReadable(key, stream, contentType, size) {
130
- const client = await this.getClient();
131
- if (!client)
132
- return;
146
+ const client = await this.requireClient();
133
147
  const { PutObjectCommand } = await Promise.resolve().then(() => __importStar(require("@aws-sdk/client-s3")));
134
148
  const r2Key = (0, r2KeyMap_1.toR2Key)(key);
135
149
  await client.send(new PutObjectCommand({
@@ -141,14 +155,19 @@ class R2Backend {
141
155
  }));
142
156
  logger_1.logger.info("R2Backend: wrote object from stream", { key, r2Key, size });
143
157
  }
144
- /** Delivery URL once R2 is primary: the CDN host + clean key. */
158
+ /**
159
+ * Bare CDN read URL (no signature/access-control). Not used as the actual
160
+ * delivery-URL source today — `MediaStorage` mints via `GcsBackend`
161
+ * instead, since the Worker doesn't recognize this bare-key shape and it
162
+ * carries no access control for private content (see MediaStorage.ts's
163
+ * class doc, "Stage 2 composition"). Kept for interface completeness /
164
+ * future use once a real signed-URL scheme exists for this shape.
165
+ */
145
166
  async signedReadUrl(key) {
146
167
  return `${cdnBase()}/${(0, r2KeyMap_1.toR2Key)(key)}`;
147
168
  }
148
169
  async delete(key) {
149
- const client = await this.getClient();
150
- if (!client)
151
- return;
170
+ const client = await this.requireClient();
152
171
  const { DeleteObjectCommand } = await Promise.resolve().then(() => __importStar(require("@aws-sdk/client-s3")));
153
172
  await client.send(new DeleteObjectCommand({ Bucket: R2_BUCKET, Key: (0, r2KeyMap_1.toR2Key)(key) }));
154
173
  }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Backend counterpart of the frontend's `cdn()` helper
3
+ * (vidspot-frontend/src/lib/mediaCdn.ts). Both must stay in sync — same host
4
+ * prefixes, same `/gcs-pub/` `/gcs-priv/` tagging scheme the Worker
5
+ * (infra/cloudflare-media-cdn/worker.js) expects.
6
+ *
7
+ * Most delivery URLs (finalVideoUrl, posterUrl, etc.) are stored once in
8
+ * Firestore and rewritten to the CDN host at RENDER TIME by the frontend. But
9
+ * a few backend endpoints mint a URL and hand it straight to an external
10
+ * client themselves (share links, download redirects) — those never pass
11
+ * through the frontend's cdn(), so they need this to get R2 zero-egress
12
+ * delivery instead of a bare storage.googleapis.com URL.
13
+ */
14
+ export type MediaVisibility = "public" | "private";
15
+ /**
16
+ * Rewrite a Firebase Storage download URL or a GCS V4 signed URL (for our
17
+ * bucket) to the CDN host. Non-matching URLs are returned untouched.
18
+ *
19
+ * @param visibility Only affects GCS signed URLs — "public" (default) is a
20
+ * 1yr-immutable edge cache; "private" is a short edge TTL so a
21
+ * revoked/expired link stops being served within a day. Firebase download
22
+ * URLs are always treated as public.
23
+ */
24
+ export declare function toCdnUrl(url: string, opts?: {
25
+ visibility?: MediaVisibility;
26
+ }): string;
27
+ //# sourceMappingURL=cdnUrl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cdnUrl.d.ts","sourceRoot":"","sources":["../../../src/libs/storage/cdnUrl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAeH,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEnD;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CACtB,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,eAAe,CAAA;CAAE,GACtC,MAAM,CAeR"}
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ /**
3
+ * Backend counterpart of the frontend's `cdn()` helper
4
+ * (vidspot-frontend/src/lib/mediaCdn.ts). Both must stay in sync — same host
5
+ * prefixes, same `/gcs-pub/` `/gcs-priv/` tagging scheme the Worker
6
+ * (infra/cloudflare-media-cdn/worker.js) expects.
7
+ *
8
+ * Most delivery URLs (finalVideoUrl, posterUrl, etc.) are stored once in
9
+ * Firestore and rewritten to the CDN host at RENDER TIME by the frontend. But
10
+ * a few backend endpoints mint a URL and hand it straight to an external
11
+ * client themselves (share links, download redirects) — those never pass
12
+ * through the frontend's cdn(), so they need this to get R2 zero-egress
13
+ * delivery instead of a bare storage.googleapis.com URL.
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.toCdnUrl = toCdnUrl;
17
+ const FIREBASE_STORAGE_HOST = "https://firebasestorage.googleapis.com";
18
+ const GCS_HOST = "https://storage.googleapis.com";
19
+ const BUCKET = "vidspot-firebase.firebasestorage.app";
20
+ const GCS_SIGNED_PREFIX = `${GCS_HOST}/${BUCKET}/`;
21
+ function cdnBase() {
22
+ return (process.env.MEDIA_CDN_BASE ||
23
+ process.env.NEXT_PUBLIC_MEDIA_CDN_BASE ||
24
+ "https://cdn.vidspotai.com").replace(/\/+$/, "");
25
+ }
26
+ /**
27
+ * Rewrite a Firebase Storage download URL or a GCS V4 signed URL (for our
28
+ * bucket) to the CDN host. Non-matching URLs are returned untouched.
29
+ *
30
+ * @param visibility Only affects GCS signed URLs — "public" (default) is a
31
+ * 1yr-immutable edge cache; "private" is a short edge TTL so a
32
+ * revoked/expired link stops being served within a day. Firebase download
33
+ * URLs are always treated as public.
34
+ */
35
+ function toCdnUrl(url, opts) {
36
+ const base = cdnBase();
37
+ if (!url || !base)
38
+ return url;
39
+ if (url.startsWith(FIREBASE_STORAGE_HOST)) {
40
+ return base + url.slice(FIREBASE_STORAGE_HOST.length);
41
+ }
42
+ if (url.startsWith(GCS_SIGNED_PREFIX)) {
43
+ const rest = url.slice(GCS_HOST.length); // "/<bucket>/<object>?<signed>"
44
+ const seg = opts?.visibility === "private" ? "gcs-priv" : "gcs-pub";
45
+ return `${base}/${seg}${rest}`;
46
+ }
47
+ return url;
48
+ }
@@ -2,4 +2,5 @@ export * from "./StorageBackend";
2
2
  export * from "./GcsBackend";
3
3
  export * from "./R2Backend";
4
4
  export * from "./MediaStorage";
5
+ export * from "./cdnUrl";
5
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/libs/storage/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/libs/storage/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,UAAU,CAAC"}
@@ -18,3 +18,4 @@ __exportStar(require("./StorageBackend"), exports);
18
18
  __exportStar(require("./GcsBackend"), exports);
19
19
  __exportStar(require("./R2Backend"), exports);
20
20
  __exportStar(require("./MediaStorage"), exports);
21
+ __exportStar(require("./cdnUrl"), exports);
@@ -31,6 +31,33 @@ export interface IBrandKitModel {
31
31
  * talking-head-avatar strategy. Planner injects into PlannedScene.avatarFaceUrl.
32
32
  */
33
33
  presenterFaceUrl?: string;
34
+ /**
35
+ * Trained hosted-avatar likenesses ("create your own avatar" — Reach
36
+ * Phase 4). Each entry backs one `ISupportsReplica.createReplica` call;
37
+ * once `status: "ready"`, `replicaId` is used directly as a template's
38
+ * `hostedAvatarId` for that `engine`.
39
+ */
40
+ avatarReplicas?: IAvatarReplica[];
41
+ createdAt: string;
42
+ updatedAt: string;
43
+ }
44
+ export interface IAvatarReplica {
45
+ /** Stable per-entry id (uuid), minted at creation — NOT the provider's replicaId. */
46
+ id: string;
47
+ engine: "heygen" | "tavus";
48
+ /** Which avatar model this replica renders through (e.g. heygen-avatar / tavus-avatar). */
49
+ modelKey: string;
50
+ /** Provider-scoped id — once ready, pass straight through as `hostedAvatarId`. */
51
+ replicaId: string;
52
+ /** Opaque per-engine bookkeeping round-tripped to `checkReplicaStatus` unchanged. */
53
+ providerRef?: string;
54
+ status: "training" | "pending_consent" | "ready" | "failed";
55
+ /** Hosted consent page the subject must open (HeyGen); absent for engines
56
+ * that capture consent as part of training itself (Tavus). */
57
+ consentUrl?: string;
58
+ errorMessage?: string;
59
+ /** User-facing label, e.g. "My avatar". */
60
+ name?: string;
34
61
  createdAt: string;
35
62
  updatedAt: string;
36
63
  }