deepline 0.3.423 → 0.3.425

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 (115) hide show
  1. package/dist/bundling-sources/sdk/src/client.ts +13 -6
  2. package/dist/bundling-sources/sdk/src/release.ts +1 -1
  3. package/dist/bundling-sources/shared_libs/monitors/fleets/verdict.ts +11 -1
  4. package/dist/bundling-sources/shared_libs/monitors/inventory-reconciliation.ts +38 -4
  5. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-batch-operation.ts +12 -0
  6. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-control-plane-capability.ts +25 -0
  7. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-errors.ts +10 -0
  8. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-identity-claims.ts +201 -0
  9. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-state.ts +42 -5
  10. package/dist/bundling-sources/shared_libs/monitors/provider-webhook-monitor-runtime.ts +5 -0
  11. package/dist/bundling-sources/shared_libs/observability/scheduled-jobs.json +18 -0
  12. package/dist/cli/auth-PTKVFEIT.js +40 -0
  13. package/dist/cli/{auth-L7Q53QKK.mjs → auth-RF5WGHBC.mjs} +4 -4
  14. package/dist/cli/{billing-QNP6YGI2.js → billing-E4G4QVR5.js} +73 -73
  15. package/dist/cli/{billing-IH7AKDR2.mjs → billing-P4RUJ4UT.mjs} +4 -4
  16. package/dist/cli/{chunk-2F5ULM2F.js → chunk-2ACYJZHU.js} +1 -1
  17. package/dist/cli/{chunk-FJRFSBWO.mjs → chunk-2J2I5A7K.mjs} +4 -4
  18. package/dist/cli/{chunk-RAL75ND3.js → chunk-53DTOGNJ.js} +2 -2
  19. package/dist/cli/{chunk-EWWWOKX2.js → chunk-7F6KTNUP.js} +6 -6
  20. package/dist/cli/{chunk-QN6DG4JO.mjs → chunk-BFVDDMRH.mjs} +2 -2
  21. package/dist/cli/{chunk-4WT5RISA.js → chunk-CSP5CXTC.js} +20 -20
  22. package/dist/cli/{chunk-S6KG7JCR.mjs → chunk-E7RPU3VG.mjs} +2 -2
  23. package/dist/cli/{chunk-44US3EL2.mjs → chunk-FDM3BUIB.mjs} +5 -5
  24. package/dist/cli/{chunk-OPI7UCQG.mjs → chunk-HT3UBTXV.mjs} +1 -1
  25. package/dist/cli/{chunk-2U3AMRHF.js → chunk-IJPWBQEA.js} +8 -8
  26. package/dist/cli/{chunk-YCHR57TD.js → chunk-J6FKYOFB.js} +35 -35
  27. package/dist/cli/{chunk-YNT7PJND.mjs → chunk-MWR452MP.mjs} +3 -3
  28. package/dist/cli/{chunk-OZLMMMZH.js → chunk-NC5DYZ36.js} +6 -6
  29. package/dist/cli/{chunk-6FFORGD2.mjs → chunk-NUET45RU.mjs} +1 -1
  30. package/dist/cli/{chunk-NFIZ5YED.mjs → chunk-ODO6ZIHB.mjs} +2 -2
  31. package/dist/cli/{chunk-IW5QK3K6.mjs → chunk-P7SNOFPA.mjs} +3 -3
  32. package/dist/cli/{chunk-DRK6FYJU.js → chunk-RH2N5JUT.js} +26 -26
  33. package/dist/cli/{chunk-MHG3NND4.mjs → chunk-RTFXD5ZX.mjs} +3 -3
  34. package/dist/cli/{chunk-XSERB7H2.mjs → chunk-S5FCTT3E.mjs} +1 -1
  35. package/dist/cli/{chunk-PQ4G6MKI.js → chunk-SBPPCMZD.js} +16 -16
  36. package/dist/cli/{chunk-W42SSVM7.js → chunk-U42S2GAF.js} +4 -4
  37. package/dist/cli/{chunk-PH4BP6KM.mjs → chunk-UDRNGM3S.mjs} +2 -2
  38. package/dist/cli/{chunk-AVOBDFQ5.js → chunk-UXLJZ4XQ.js} +10 -10
  39. package/dist/cli/{chunk-QWJJMQNE.mjs → chunk-VYO6TLWN.mjs} +1 -1
  40. package/dist/cli/{chunk-ARTGL3FM.mjs → chunk-WNXYRODJ.mjs} +1 -1
  41. package/dist/cli/{chunk-WJO7KIFT.js → chunk-WZLGL37A.js} +50 -50
  42. package/dist/cli/{chunk-JDAXVQV7.mjs → chunk-XC3J4P5W.mjs} +1 -1
  43. package/dist/cli/{chunk-H662SHPT.mjs → chunk-XLEA2CGA.mjs} +8 -8
  44. package/dist/cli/{chunk-5DGR3TB6.js → chunk-XN25EAP6.js} +2 -2
  45. package/dist/cli/{chunk-NA6SGG7X.js → chunk-XO5RJ3PF.js} +79 -79
  46. package/dist/cli/{chunk-MMI2DXCW.js → chunk-XSC2FG4V.js} +8 -8
  47. package/dist/cli/{chunk-OMWO2JLC.js → chunk-ZYUKNQO4.js} +52 -52
  48. package/dist/cli/{csv-GF7VRES5.js → csv-P32NU7IS.js} +12 -12
  49. package/dist/cli/{csv-5KW7M6ZS.mjs → csv-XKCR2MB6.mjs} +3 -3
  50. package/dist/cli/{db-AEDXKB4F.js → db-AHFQJ7ZN.js} +25 -25
  51. package/dist/cli/{db-NN4JQAC4.mjs → db-ZJQPREBZ.mjs} +4 -4
  52. package/dist/cli/{describe-RX6VROHQ.mjs → describe-IZNT6RGY.mjs} +12 -12
  53. package/dist/cli/{describe-5RLXW332.js → describe-YE2WIS23.js} +16 -16
  54. package/dist/cli/describe-core.d.mts +1 -1
  55. package/dist/cli/describe-core.d.ts +1 -1
  56. package/dist/cli/{executions-PGIGFDDS.js → executions-EZDFYAWW.js} +6 -6
  57. package/dist/cli/{executions-EJZ34VUB.mjs → executions-WLRZODFZ.mjs} +4 -4
  58. package/dist/cli/{feedback-L2ODMANV.js → feedback-A62XZMY2.js} +7 -7
  59. package/dist/cli/{feedback-6MWOKE7H.mjs → feedback-M6TNBIUP.mjs} +3 -3
  60. package/dist/cli/git-62FZH46U.js +24 -0
  61. package/dist/cli/{git-456RF3AT.mjs → git-XYDEA57G.mjs} +4 -4
  62. package/dist/cli/index.js +131 -131
  63. package/dist/cli/index.mjs +36 -36
  64. package/dist/cli/{legacy-noops-MDPB3MIS.js → legacy-noops-D34K4LWU.js} +7 -7
  65. package/dist/cli/{legacy-noops-ZPRBXQDE.mjs → legacy-noops-S4XSVXIN.mjs} +4 -4
  66. package/dist/cli/{monitors-TXKR5XYW.js → monitors-VUSDOVGA.js} +97 -91
  67. package/dist/cli/{monitors-ZLP6A7FT.mjs → monitors-YDHQJMMQ.mjs} +17 -11
  68. package/dist/cli/{org-YZ62BIGM.mjs → org-EF7Q22GZ.mjs} +4 -4
  69. package/dist/cli/{org-73SQ3AT2.js → org-IRWGFW3I.js} +64 -64
  70. package/dist/cli/{play-M75EBXEV.js → play-D54PEGMK.js} +283 -283
  71. package/dist/cli/{play-VCYQKCKF.mjs → play-Y4O3WFYH.mjs} +10 -10
  72. package/dist/cli/{providers-GIINJPWQ.js → providers-2NPEOE22.js} +7 -7
  73. package/dist/cli/{providers-JLA6LST3.mjs → providers-PX672XRG.mjs} +4 -4
  74. package/dist/cli/{quickstart-HHHLYCHT.js → quickstart-3XXUIDVF.js} +5 -5
  75. package/dist/cli/{quickstart-AHCU75GG.mjs → quickstart-KSFYOZGU.mjs} +3 -3
  76. package/dist/cli/{search-5GACUIAX.mjs → search-DIATDWNB.mjs} +5 -5
  77. package/dist/cli/search-TW7PGWYR.js +30 -0
  78. package/dist/cli/{secrets-S2NBKAEN.mjs → secrets-HSZNYSHN.mjs} +4 -4
  79. package/dist/cli/{secrets-PI7IPCOE.js → secrets-S7J53N4D.js} +13 -13
  80. package/dist/cli/{sessions-IBKYGTBD.mjs → sessions-BLJ5AZ2O.mjs} +4 -4
  81. package/dist/cli/{sessions-BK4CSRFS.js → sessions-ECOJWISN.js} +5 -5
  82. package/dist/cli/{settings-JY6UN4KO.mjs → settings-4X2OSKMC.mjs} +8 -8
  83. package/dist/cli/{settings-2G7TUDM7.js → settings-BMKHMIN2.js} +75 -75
  84. package/dist/cli/{setup-R424FIBF.js → setup-GOT6Y2E3.js} +42 -42
  85. package/dist/cli/{setup-HS5X3OSN.mjs → setup-NUEJ22OI.mjs} +7 -7
  86. package/dist/cli/skills-DCOMWBDX.js +29 -0
  87. package/dist/cli/{skills-UIBUDTGN.mjs → skills-FCLEKW4O.mjs} +5 -5
  88. package/dist/cli/{tools-SB4FREB6.mjs → tools-IVCHIOIY.mjs} +12 -12
  89. package/dist/cli/tools-OAYJGYL7.js +44 -0
  90. package/dist/cli/update-2DBL37AU.js +31 -0
  91. package/dist/cli/{update-NJSUE2YU.mjs → update-Y5RO5LSX.mjs} +7 -7
  92. package/dist/cli/{workflow-HBG76XYX.mjs → workflow-CSVQCXJZ.mjs} +5 -5
  93. package/dist/cli/{workflow-3AZWZ4J3.js → workflow-XGN3FZAE.js} +15 -15
  94. package/dist/{client-BTUOYGID.d.mts → client-BcfFWD4Z.d.mts} +9 -6
  95. package/dist/{client-C668iUhZ.d.ts → client-DH-fmT69.d.ts} +9 -6
  96. package/dist/index.d.mts +2 -2
  97. package/dist/index.d.ts +2 -2
  98. package/dist/index.js +6 -6
  99. package/dist/index.mjs +3 -3
  100. package/dist/install-integrity.json +80 -80
  101. package/dist/plays/play-description.d.mts +1 -1
  102. package/dist/plays/play-description.d.ts +1 -1
  103. package/dist/plays/run-request.d.mts +1 -1
  104. package/dist/plays/run-request.d.ts +1 -1
  105. package/dist/release.d.mts +1 -1
  106. package/dist/release.d.ts +1 -1
  107. package/dist/release.js +2 -2
  108. package/dist/release.mjs +1 -1
  109. package/package.json +1 -1
  110. package/dist/cli/auth-SUNY477Y.js +0 -40
  111. package/dist/cli/git-2ZDCRTBD.js +0 -24
  112. package/dist/cli/search-W2PGBXQO.js +0 -30
  113. package/dist/cli/skills-M3RZAN4A.js +0 -29
  114. package/dist/cli/tools-K2GII2PA.js +0 -44
  115. package/dist/cli/update-C2ORJRXN.js +0 -31
@@ -1194,12 +1194,18 @@ export type MonitorsAvailableOptions = {
1194
1194
  /**
1195
1195
  * Stable customer-facing Monitor/Fleet state.
1196
1196
  *
1197
- * Provider provisioning, cleanup, retries, and failures are Monitor Job
1198
- * progress and must never be added to this union. The `status` and `active`
1199
- * fields below are retained only as deprecated compatibility aliases for
1200
- * older API responses.
1197
+ * `provisioning` is a monitor whose create was recorded but that the provider
1198
+ * has not confirmed yet; it delivers no events and does not bill until it
1199
+ * becomes `active`. A Fleet is never `provisioning`. Provider cleanup,
1200
+ * retries, and failures are Monitor Job progress and must never be added to
1201
+ * this union. The `status` and `active` fields below are retained only as
1202
+ * deprecated compatibility aliases for older API responses.
1201
1203
  */
1202
- export type MonitorState = 'active' | 'billing_suspended' | 'disabled';
1204
+ export type MonitorState =
1205
+ | 'active'
1206
+ | 'provisioning'
1207
+ | 'billing_suspended'
1208
+ | 'disabled';
1203
1209
 
1204
1210
  /** List filters accepted by the canonical state surface. */
1205
1211
  export type MonitorStateFilter = MonitorState | 'all';
@@ -1873,7 +1879,8 @@ export type MonitorsNamespace = {
1873
1879
  options?: MonitorLifecycleOptions,
1874
1880
  ) => Promise<MonitorJobResult | MonitorDeployResult>;
1875
1881
  /** List deployed monitors (active by default). Use `state` to filter the
1876
- * three customer states; `status` is retained for older servers.
1882
+ * four customer states (`active`, `provisioning`, `billing_suspended`,
1883
+ * `disabled`); `status` is retained for older servers.
1877
1884
  * `includeConsumers` requires a limit of 20 or fewer. */
1878
1885
  list: (options?: MonitorsListOptions) => Promise<MonitorsListResult>;
1879
1886
  /** Fetch one deployed monitor by public key with bounded current listener health. */
@@ -205,7 +205,7 @@ export const SDK_RELEASE = {
205
205
  // getters keep their established compatibility behavior.
206
206
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
207
207
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
208
- version: '0.3.423',
208
+ version: '0.3.425',
209
209
  updateSummary: {
210
210
  introducedIn: '0.3.90',
211
211
  summary:
@@ -46,6 +46,16 @@ export type FleetStatusVerdict =
46
46
  | 'billing_suspended'
47
47
  | 'billing_reactivating';
48
48
 
49
+ /**
50
+ * A Fleet's customer state. A Fleet has no `provisioning` state: its first
51
+ * convergence is reported by the durable Fleet operation, while each member
52
+ * monitor still pending its create reports `provisioning` itself.
53
+ */
54
+ export type FleetCustomerState = Exclude<
55
+ ProviderMonitorCustomerState,
56
+ 'provisioning'
57
+ >;
58
+
49
59
  /**
50
60
  * The Fleet's stable customer state. Convergence and lifecycle transitions are
51
61
  * reported by the durable Fleet operation, not by growing this union.
@@ -54,7 +64,7 @@ export function fleetCustomerState(input: {
54
64
  lifecycle: FleetLifecycleStatus;
55
65
  verdict: FleetStatusVerdict;
56
66
  convergedGeneration: number | null;
57
- }): ProviderMonitorCustomerState {
67
+ }): FleetCustomerState {
58
68
  switch (input.lifecycle) {
59
69
  case 'billing_suspending':
60
70
  case 'billing_suspended':
@@ -9,6 +9,17 @@ export type InventoryDecision = {
9
9
  radarId?: string;
10
10
  };
11
11
 
12
+ /**
13
+ * Desynced definition findings that audit-scoped repair acts on. Every other
14
+ * desynced reason is resolved elsewhere (operator bind, orphan cleanup), so
15
+ * submitting repair for it would be a no-op that recurs every audit.
16
+ */
17
+ export const GLOBAL_AUDIT_REPAIRABLE_REASONS: ReadonlySet<string> = new Set([
18
+ 'missing_tamradar_radar',
19
+ 'tamradar_state_differs',
20
+ 'tamradar_configuration_differs',
21
+ ]);
22
+
12
23
  /** Call only after BOTH inventories completed. Absence is otherwise unknown. */
13
24
  export function compareMonitorInventory(input: {
14
25
  desired: 'active' | 'inactive';
@@ -24,20 +35,43 @@ export function compareMonitorInventory(input: {
24
35
  if (!resourceId) {
25
36
  if (marker.length > 1)
26
37
  return { verdict: 'unknown', reason: 'ambiguous_tamradar_binding' };
27
- if (marker.length === 1)
38
+ const stamped = marker[0];
39
+ if (stamped && desired === 'active')
28
40
  return {
29
41
  verdict: 'desynced',
30
42
  reason: 'adoptable_tamradar_radar',
31
- radarId: marker[0]!.id,
43
+ radarId: stamped.id,
32
44
  };
45
+ // An inactive definition never adopts: binding refuses a row that may not
46
+ // occupy an upstream identity. Its stamped radar is either already closed
47
+ // or a live leftover that provider-side orphan cleanup owns.
48
+ if (stamped) {
49
+ if (stamped.status === 'unknown')
50
+ return {
51
+ verdict: 'unknown',
52
+ reason: 'unknown_tamradar_state',
53
+ radarId: stamped.id,
54
+ };
55
+ return stamped.status === 'inactive'
56
+ ? { verdict: 'converged', reason: 'in_sync', radarId: stamped.id }
57
+ : {
58
+ verdict: 'desynced',
59
+ reason: 'orphaned_tamradar_radar',
60
+ radarId: stamped.id,
61
+ };
62
+ }
33
63
  }
34
64
  const radar = exact[0];
35
65
  if (!radar) {
36
66
  if (!resourceId) {
37
67
  // A complete account list proves that no stamped counterpart exists; it
38
68
  // cannot prove which resource an unbound historical row used to own.
39
- // Creation or adoption is a separate, explicit operator operation.
40
- return { verdict: 'unknown', reason: 'missing_tamradar_binding' };
69
+ // Creation or adoption is a separate, explicit operator operation. An
70
+ // inactive row wants nothing upstream, and a markerless legacy radar is
71
+ // reported on the provider side as unattributed, so it has converged.
72
+ return desired === 'inactive'
73
+ ? { verdict: 'converged', reason: 'in_sync' }
74
+ : { verdict: 'unknown', reason: 'missing_tamradar_binding' };
41
75
  }
42
76
  return desired === 'inactive'
43
77
  ? { verdict: 'converged', reason: 'in_sync' }
@@ -235,6 +235,18 @@ export function providerMonitorBatchOperationId(input: {
235
235
  return `monitor-batch:${orgId}:${idempotencyKey}`;
236
236
  }
237
237
 
238
+ /**
239
+ * The lifecycle operation one batch run creates one monitor under. A row the
240
+ * run writes ahead names it, and its settle publishes under it, so both must
241
+ * derive it here.
242
+ */
243
+ export function providerMonitorBatchCreateOperationId(
244
+ runId: string,
245
+ monitorKey: string,
246
+ ): string {
247
+ return `${runId}:provider-create:${monitorKey}`;
248
+ }
249
+
238
250
  export function isProviderMonitorBatchOperationKind(
239
251
  value: string,
240
252
  ): value is ProviderMonitorBatchOperationKind {
@@ -37,6 +37,31 @@ export function providerMonitorBatchOperationContinuationSecret(
37
37
  );
38
38
  }
39
39
 
40
+ /**
41
+ * TEMPORARY(#8221), disabled. Uncomment this, its re-export in
42
+ * apps/deepline-api/src/lib/monitors/provider-monitor-control-plane-capability.ts,
43
+ * the `expected` line in the five webhook-reconciliation continuation routes,
44
+ * and `reconciliationSecret` in scripts/lib/monitor-load-test-dispatch-config.ts
45
+ * together to let the update-feed reconciliation self-drive on a Preview.
46
+ *
47
+ * The webhook-reconciliation continuation routes accept only the dedicated
48
+ * secret, which Preview does not carry, so the update-feed reconciliation can
49
+ * never self-drive on a Preview and the monitor load test's Stage 2 cannot
50
+ * exercise it. On a Vercel Preview with no dedicated secret, this also accepts
51
+ * the capability derived from the Preview internal token, which the load-test
52
+ * driver sets on the branch Convex. Production carries the dedicated secret
53
+ * and is unaffected.
54
+ */
55
+ // export function providerMonitorReconciliationContinuationSecret(
56
+ // env: Record<string, string | undefined> = process.env,
57
+ // ): string | undefined {
58
+ // const dedicated = env[LEGACY_SECRET_ENV]?.trim();
59
+ // if (dedicated) return dedicated;
60
+ // return env.VERCEL_ENV === 'preview'
61
+ // ? derivedControlPlaneCapability(env)
62
+ // : undefined;
63
+ // }
64
+
40
65
  export function providerMonitorGlobalAuditContinuationSecret(
41
66
  env: Record<string, string | undefined> = process.env,
42
67
  ): string | undefined {
@@ -121,6 +121,16 @@ export class ProviderMonitorDeleteOperationInProgressError extends Error {
121
121
  }
122
122
  }
123
123
 
124
+ /** A deploy found the monitor stopped or deleted after it was submitted. */
125
+ export class ProviderMonitorStoppedAfterSubmitError extends Error {
126
+ constructor(readonly monitorKey: string) {
127
+ super(
128
+ `Monitor "${monitorKey}" was stopped or deleted after this deploy was submitted, so the deploy left it as it is. Deploy it again to turn it back on.`,
129
+ );
130
+ this.name = 'ProviderMonitorStoppedAfterSubmitError';
131
+ }
132
+ }
133
+
124
134
  export class PriorityMonitorExecutionLimitError extends Error {
125
135
  constructor(readonly max: number) {
126
136
  super(
@@ -6,6 +6,7 @@ import {
6
6
  ProviderMonitorIdentityBackfillInProgressError,
7
7
  ProviderMonitorEntityLimitExceededError,
8
8
  ProviderMonitorOrgLimitExceededError,
9
+ type ProviderMonitorCapacitySnapshot,
9
10
  } from '@deepline/monitors/provider-monitor-errors';
10
11
  import { MAX_PRIORITY_MONITORS_PER_ORG } from '@deepline/monitors/provider-monitor-priority-execution';
11
12
  import { internal } from '@deepline/convex-client/function-references';
@@ -374,6 +375,206 @@ export async function beginProviderMonitorLifecycleReservation(input: {
374
375
  });
375
376
  }
376
377
 
378
+ /** Keys one batch provisioning call fences: Convex's own 100-key bound. */
379
+ const PROVISIONING_BATCH_CHUNK = 100;
380
+
381
+ /**
382
+ * One item's lifecycle admission, decided for its whole chunk ahead of time.
383
+ *
384
+ * Calling it yields exactly what `beginProviderMonitorLifecycleReservation`
385
+ * would have yielded for the item - the same reservation, or the same typed
386
+ * refusal thrown - so a caller can swap one for the other per item.
387
+ */
388
+ export type ProviderMonitorLifecycleAdmission =
389
+ () => Promise<ProviderMonitorLifecycleReservation>;
390
+
391
+ /**
392
+ * Begin the provisioning fence for many new monitors, taking organization
393
+ * capacity once per chunk of 100 instead of once per item.
394
+ *
395
+ * Per chunk: one query counts which accounts already carry a monitor, one
396
+ * short mutation (`reserveProvisioningCapacityAdmission`) takes allowance for
397
+ * the accounts the chunk will open, and one transaction
398
+ * (`beginLifecycleProvisioningBatch`) fences every item against that grant
399
+ * without touching the organization fence. Items the grant cannot decide
400
+ * exactly are admitted by the scalar path when their admission is called.
401
+ *
402
+ * Asking for exactly the accounts with no monitor yet keeps the grant from
403
+ * holding allowance a concurrent job could use. Planning can race another
404
+ * writer either way: an account opened meanwhile simply hands its unit back
405
+ * when the chunk settles, and an item that needs a unit nobody asked for is
406
+ * handed to the scalar path - never refused by a limit the fence did not hit.
407
+ */
408
+ export async function beginProviderMonitorProvisioningBatch(input: {
409
+ auth: OrgAuthContext;
410
+ items: ReadonlyArray<{
411
+ monitorKey: string;
412
+ operationId: string;
413
+ entityKey?: string | null;
414
+ }>;
415
+ }): Promise<Map<string, ProviderMonitorLifecycleAdmission>> {
416
+ const client = getRequiredInternalConvexClient();
417
+ const orgId = input.auth.orgId;
418
+ const admissions = new Map<string, ProviderMonitorLifecycleAdmission>();
419
+ const scalar =
420
+ (item: (typeof input.items)[number]): ProviderMonitorLifecycleAdmission =>
421
+ () =>
422
+ beginProviderMonitorLifecycleReservation({
423
+ auth: input.auth,
424
+ monitorKey: item.monitorKey,
425
+ operationId: item.operationId,
426
+ entityKey: item.entityKey ?? null,
427
+ state: 'provisioning',
428
+ });
429
+ for (
430
+ let offset = 0;
431
+ offset < input.items.length;
432
+ offset += PROVISIONING_BATCH_CHUNK
433
+ ) {
434
+ const chunk = input.items.slice(offset, offset + PROVISIONING_BATCH_CHUNK);
435
+ const entityKeyOf = (item: (typeof chunk)[number]) =>
436
+ item.entityKey || `monitor:${item.monitorKey}`;
437
+ const entityKeys = [...new Set(chunk.map(entityKeyOf))];
438
+ const counts = (await client.query(
439
+ internal.providerMonitorCapacity.countMonitorsByEntities,
440
+ { orgId, entityKeys },
441
+ )) as Array<{ entityKey: string; monitors: number }>;
442
+ const requested = counts.filter((count) => count.monitors === 0).length;
443
+ const reservationId = `direct-batch-provisioning:${randomUUID()}`;
444
+ const admission =
445
+ requested > 0
446
+ ? ((await retryProviderMonitorLifecycleAdmission(() =>
447
+ client.mutation(
448
+ internal.providerMonitorCapacity
449
+ .reserveProvisioningCapacityAdmission,
450
+ { orgId, reservationId, requested },
451
+ ),
452
+ )) as {
453
+ granted: number;
454
+ capacity: ProviderMonitorCapacitySnapshot & {
455
+ monitors_per_entity: number;
456
+ };
457
+ })
458
+ : null;
459
+ let batch: {
460
+ items: Array<
461
+ | { monitorKey: string; kind: 'acquired' }
462
+ | {
463
+ monitorKey: string;
464
+ kind: 'in_progress' | 'deleting';
465
+ state: 'provisioning' | 'deleting';
466
+ retryAt: number;
467
+ }
468
+ | { monitorKey: string; kind: 'limit_exceeded' }
469
+ | {
470
+ monitorKey: string;
471
+ kind: 'entity_limit_exceeded';
472
+ entityKey: string;
473
+ monitorsPerEntity: number;
474
+ }
475
+ | { monitorKey: string; kind: 'cleanup_blocked' }
476
+ | { monitorKey: string; kind: 'fallback' }
477
+ >;
478
+ };
479
+ try {
480
+ batch = await retryProviderMonitorLifecycleAdmission(() =>
481
+ client.mutation(
482
+ internal.providerMonitorIdentityClaims
483
+ .beginLifecycleProvisioningBatch,
484
+ {
485
+ orgId,
486
+ ...(admission ? { reservationId } : {}),
487
+ items: chunk.map((item) => ({
488
+ monitorKey: item.monitorKey,
489
+ operationId: item.operationId,
490
+ entityKey: entityKeyOf(item),
491
+ })),
492
+ },
493
+ ),
494
+ );
495
+ } catch (error) {
496
+ // Hand the grant back now rather than when it expires. Safe whether or
497
+ // not the batch committed: a committed batch consumed the grant, and
498
+ // releasing a consumed grant is a no-op.
499
+ if (admission && admission.granted > 0) {
500
+ await client
501
+ .mutation(
502
+ internal.providerMonitorCapacity.releaseExpiredOrgCapacityAdmission,
503
+ { orgId, reservationId },
504
+ )
505
+ .catch(() => undefined);
506
+ }
507
+ // Every item of the chunk fails the way its own admission would have
508
+ // failed, on its own retry path; the error is not swallowed.
509
+ for (const item of chunk) {
510
+ admissions.set(item.monitorKey, () => Promise.reject(error));
511
+ }
512
+ continue;
513
+ }
514
+ const byKey = new Map(chunk.map((item) => [item.monitorKey, item]));
515
+ for (const result of batch.items) {
516
+ const item = byKey.get(result.monitorKey);
517
+ if (!item) {
518
+ throw new Error(
519
+ `Provider monitor batch provisioning answered for unknown monitor ${result.monitorKey}.`,
520
+ );
521
+ }
522
+ byKey.delete(result.monitorKey);
523
+ switch (result.kind) {
524
+ case 'acquired':
525
+ case 'in_progress':
526
+ case 'deleting': {
527
+ const reservation = normalizeProviderMonitorLifecycleReservation({
528
+ result,
529
+ state: 'provisioning',
530
+ operationId: item.operationId,
531
+ });
532
+ admissions.set(item.monitorKey, async () => reservation);
533
+ break;
534
+ }
535
+ case 'limit_exceeded': {
536
+ if (!admission) {
537
+ throw new Error(
538
+ 'Provider monitor batch provisioning refused an account it was never asked to grant.',
539
+ );
540
+ }
541
+ const capacity = admission.capacity;
542
+ admissions.set(item.monitorKey, () =>
543
+ Promise.reject(new ProviderMonitorOrgLimitExceededError(capacity)),
544
+ );
545
+ break;
546
+ }
547
+ case 'entity_limit_exceeded':
548
+ admissions.set(item.monitorKey, () =>
549
+ Promise.reject(
550
+ new ProviderMonitorEntityLimitExceededError(
551
+ result.entityKey,
552
+ result.monitorsPerEntity,
553
+ ),
554
+ ),
555
+ );
556
+ break;
557
+ case 'cleanup_blocked':
558
+ admissions.set(item.monitorKey, () =>
559
+ Promise.reject(
560
+ new ProviderMonitorCapacityCleanupRequiredError(item.monitorKey),
561
+ ),
562
+ );
563
+ break;
564
+ case 'fallback':
565
+ admissions.set(item.monitorKey, scalar(item));
566
+ break;
567
+ }
568
+ }
569
+ if (byKey.size > 0) {
570
+ throw new Error(
571
+ 'Provider monitor batch provisioning did not answer for every monitor key.',
572
+ );
573
+ }
574
+ }
575
+ return admissions;
576
+ }
577
+
377
578
  async function ensureProviderMonitorCapacityBackfill(input: {
378
579
  auth: OrgAuthContext;
379
580
  }) {
@@ -7,11 +7,16 @@ export type ProviderMonitorDeletionObservation = {
7
7
  /**
8
8
  * The complete customer-visible lifecycle of a monitor.
9
9
  *
10
+ * `provisioning` means the monitor was accepted and recorded, but the provider
11
+ * has not yet confirmed that it exists: it does not deliver events or bill
12
+ * until the create commits and the monitor becomes `active`.
13
+ *
10
14
  * Provider work, retries, and audit evidence intentionally live on separate
11
15
  * axes. They must never become additional values in this union.
12
16
  */
13
17
  export type ProviderMonitorCustomerState =
14
18
  | 'active'
19
+ | 'provisioning'
15
20
  | 'billing_suspended'
16
21
  | 'disabled';
17
22
 
@@ -21,6 +26,32 @@ export type ProviderMonitorCustomerState =
21
26
  */
22
27
  export type ProviderMonitorState = 'active' | 'inactive';
23
28
 
29
+ /**
30
+ * True when a deploy submitted at `submittedAt` must leave this monitor
31
+ * alone: its desired state was turned inactive, or it was deleted, after the
32
+ * deploy was submitted. That stop is newer customer (or policy) intent. A row
33
+ * without `desiredChangedAt`, or a deploy without `submittedAt`, keeps the
34
+ * earlier behavior.
35
+ */
36
+ export function providerMonitorStoppedAfter(
37
+ row: {
38
+ status?: string;
39
+ desired?: ProviderMonitorState;
40
+ desiredChangedAt?: number;
41
+ },
42
+ submittedAt: number | undefined,
43
+ ): boolean {
44
+ if (submittedAt === undefined || row.desiredChangedAt === undefined) {
45
+ return false;
46
+ }
47
+ if (row.desiredChangedAt <= submittedAt) return false;
48
+ return (
49
+ row.status === 'deleted' ||
50
+ row.status === 'deleting' ||
51
+ row.desired === 'inactive'
52
+ );
53
+ }
54
+
24
55
  export type ProviderMonitorStatusAlias = ProviderMonitorState;
25
56
 
26
57
  declare const providerMonitorResourceIdBrand: unique symbol;
@@ -127,10 +158,11 @@ export function providerMonitorCustomerStateForBillingState(
127
158
 
128
159
  /**
129
160
  * The single public monitor-state projection. A billing suspension owns the
130
- * off state. Otherwise `active` is operational proof: a committed active
131
- * lifecycle and a non-empty provider resource binding. Internal billing
132
- * bookkeeping such as an unresolved usage charge must not make a usable
133
- * provider resource look disabled.
161
+ * off state. A `pending_create` lifecycle is `provisioning`: the create was
162
+ * recorded but the provider has not confirmed the resource. Otherwise `active`
163
+ * is operational proof: a committed active lifecycle and a non-empty provider
164
+ * resource binding. Internal billing bookkeeping such as an unresolved usage
165
+ * charge must not make a usable provider resource look disabled.
134
166
  */
135
167
  export function providerMonitorCustomerState(input: {
136
168
  lifecycleStatus?: string | null;
@@ -141,6 +173,7 @@ export function providerMonitorCustomerState(input: {
141
173
  input.billingState,
142
174
  );
143
175
  if (billingState === 'billing_suspended') return billingState;
176
+ if (input.lifecycleStatus === 'pending_create') return 'provisioning';
144
177
 
145
178
  const providerResourceId = providerMonitorResourceId(
146
179
  input.providerResourceId,
@@ -151,7 +184,11 @@ export function providerMonitorCustomerState(input: {
151
184
  return 'disabled';
152
185
  }
153
186
 
154
- /** Deprecated compatibility projection for the old `status`/`active` keys. */
187
+ /**
188
+ * Deprecated compatibility projection for the old `status`/`active` keys. The
189
+ * alias stays two-valued: every non-active state, including `provisioning`,
190
+ * is `inactive`.
191
+ */
155
192
  export function providerMonitorStatusAlias(
156
193
  state: ProviderMonitorCustomerState,
157
194
  ): ProviderMonitorStatusAlias {
@@ -94,16 +94,21 @@ function managedWebhookName(input: {
94
94
  /**
95
95
  * Resolve the externally reachable origin for provider callbacks and durable
96
96
  * workers. Local Convex actions need the preview tunnel, not a loopback URL.
97
+ * A Vercel Preview shares its app URL settings with Production, so without
98
+ * an explicit origin it calls back to its own deployment, never Production.
97
99
  */
98
100
  export function resolveProviderMonitorCallbackBaseUrl(
99
101
  explicit?: string | null,
100
102
  environment: NodeJS.ProcessEnv = process.env,
101
103
  ) {
104
+ const previewDeployment =
105
+ environment.VERCEL_ENV === 'preview' ? environment.VERCEL_URL : undefined;
102
106
  const baseUrl =
103
107
  explicit ||
104
108
  environment.DEEPLINE_WORKER_CALLBACK_URL ||
105
109
  readPreviewCallbackUrlFile(environment) ||
106
110
  environment.WORKTREE_PUBLIC_APP_URL ||
111
+ previewDeployment ||
107
112
  environment.DEEPLINE_API_BASE_URL ||
108
113
  environment.NEXT_PUBLIC_APP_URL ||
109
114
  environment.APP_URL ||
@@ -1035,6 +1035,24 @@
1035
1035
  "failureAlert": "vercel_route_wrapper",
1036
1036
  "domainReportRequired": true
1037
1037
  },
1038
+ {
1039
+ "id": "vercel.managed-storage-charges",
1040
+ "name": "Charge managed storage overage",
1041
+ "scheduler": "vercel_cron",
1042
+ "cadence": "40 6 * * *",
1043
+ "timezone": "UTC",
1044
+ "source": "apps/deepline-api/vercel.json",
1045
+ "locator": "/api/v2/cron/managed-storage-charges",
1046
+ "owner": "billing",
1047
+ "criticality": "operational",
1048
+ "purpose": "Price every workspace-day of managed storage that ended two to five days ago, then charge the storage above its included GB for workspaces enrolled in the managed-storage-charges rollout, settling through the charge lifecycle.",
1049
+ "successDefinition": "Every open day in the window is priced, and every enrolled day with overage is charged or deferred after a refused charge; no day is left over.",
1050
+ "failureDefinition": "A day's charge cannot be prepared or settled, or more days are due than one run charges.",
1051
+ "startGraceMs": 300000,
1052
+ "runTimeoutMs": 600000,
1053
+ "failureAlert": "vercel_route_wrapper",
1054
+ "domainReportRequired": true
1055
+ },
1038
1056
  {
1039
1057
  "id": "convex.observe-operational-queue-health",
1040
1058
  "name": "Observe operational queue health",
@@ -0,0 +1,40 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+ var _chunkWZLGL37Ajs = require('./chunk-WZLGL37A.js');
17
+ require('./chunk-7F6KTNUP.js');
18
+ require('./chunk-U42S2GAF.js');
19
+ require('./chunk-NPBJI7RE.js');
20
+ require('./chunk-XNYIZMNQ.js');
21
+ require('./chunk-PPDBRJRW.js');
22
+ require('./chunk-2ACYJZHU.js');
23
+ require('./chunk-OG64RBAC.js');
24
+ require('./chunk-COGTRVWW.js');
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+ exports.EXIT_WORKSPACE_MISMATCH = _chunkWZLGL37Ajs.EXIT_WORKSPACE_MISMATCH; exports.authStatusLine = _chunkWZLGL37Ajs.authStatusLine; exports.clearPendingClaim = _chunkWZLGL37Ajs.clearPendingClaim; exports.clearSatisfiedPendingClaim = _chunkWZLGL37Ajs.clearSatisfiedPendingClaim; exports.handleRegister = _chunkWZLGL37Ajs.handleRegister; exports.handleStatus = _chunkWZLGL37Ajs.handleStatus; exports.handleWait = _chunkWZLGL37Ajs.handleWait; exports.httpJson = _chunkWZLGL37Ajs.httpJson; exports.readPendingAuthClaim = _chunkWZLGL37Ajs.readPendingAuthClaim; exports.readStatusBanner = _chunkWZLGL37Ajs.readStatusBanner; exports.registerAuthCommands = _chunkWZLGL37Ajs.registerAuthCommands; exports.reportSetupCompleted = _chunkWZLGL37Ajs.reportSetupCompleted; exports.resolvePendingAuthClaimForResume = _chunkWZLGL37Ajs.resolvePendingAuthClaimForResume; exports.statusBannerLine = _chunkWZLGL37Ajs.statusBannerLine;
@@ -13,13 +13,13 @@ import {
13
13
  reportSetupCompleted,
14
14
  resolvePendingAuthClaimForResume,
15
15
  statusBannerLine
16
- } from "./chunk-NFIZ5YED.mjs";
17
- import "./chunk-QWJJMQNE.mjs";
18
- import "./chunk-XSERB7H2.mjs";
16
+ } from "./chunk-ODO6ZIHB.mjs";
17
+ import "./chunk-VYO6TLWN.mjs";
18
+ import "./chunk-S5FCTT3E.mjs";
19
19
  import "./chunk-MAMVGOSC.mjs";
20
20
  import "./chunk-DLIRSHV6.mjs";
21
21
  import "./chunk-E4IXDAZI.mjs";
22
- import "./chunk-JDAXVQV7.mjs";
22
+ import "./chunk-XC3J4P5W.mjs";
23
23
  import "./chunk-WZYKRD7T.mjs";
24
24
  import "./chunk-KRD6H754.mjs";
25
25
  export {