@vibesdotdev/account 1.0.0-rc.4 → 1.0.0-rc.9

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 (61) hide show
  1. package/dist/account/account-settings.storage.descriptor.d.ts +2 -0
  2. package/dist/account/account-settings.storage.descriptor.d.ts.map +1 -1
  3. package/dist/billing/internal/quota-client.d.ts +59 -0
  4. package/dist/billing/internal/quota-client.d.ts.map +1 -1
  5. package/dist/billing/internal/quota-client.js +113 -1
  6. package/dist/billing/internal/quota-client.js.map +1 -1
  7. package/dist/billing/overage/overage-policy.config.descriptor.d.ts +114 -0
  8. package/dist/billing/overage/overage-policy.config.descriptor.d.ts.map +1 -0
  9. package/dist/billing/overage/overage-policy.config.descriptor.js +52 -0
  10. package/dist/billing/overage/overage-policy.config.descriptor.js.map +1 -0
  11. package/dist/billing/overage/overage-policy.d.ts +159 -0
  12. package/dist/billing/overage/overage-policy.d.ts.map +1 -0
  13. package/dist/billing/overage/overage-policy.js +93 -0
  14. package/dist/billing/overage/overage-policy.js.map +1 -0
  15. package/dist/billing/usage/delivery.d.ts +96 -1
  16. package/dist/billing/usage/delivery.d.ts.map +1 -1
  17. package/dist/billing/usage/delivery.js +55 -0
  18. package/dist/billing/usage/delivery.js.map +1 -1
  19. package/dist/billing/usage/record-code-session-usage.d.ts +9 -2
  20. package/dist/billing/usage/record-code-session-usage.d.ts.map +1 -1
  21. package/dist/billing/usage/record-code-session-usage.js +4 -1
  22. package/dist/billing/usage/record-code-session-usage.js.map +1 -1
  23. package/dist/billing/usage/record-platform-resource.d.ts +14 -2
  24. package/dist/billing/usage/record-platform-resource.d.ts.map +1 -1
  25. package/dist/billing/usage/record-platform-resource.js +25 -6
  26. package/dist/billing/usage/record-platform-resource.js.map +1 -1
  27. package/dist/billing/usage/record-sandbox-uptime.d.ts +16 -3
  28. package/dist/billing/usage/record-sandbox-uptime.d.ts.map +1 -1
  29. package/dist/billing/usage/record-sandbox-uptime.js +24 -5
  30. package/dist/billing/usage/record-sandbox-uptime.js.map +1 -1
  31. package/dist/cli/plugin.d.ts.map +1 -1
  32. package/dist/cli/plugin.js +2 -0
  33. package/dist/cli/plugin.js.map +1 -1
  34. package/dist/org/account-org.plugin.d.ts +4 -5
  35. package/dist/org/account-org.plugin.d.ts.map +1 -1
  36. package/dist/org/account-org.plugin.js +5 -6
  37. package/dist/org/account-org.plugin.js.map +1 -1
  38. package/dist/org/orgId.context.descriptor.d.ts +2 -3
  39. package/dist/org/orgId.context.descriptor.d.ts.map +1 -1
  40. package/dist/org/orgId.context.descriptor.js +2 -3
  41. package/dist/org/orgId.context.descriptor.js.map +1 -1
  42. package/dist/org/orgId.context.impl.d.ts +5 -6
  43. package/dist/org/orgId.context.impl.d.ts.map +1 -1
  44. package/dist/org/orgId.context.impl.js +34 -8
  45. package/dist/org/orgId.context.impl.js.map +1 -1
  46. package/dist/plugin/billing-overage.d.ts +9 -0
  47. package/dist/plugin/billing-overage.d.ts.map +1 -0
  48. package/dist/plugin/billing-overage.js +17 -0
  49. package/dist/plugin/billing-overage.js.map +1 -0
  50. package/dist/plugin/index.d.ts.map +1 -1
  51. package/dist/plugin/index.js +5 -1
  52. package/dist/plugin/index.js.map +1 -1
  53. package/dist/system/account-system.config.descriptor.d.ts +17 -4
  54. package/dist/system/account-system.config.descriptor.d.ts.map +1 -1
  55. package/dist/system/account-system.config.descriptor.js +14 -2
  56. package/dist/system/account-system.config.descriptor.js.map +1 -1
  57. package/dist/system/config.d.ts +7 -2
  58. package/dist/system/config.d.ts.map +1 -1
  59. package/dist/system/config.js +15 -1
  60. package/dist/system/config.js.map +1 -1
  61. package/package.json +93 -18
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Overage policy — what happens to running work when a billing subject's
3
+ * credits reach zero.
4
+ *
5
+ * Three behaviors:
6
+ * - `continue-invoice` — keep running and invoice the overage.
7
+ * - `pause` — pause immediately.
8
+ * - `continue-internal` — keep running, never invoice, and record the
9
+ * overage for system visibility.
10
+ *
11
+ * The declared defaults live in the `billing.overage` config manifest
12
+ * (`overage-policy.config.descriptor.ts`) and resolve through the runtime
13
+ * like any other setting; this module is the schema they parse against, never
14
+ * a second copy of the values. Account Web resolves a subject's behavior
15
+ * (`POST /api/billing/overage/resolve`): an explicit override for the user in
16
+ * the org, then the role in the org, then the org, then the class default,
17
+ * then `userDefault` for usage with no org. Callers never hard-code one.
18
+ */
19
+ import * as z from 'zod/v4';
20
+ export const OVERAGE_POLICY_MANIFEST_ID = 'billing.overage';
21
+ export const OverageBehaviorSchema = z.enum(['continue-invoice', 'pause', 'continue-internal']);
22
+ /**
23
+ * The org class a default is keyed by. `enterprise` is an org whose
24
+ * subscription tier is `accountType: enterprise`; `standard` is every other
25
+ * individual or team org; `internal` is the org a system admin marks as
26
+ * Vibes-internal.
27
+ */
28
+ export const OverageOrgClassSchema = z.enum(['enterprise', 'standard', 'internal']);
29
+ /** Who may set an org's overage behavior. */
30
+ export const OverageSetterRoleSchema = z.enum(['owner', 'admin']);
31
+ /**
32
+ * The behaviors the Vibes internal org may run under. Drew, 2026-10-29: the
33
+ * internal org "keeps moving" — it is never paused for credits, so `pause` is
34
+ * not a value its default can hold, and Account never resolves it to `pause`
35
+ * from an override either.
36
+ */
37
+ export const InternalOverageBehaviorSchema = OverageBehaviorSchema.exclude(['pause']);
38
+ /** Per-class defaults (Drew, 2026-10-29). */
39
+ export const OverageClassDefaultsSchema = z.strictObject({
40
+ enterprise: OverageBehaviorSchema.default('continue-invoice'),
41
+ standard: OverageBehaviorSchema.default('pause'),
42
+ internal: InternalOverageBehaviorSchema.default('continue-internal')
43
+ });
44
+ /**
45
+ * Whether a `standard` org may opt in to `continue-invoice`, and on what
46
+ * terms. The terms are the lane D review's (2026-10-29): a payment method on
47
+ * file and an owner or admin making the choice. `allowed` defaults to true and
48
+ * is policy, so it can be changed without code.
49
+ */
50
+ export const StandardContinueInvoicePolicySchema = z.strictObject({
51
+ allowed: z.boolean().default(true),
52
+ requiresPaymentMethod: z.boolean().default(true),
53
+ setterRoles: z.array(OverageSetterRoleSchema).min(1).default(['owner', 'admin'])
54
+ });
55
+ export const OveragePolicySchema = z.strictObject({
56
+ defaults: OverageClassDefaultsSchema.default(() => OverageClassDefaultsSchema.parse({})),
57
+ /** Usage billed to a user with no org. */
58
+ userDefault: OverageBehaviorSchema.default('pause'),
59
+ standardContinueInvoice: StandardContinueInvoicePolicySchema.default(() => StandardContinueInvoicePolicySchema.parse({}))
60
+ });
61
+ /** Where a resolved behavior came from, most specific first. */
62
+ export const OverageBehaviorSourceSchema = z.enum([
63
+ 'user-override',
64
+ 'role-override',
65
+ 'org-override',
66
+ 'class-default',
67
+ 'user-default'
68
+ ]);
69
+ /** A resolved overage behavior and where it came from. */
70
+ export const OverageResolutionSchema = z.object({
71
+ behavior: OverageBehaviorSchema,
72
+ source: OverageBehaviorSourceSchema
73
+ });
74
+ /**
75
+ * Whether an org of `orgClass` may choose `behavior`, set by `setterRole`.
76
+ * Only `continue-invoice` on a `standard` org is conditioned here; the
77
+ * owner/admin-edit rule for every other choice belongs to the override
78
+ * route's own authorization.
79
+ */
80
+ export function overageChoiceRefusal(policy, choice) {
81
+ if (choice.orgClass !== 'standard' || choice.behavior !== 'continue-invoice')
82
+ return null;
83
+ const terms = policy.standardContinueInvoice;
84
+ if (!terms.allowed)
85
+ return 'standard-continue-invoice-disallowed';
86
+ if (terms.requiresPaymentMethod && !choice.hasPaymentMethod)
87
+ return 'payment-method-required';
88
+ if (choice.setterRole === 'member' || !terms.setterRoles.includes(choice.setterRole)) {
89
+ return 'setter-role-not-permitted';
90
+ }
91
+ return null;
92
+ }
93
+ //# sourceMappingURL=overage-policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overage-policy.js","sourceRoot":"","sources":["../../../src/billing/overage/overage-policy.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,7 @@
7
7
  import type { Logger } from '@vibesdotdev/logging';
8
8
  import { type Settled, type ValueFreeFailure } from '@vibesdotdev/kernel';
9
9
  import type { JsonValue } from '@vibesdotdev/kernel/schemas/json';
10
+ import { type OverageBehavior, type OverageBehaviorSource } from '../overage/overage-policy.ts';
10
11
  /** Metadata a usage event carries to Account Web: JSON values; an undefined entry is dropped when serialized. */
11
12
  export type BillingEventMetadata = Record<string, JsonValue | undefined>;
12
13
  /** How a delivery failed: a non-2xx status, the deadline, or a thrown failure described value-free. */
@@ -20,7 +21,10 @@ export type DeliveryFailure = {
20
21
  error: ValueFreeFailure;
21
22
  };
22
23
  /** The failure a settled delivery ended with, or null when Account Web accepted it. */
23
- export declare function deliveryFailure(delivered: Settled<Response>): DeliveryFailure | null;
24
+ export declare function deliveryFailure(delivered: Settled<{
25
+ readonly ok: boolean;
26
+ readonly status: number;
27
+ }>): DeliveryFailure | null;
24
28
  /** The journal message for a failed delivery: the status, the deadline, or the failure class, never response text. */
25
29
  export declare function deliveryFailureMessage(failure: DeliveryFailure, timeoutMs: number): string;
26
30
  /**
@@ -31,4 +35,95 @@ export declare function deliveryFailureMessage(failure: DeliveryFailure, timeout
31
35
  export declare function keepAlive<Platform>(logger: Pick<Logger, 'error'>, label: string, platform: Platform, promise: Promise<void>): void;
32
36
  /** Run a caller's journal callback; a throw or rejection is logged by failure class, never raised into the emitter. */
33
37
  export declare function notifyJournal(logger: Pick<Logger, 'warn'>, label: string, callback: (() => Promise<void> | void) | undefined): Promise<void>;
38
+ /**
39
+ * What Account Web did with a delivered usage record, as
40
+ * `/api/billing/usage/record-internal` reports it in its 200 body.
41
+ *
42
+ * Delivery and deduction are separate facts. The usage row is written before
43
+ * the credit deduction, so a record that could not be paid for is still
44
+ * DELIVERED: the journal marks it delivered and the reconciler must not retry
45
+ * it (a retry would write a second usage row). The deduction outcome is what
46
+ * tells a caller the charge was not collected.
47
+ *
48
+ * - `charged` — the rated charge was deducted in full.
49
+ * - `shortfall` — the pools could not cover the charge; `charged` is what
50
+ * was deducted and `shortfallUsd` the uncollected
51
+ * cost-basis USD (rating value of the credits not paid).
52
+ * It carries the subject's overage behavior (see
53
+ * {@link UsageRecordOverage}) so a caller can enforce it.
54
+ * - `unrecorded` — Account Web accepted the request but recorded no charge
55
+ * for a reason other than balance (unknown feature, a
56
+ * failed insert).
57
+ * - `unreported` — the body did not carry the outcome (an Account Web that
58
+ * predates it, or an unreadable body). Never read as paid.
59
+ */
60
+ export type UsageRecordOutcome = {
61
+ readonly status: 'charged';
62
+ readonly charged: number;
63
+ } | ({
64
+ readonly status: 'shortfall';
65
+ readonly charged: number;
66
+ readonly shortfallUsd: number;
67
+ } & UsageRecordOverage) | {
68
+ readonly status: 'unrecorded';
69
+ readonly error: string;
70
+ } | {
71
+ readonly status: 'unreported';
72
+ };
73
+ /**
74
+ * The overage facts a shortfall carries, as record-internal reports them
75
+ * (lane D step 3): the subject's resolved overage behavior, the layer that
76
+ * decided it, and the overage record written for the shortfall.
77
+ *
78
+ * Each is null when the answering Account Web did not report it (one that
79
+ * predates the field) or reported a value this client cannot read. A null
80
+ * behavior is never read as any behavior: an enforcer acts only on an
81
+ * explicit `pause`.
82
+ */
83
+ export interface UsageRecordOverage {
84
+ readonly behavior: OverageBehavior | null;
85
+ readonly behaviorSource: OverageBehaviorSource | null;
86
+ /** The `billing_overage_records` row; null when none was written or reported. */
87
+ readonly overageRecordId: string | null;
88
+ }
89
+ /** Read the deduction outcome from a record-internal 200 body. */
90
+ export declare function usageRecordOutcome(body: JsonValue): UsageRecordOutcome;
91
+ /** A settled record-internal response: its status, and on a 2xx the outcome its body reported. */
92
+ export interface UsageRecordDelivery {
93
+ readonly ok: boolean;
94
+ readonly status: number;
95
+ readonly outcome: UsageRecordOutcome | null;
96
+ }
97
+ /**
98
+ * Read a record-internal response, body included. Call it inside the same
99
+ * lifecycle deadline as the fetch, so a stalled body is a timeout rather than
100
+ * a read that outlives the emitter's budget.
101
+ */
102
+ export declare function readUsageRecordDelivery(response: Response): Promise<UsageRecordDelivery>;
103
+ /**
104
+ * How one fire-and-forget usage emission ended: skipped before sending, not
105
+ * delivered, or delivered with the deduction outcome Account Web reported.
106
+ * Every record-internal emitter reports through this one shape, so a caller
107
+ * reads a shortfall the same way whichever emitter it used.
108
+ */
109
+ export type UsageEmissionOutcome = {
110
+ readonly delivery: 'skipped';
111
+ readonly message: string;
112
+ } | {
113
+ readonly delivery: 'failed';
114
+ readonly failure: DeliveryFailure;
115
+ } | {
116
+ readonly delivery: 'delivered';
117
+ readonly outcome: UsageRecordOutcome;
118
+ };
119
+ /** A settled record-internal call: not delivered (and why), or delivered with its deduction outcome. */
120
+ export type UsageRecordSettlement = {
121
+ readonly delivered: false;
122
+ readonly failure: DeliveryFailure;
123
+ } | {
124
+ readonly delivered: true;
125
+ readonly outcome: UsageRecordOutcome;
126
+ };
127
+ /** Classify a settled {@link readUsageRecordDelivery}; a 2xx without a readable outcome is `unreported`. */
128
+ export declare function usageRecordSettlement(settled: Settled<UsageRecordDelivery>): UsageRecordSettlement;
34
129
  //# sourceMappingURL=delivery.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"delivery.d.ts","sourceRoot":"","sources":["../../../src/billing/usage/delivery.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAuC,KAAK,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC/G,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAGlE,iHAAiH;AACjH,MAAM,MAAM,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC,CAAC;AAEzE,uGAAuG;AACvG,MAAM,MAAM,eAAe,GACxB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,GACrB;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAEhD,uFAAuF;AACvF,wBAAgB,eAAe,CAAC,SAAS,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,eAAe,GAAG,IAAI,CAIpF;AAED,sHAAsH;AACtH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAI1F;AAaD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EACjC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,GACpB,IAAI,CASN;AAED,uHAAuH;AACvH,wBAAsB,aAAa,CAClC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,SAAS,GAChD,OAAO,CAAC,IAAI,CAAC,CAQf"}
1
+ {"version":3,"file":"delivery.d.ts","sourceRoot":"","sources":["../../../src/billing/usage/delivery.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,7 @@
7
7
  import * as z from 'zod/v4';
8
8
  import { settle, settleNow, valueFreeFailure } from '@vibesdotdev/kernel';
9
9
  import { isWaitTimeout } from "./wait-timeout.js";
10
+ import { OverageBehaviorSchema, OverageBehaviorSourceSchema } from "../overage/overage-policy.js";
10
11
  /** The failure a settled delivery ended with, or null when Account Web accepted it. */
11
12
  export function deliveryFailure(delivered) {
12
13
  if (delivered.ok)
@@ -58,4 +59,58 @@ export async function notifyJournal(logger, label, callback) {
58
59
  error: valueFreeFailure(settled.cause)
59
60
  });
60
61
  }
62
+ /** The fields of the record-internal 200 body the outcome is read from. */
63
+ const recordInternalOutcomeBodySchema = z.object({
64
+ success: z.boolean(),
65
+ charged: z.number().nonnegative(),
66
+ shortfallUsd: z.number().nonnegative(),
67
+ error: z.string().optional(),
68
+ behavior: OverageBehaviorSchema.nullable().optional().catch(null),
69
+ behaviorSource: OverageBehaviorSourceSchema.nullable().optional().catch(null),
70
+ overageRecordId: z.string().min(1).nullable().optional().catch(null)
71
+ });
72
+ /** Read the deduction outcome from a record-internal 200 body. */
73
+ export function usageRecordOutcome(body) {
74
+ const parsed = recordInternalOutcomeBodySchema.safeParse(body);
75
+ if (!parsed.success)
76
+ return { status: 'unreported' };
77
+ const { success, charged, shortfallUsd, error } = parsed.data;
78
+ if (shortfallUsd > 0) {
79
+ return {
80
+ status: 'shortfall',
81
+ charged,
82
+ shortfallUsd,
83
+ behavior: parsed.data.behavior ?? null,
84
+ behaviorSource: parsed.data.behaviorSource ?? null,
85
+ overageRecordId: parsed.data.overageRecordId ?? null
86
+ };
87
+ }
88
+ if (!success)
89
+ return { status: 'unrecorded', error: error ?? 'not recorded' };
90
+ return { status: 'charged', charged };
91
+ }
92
+ const jsonBodySchema = z.json();
93
+ /**
94
+ * Read a record-internal response, body included. Call it inside the same
95
+ * lifecycle deadline as the fetch, so a stalled body is a timeout rather than
96
+ * a read that outlives the emitter's budget.
97
+ */
98
+ export async function readUsageRecordDelivery(response) {
99
+ if (!response.ok)
100
+ return { ok: false, status: response.status, outcome: null };
101
+ const body = await settle(async () => jsonBodySchema.parse(await response.json()));
102
+ return {
103
+ ok: true,
104
+ status: response.status,
105
+ outcome: body.ok ? usageRecordOutcome(body.value) : { status: 'unreported' }
106
+ };
107
+ }
108
+ /** Classify a settled {@link readUsageRecordDelivery}; a 2xx without a readable outcome is `unreported`. */
109
+ export function usageRecordSettlement(settled) {
110
+ const failure = deliveryFailure(settled);
111
+ if (failure)
112
+ return { delivered: false, failure };
113
+ const outcome = settled.ok ? settled.value.outcome : null;
114
+ return { delivered: true, outcome: outcome ?? { status: 'unreported' } };
115
+ }
61
116
  //# sourceMappingURL=delivery.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"delivery.js","sourceRoot":"","sources":["../../../src/billing/usage/delivery.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAE5B,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,gBAAgB,EAAuC,MAAM,qBAAqB,CAAC;AAE/G,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAWlD,uFAAuF;AACvF,MAAM,UAAU,eAAe,CAAC,SAA4B;IAC3D,IAAI,SAAS,CAAC,EAAE;QAAE,OAAO,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;IACxG,IAAI,aAAa,CAAC,SAAS,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IACjE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,gBAAgB,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;AACtE,CAAC;AAED,sHAAsH;AACtH,MAAM,UAAU,sBAAsB,CAAC,OAAwB,EAAE,SAAiB;IACjF,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM;QAAE,OAAO,QAAQ,OAAO,CAAC,MAAM,EAAE,CAAC;IAC/D,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS;QAAE,OAAO,WAAW,SAAS,IAAI,CAAC;IAClE,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACjG,CAAC;AAKD,MAAM,8BAA8B,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;AAEpH;;;GAGG;AACH,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAmB,CAAC,KAAK,EAAE,EAAE,CAAC,8BAA8B,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC;AAE9H;;;;GAIG;AACH,MAAM,UAAU,SAAS,CACxB,MAA6B,EAC7B,KAAa,EACb,QAAkB,EAClB,OAAsB;IAEtB,MAAM,OAAO,GAAG,sBAAsB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC3D,IAAI,CAAC,OAAO,CAAC,OAAO;QAAE,OAAO;IAC7B,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IACtE,IAAI,IAAI,CAAC,EAAE;QAAE,OAAO;IACpB,MAAM,CAAC,KAAK,CAAC,8CAA8C,EAAE;QAC5D,OAAO,EAAE,KAAK;QACd,KAAK,EAAE,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC;KACnC,CAAC,CAAC;AACJ,CAAC;AAED,uHAAuH;AACvH,MAAM,CAAC,KAAK,UAAU,aAAa,CAClC,MAA4B,EAC5B,KAAa,EACb,QAAkD;IAElD,IAAI,CAAC,QAAQ;QAAE,OAAO;IACtB,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,OAAO,CAAC,EAAE;QAAE,OAAO;IACvB,MAAM,CAAC,IAAI,CAAC,+BAA+B,EAAE;QAC5C,OAAO,EAAE,KAAK;QACd,KAAK,EAAE,gBAAgB,CAAC,OAAO,CAAC,KAAK,CAAC;KACtC,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"delivery.js","sourceRoot":"","sources":["../../../src/billing/usage/delivery.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAE5B,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,gBAAgB,EAAuC,MAAM,qBAAqB,CAAC;AAE/G,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EACN,qBAAqB,EACrB,2BAA2B,EAG3B,MAAM,8BAA8B,CAAC;AAWtC,uFAAuF;AACvF,MAAM,UAAU,eAAe,CAAC,SAAqE;IACpG,IAAI,SAAS,CAAC,EAAE;QAAE,OAAO,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;IACxG,IAAI,aAAa,CAAC,SAAS,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IACjE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,gBAAgB,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;AACtE,CAAC;AAED,sHAAsH;AACtH,MAAM,UAAU,sBAAsB,CAAC,OAAwB,EAAE,SAAiB;IACjF,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM;QAAE,OAAO,QAAQ,OAAO,CAAC,MAAM,EAAE,CAAC;IAC/D,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS;QAAE,OAAO,WAAW,SAAS,IAAI,CAAC;IAClE,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACjG,CAAC;AAKD,MAAM,8BAA8B,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;AAEpH;;;GAGG;AACH,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAmB,CAAC,KAAK,EAAE,EAAE,CAAC,8BAA8B,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC;AAE9H;;;;GAIG;AACH,MAAM,UAAU,SAAS,CACxB,MAA6B,EAC7B,KAAa,EACb,QAAkB,EAClB,OAAsB;IAEtB,MAAM,OAAO,GAAG,sBAAsB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC3D,IAAI,CAAC,OAAO,CAAC,OAAO;QAAE,OAAO;IAC7B,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IACtE,IAAI,IAAI,CAAC,EAAE;QAAE,OAAO;IACpB,MAAM,CAAC,KAAK,CAAC,8CAA8C,EAAE;QAC5D,OAAO,EAAE,KAAK;QACd,KAAK,EAAE,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC;KACnC,CAAC,CAAC;AACJ,CAAC;AAED,uHAAuH;AACvH,MAAM,CAAC,KAAK,UAAU,aAAa,CAClC,MAA4B,EAC5B,KAAa,EACb,QAAkD;IAElD,IAAI,CAAC,QAAQ;QAAE,OAAO;IACtB,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,OAAO,CAAC,EAAE;QAAE,OAAO;IACvB,MAAM,CAAC,IAAI,CAAC,+BAA+B,EAAE;QAC5C,OAAO,EAAE,KAAK;QACd,KAAK,EAAE,gBAAgB,CAAC,OAAO,CAAC,KAAK,CAAC;KACtC,CAAC,CAAC;AACJ,CAAC;AA+CD,2EAA2E;AAC3E,MAAM,+BAA+B,GAAG,CAAC,CAAC,MAAM,CAAC;IAChD,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;IACpB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE;IACjC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE;IACtC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,QAAQ,EAAE,qBAAqB,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC;IACjE,cAAc,EAAE,2BAA2B,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC;IAC7E,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC;CACpE,CAAC,CAAC;AAEH,kEAAkE;AAClE,MAAM,UAAU,kBAAkB,CAAC,IAAe;IACjD,MAAM,MAAM,GAAG,+BAA+B,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC/D,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;IACrD,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC;IAC9D,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;QACtB,OAAO;YACN,MAAM,EAAE,WAAW;YACnB,OAAO;YACP,YAAY;YACZ,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI;YACtC,cAAc,EAAE,MAAM,CAAC,IAAI,CAAC,cAAc,IAAI,IAAI;YAClD,eAAe,EAAE,MAAM,CAAC,IAAI,CAAC,eAAe,IAAI,IAAI;SACpD,CAAC;IACH,CAAC;IACD,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,KAAK,IAAI,cAAc,EAAE,CAAC;IAC9E,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC;AACvC,CAAC;AASD,MAAM,cAAc,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AAEhC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,QAAkB;IAC/D,IAAI,CAAC,QAAQ,CAAC,EAAE;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC/E,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACnF,OAAO;QACN,EAAE,EAAE,IAAI;QACR,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE;KAC5E,CAAC;AACH,CAAC;AAkBD,4GAA4G;AAC5G,MAAM,UAAU,qBAAqB,CAAC,OAAqC;IAC1E,MAAM,OAAO,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IACzC,IAAI,OAAO;QAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;IAClD,MAAM,OAAO,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1D,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE,CAAC;AAC1E,CAAC"}
@@ -26,8 +26,8 @@
26
26
  import type { RuntimeRef } from '@vibesdotdev/kernel';
27
27
  import type { CostBasis } from '../rating/schemas/cost-basis.ts';
28
28
  import type { HardwarePath } from '../rating/schemas/rated-usage.ts';
29
- import { type PlatformResourceReason } from './record-platform-resource.ts';
30
- import type { BillingEventMetadata } from './delivery.ts';
29
+ import { type PlatformResourceOutcome, type PlatformResourceReason } from './record-platform-resource.ts';
30
+ import { type BillingEventMetadata } from './delivery.ts';
31
31
  /** The metadata this emitter's input accepts: JSON values, undefined entries dropped. */
32
32
  export type { BillingEventMetadata };
33
33
  export interface RecordCodeSessionUsageInput {
@@ -80,6 +80,13 @@ export interface RecordCodeSessionUsageInput {
80
80
  message: string;
81
81
  }) => Promise<void> | void;
82
82
  };
83
+ /**
84
+ * Receives how the emission ended, deduction outcome included (see
85
+ * `record-platform-resource`). A `shortfall` carries the owner's overage
86
+ * behavior, which the code-session meter enforces. Always called once: a
87
+ * zero-compute emission sends nothing and reports `skipped`.
88
+ */
89
+ onOutcome?: (outcome: PlatformResourceOutcome) => Promise<void> | void;
83
90
  }
84
91
  /**
85
92
  * Fire-and-forget rated emission for code-session compute. Consumer / local
@@ -1 +1 @@
1
- {"version":3,"file":"record-code-session-usage.d.ts","sourceRoot":"","sources":["../../../src/billing/usage/record-code-session-usage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAGrE,OAAO,EAEN,KAAK,sBAAsB,EAC3B,MAAM,+BAA+B,CAAC;AACvC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAE1D,yFAAyF;AACzF,YAAY,EAAE,oBAAoB,EAAE,CAAC;AAQrC,MAAM,WAAW,2BAA2B;IAC3C,8EAA8E;IAC9E,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACzC,6DAA6D;IAC7D,oBAAoB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAChD;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB,2DAA2D;IAC3D,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB;;;;OAIG;IACH,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC;IACxB,6FAA6F;IAC7F,MAAM,EAAE,sBAAsB,CAAC;IAC/B,mDAAmD;IACnD,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,4EAA4E;IAC5E,OAAO,CAAC,EAAE;QACT,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;QACvC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE;YAClB,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;YAC9C,OAAO,EAAE,MAAM,CAAC;SAChB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;KAC3B,CAAC;CACF;AAYD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,2BAA2B,GAAG,IAAI,CAuCpG"}
1
+ {"version":3,"file":"record-code-session-usage.d.ts","sourceRoot":"","sources":["../../../src/billing/usage/record-code-session-usage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAGrE,OAAO,EAEN,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAiB,KAAK,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAEzE,yFAAyF;AACzF,YAAY,EAAE,oBAAoB,EAAE,CAAC;AAQrC,MAAM,WAAW,2BAA2B;IAC3C,8EAA8E;IAC9E,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACzC,6DAA6D;IAC7D,oBAAoB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAChD;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB,2DAA2D;IAC3D,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB;;;;OAIG;IACH,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC;IACxB,6FAA6F;IAC7F,MAAM,EAAE,sBAAsB,CAAC;IAC/B,mDAAmD;IACnD,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,4EAA4E;IAC5E,OAAO,CAAC,EAAE;QACT,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;QACvC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE;YAClB,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;YAC9C,OAAO,EAAE,MAAM,CAAC;SAChB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;KAC3B,CAAC;IACF;;;;;OAKG;IACH,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,uBAAuB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACvE;AAYD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,2BAA2B,GAAG,IAAI,CA2CpG"}
@@ -27,6 +27,7 @@ import { getLogger } from '@vibesdotdev/logging';
27
27
  import { FEATURE_SLUGS } from "../schemas/core/feature-slugs.js";
28
28
  import { codeSessionComputeCostBasis } from "./build-session-cost-basis.js";
29
29
  import { recordPlatformResource } from "./record-platform-resource.js";
30
+ import { notifyJournal } from "./delivery.js";
30
31
  function log(runtime) {
31
32
  return getLogger('account', runtime).child({ context: 'record-code-session-usage' });
32
33
  }
@@ -52,6 +53,7 @@ export function recordCodeSessionUsage(runtime, input) {
52
53
  sessionId: input.sessionId,
53
54
  reason: input.reason
54
55
  });
56
+ void notifyJournal(log(runtime), 'recordCodeSessionUsage', () => input.onOutcome?.({ delivery: 'skipped', message: 'zero-compute' }));
55
57
  return;
56
58
  }
57
59
  const hardware = input.hardware ?? 'cloud';
@@ -79,7 +81,8 @@ export function recordCodeSessionUsage(runtime, input) {
79
81
  computeSeconds,
80
82
  ...input.metadata
81
83
  },
82
- journal: input.journal
84
+ journal: input.journal,
85
+ onOutcome: input.onOutcome
83
86
  });
84
87
  }
85
88
  //# sourceMappingURL=record-code-session-usage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"record-code-session-usage.js","sourceRoot":"","sources":["../../../src/billing/usage/record-code-session-usage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAIjD,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AACjE,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAC5E,OAAO,EACN,sBAAsB,EAEtB,MAAM,+BAA+B,CAAC;AAMvC,SAAS,GAAG,CAAC,OAAmB;IAC/B,OAAO,SAAS,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,2BAA2B,EAAE,CAAC,CAAC;AACtF,CAAC;AAED,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAsD9B,SAAS,qBAAqB,CAAC,KAAkC;IAChE,IAAI,KAAK,CAAC,cAAc,KAAK,SAAS,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC;QACjF,OAAO,KAAK,CAAC,cAAc,CAAC;IAC7B,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QACnE,OAAO,KAAK,CAAC,OAAO,GAAG,kBAAkB,CAAC;IAC3C,CAAC;IACD,OAAO,CAAC,CAAC;AACV,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAmB,EAAE,KAAkC;IAC7F,MAAM,cAAc,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;IACpD,IAAI,cAAc,IAAI,CAAC,EAAE,CAAC;QACzB,GAAG,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,gDAAgD,EAAE;YACpE,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,MAAM,EAAE,KAAK,CAAC,MAAM;SACpB,CAAC,CAAC;QACH,OAAO;IACR,CAAC;IAED,MAAM,QAAQ,GAAiB,KAAK,CAAC,QAAQ,IAAI,OAAO,CAAC;IACzD,sEAAsE;IACtE,yEAAyE;IACzE,yEAAyE;IACzE,+DAA+D;IAC/D,MAAM,SAAS,GACd,KAAK,CAAC,SAAS,IAAI,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,2BAA2B,EAAE,CAAC,CAAC;IAE1F,sBAAsB,CAAC,OAAO,EAAE;QAC/B,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,oBAAoB,EAAE,KAAK,CAAC,oBAAoB;QAChD,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,WAAW,EAAE,aAAa,CAAC,wBAAwB,CAAC;QACpD,OAAO,EAAE,oBAAoB;QAC7B,UAAU,EAAE,KAAK,CAAC,SAAS;QAC3B,aAAa,EAAE,EAAE,cAAc,EAAE,cAAc,EAAE;QACjD,SAAS;QACT,QAAQ;QACR,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,QAAQ,EAAE;YACT,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,YAAY,EAAE,KAAK,CAAC,YAAY,IAAI,IAAI;YACxC,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,IAAI;YAC5B,cAAc;YACd,GAAG,KAAK,CAAC,QAAQ;SACjB;QACD,OAAO,EAAE,KAAK,CAAC,OAAO;KACtB,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"record-code-session-usage.js","sourceRoot":"","sources":["../../../src/billing/usage/record-code-session-usage.ts"],"names":[],"mappings":"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"}
@@ -19,13 +19,18 @@
19
19
  * - Returns `void`; failures log structured context.
20
20
  * - Honors the same journal callback contract as
21
21
  * `record-sandbox-uptime` so app-local audit tables stay consistent.
22
+ * - A delivered record that could not be paid for is NOT success: the
23
+ * caller's `onOutcome` receives `shortfall` with the uncollected
24
+ * cost-basis USD, exactly as `record-sandbox-uptime` reports it.
22
25
  */
23
26
  import { type RuntimeRef } from '@vibesdotdev/kernel';
24
- import { type BillingEventMetadata } from './delivery.ts';
27
+ import { type BillingEventMetadata, type UsageEmissionOutcome, type UsageRecordOutcome } from './delivery.ts';
25
28
  import type { CostBasis } from '../rating/schemas/cost-basis.ts';
26
29
  import type { HardwarePath, MeasuredUnits } from '../rating/schemas/rated-usage.ts';
27
30
  /** The metadata this emitter's input accepts: JSON values, undefined entries dropped. */
28
- export type { BillingEventMetadata };
31
+ export type { BillingEventMetadata, UsageRecordOutcome };
32
+ /** How one platform-resource emission ended; the shared record-internal outcome. */
33
+ export type PlatformResourceOutcome = UsageEmissionOutcome;
29
34
  export type PlatformResourceReason = 'sweep' | 'tick' | 'completion' | 'manual' | 'reconcile';
30
35
  export interface RecordPlatformResourceInput {
31
36
  /** Origin of the account app. Omit to skip metering. */
@@ -80,6 +85,13 @@ export interface RecordPlatformResourceInput {
80
85
  message: string;
81
86
  }) => Promise<void> | void;
82
87
  };
88
+ /**
89
+ * Receives how the emission ended. The journal tracks DELIVERY (a
90
+ * delivered record must not be re-sent, or the usage row is written
91
+ * twice); this tracks whether the charge was collected. A `shortfall`
92
+ * outcome is delivered and still unpaid.
93
+ */
94
+ onOutcome?: (outcome: PlatformResourceOutcome) => Promise<void> | void;
83
95
  }
84
96
  /**
85
97
  * Fire-and-forget rated emission. Skipped silently when the inputs
@@ -1 +1 @@
1
- {"version":3,"file":"record-platform-resource.d.ts","sourceRoot":"","sources":["../../../src/billing/usage/record-platform-resource.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,EAAU,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAIN,KAAK,oBAAoB,EACzB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,KAAK,EACX,YAAY,EACZ,aAAa,EACb,MAAM,kCAAkC,CAAC;AAE1C,yFAAyF;AACzF,YAAY,EAAE,oBAAoB,EAAE,CAAC;AAQrC,MAAM,MAAM,sBAAsB,GAC/B,OAAO,GACP,MAAM,GACN,YAAY,GACZ,QAAQ,GACR,WAAW,CAAC;AAEf,MAAM,WAAW,2BAA2B;IAC3C,wDAAwD;IACxD,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACzC,6DAA6D;IAC7D,oBAAoB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAChD;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B;;;;OAIG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,UAAU,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,aAAa,EAAE,aAAa,CAAC;IAC7B;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,+BAA+B;IAC/B,MAAM,EAAE,sBAAsB,CAAC;IAC/B,mDAAmD;IACnD,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,yEAAyE;IACzE,OAAO,CAAC,EAAE;QACT,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;QACvC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE;YAClB,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;YAC9C,OAAO,EAAE,MAAM,CAAC;SAChB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;KAC3B,CAAC;CACF;AAUD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,2BAA2B,GAAG,IAAI,CAgGpG"}
1
+ {"version":3,"file":"record-platform-resource.d.ts","sourceRoot":"","sources":["../../../src/billing/usage/record-platform-resource.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAGH,OAAO,EAAU,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAKN,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,KAAK,EACX,YAAY,EACZ,aAAa,EACb,MAAM,kCAAkC,CAAC;AAE1C,yFAAyF;AACzF,YAAY,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,CAAC;AAEzD,oFAAoF;AACpF,MAAM,MAAM,uBAAuB,GAAG,oBAAoB,CAAC;AAQ3D,MAAM,MAAM,sBAAsB,GAC/B,OAAO,GACP,MAAM,GACN,YAAY,GACZ,QAAQ,GACR,WAAW,CAAC;AAEf,MAAM,WAAW,2BAA2B;IAC3C,wDAAwD;IACxD,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACzC,6DAA6D;IAC7D,oBAAoB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAChD;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B;;;;OAIG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,UAAU,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,aAAa,EAAE,aAAa,CAAC;IAC7B;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC;IACxB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,+BAA+B;IAC/B,MAAM,EAAE,sBAAsB,CAAC;IAC/B,mDAAmD;IACnD,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,yEAAyE;IACzE,OAAO,CAAC,EAAE;QACT,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;QACvC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE;YAClB,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;YAC9C,OAAO,EAAE,MAAM,CAAC;SAChB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;KAC3B,CAAC;IACF;;;;;OAKG;IACH,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,uBAAuB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACvE;AAUD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,2BAA2B,GAAG,IAAI,CA6HpG"}
@@ -19,10 +19,13 @@
19
19
  * - Returns `void`; failures log structured context.
20
20
  * - Honors the same journal callback contract as
21
21
  * `record-sandbox-uptime` so app-local audit tables stay consistent.
22
+ * - A delivered record that could not be paid for is NOT success: the
23
+ * caller's `onOutcome` receives `shortfall` with the uncollected
24
+ * cost-basis USD, exactly as `record-sandbox-uptime` reports it.
22
25
  */
23
26
  import { getLogger } from '@vibesdotdev/logging';
24
27
  import { settle } from '@vibesdotdev/kernel';
25
- import { deliveryFailure, deliveryFailureMessage, notifyJournal } from "./delivery.js";
28
+ import { deliveryFailureMessage, notifyJournal, readUsageRecordDelivery, usageRecordSettlement } from "./delivery.js";
26
29
  function log(runtime) {
27
30
  return getLogger('account', runtime).child({ context: 'record-platform-resource' });
28
31
  }
@@ -42,8 +45,12 @@ function totalMeasured(units) {
42
45
  */
43
46
  export function recordPlatformResource(runtime, input) {
44
47
  const total = totalMeasured(input.measuredUnits);
45
- if (total <= 0)
48
+ if (total <= 0) {
49
+ // Nothing to bill, but still an outcome: a caller waiting on
50
+ // `onOutcome` (the code-session meter) must always hear back.
51
+ void notifyJournal(log(runtime), 'recordPlatformResource', () => input.onOutcome?.({ delivery: 'skipped', message: 'zero-quantity' }));
46
52
  return;
53
+ }
47
54
  if (!input.billingUserId && !input.organizationId) {
48
55
  const message = 'neither-billing-user-nor-organization-set';
49
56
  log(runtime).debug('recordPlatformResource: skipping (' + message + ')', {
@@ -52,6 +59,7 @@ export function recordPlatformResource(runtime, input) {
52
59
  reason: input.reason
53
60
  });
54
61
  void notifyJournal(log(runtime), 'recordPlatformResource', () => input.journal?.onFailure?.({ reason: 'skip', message }));
62
+ void notifyJournal(log(runtime), 'recordPlatformResource', () => input.onOutcome?.({ delivery: 'skipped', message }));
55
63
  return;
56
64
  }
57
65
  if (!input.accountOrigin) {
@@ -62,6 +70,7 @@ export function recordPlatformResource(runtime, input) {
62
70
  reason: input.reason
63
71
  });
64
72
  void notifyJournal(log(runtime), 'recordPlatformResource', () => input.journal?.onFailure?.({ reason: 'skip', message }));
73
+ void notifyJournal(log(runtime), 'recordPlatformResource', () => input.onOutcome?.({ delivery: 'skipped', message }));
65
74
  return;
66
75
  }
67
76
  const accountOrigin = input.accountOrigin;
@@ -73,6 +82,7 @@ export function recordPlatformResource(runtime, input) {
73
82
  reason: input.reason
74
83
  });
75
84
  void notifyJournal(log(runtime), 'recordPlatformResource', () => input.journal?.onFailure?.({ reason: 'skip', message }));
85
+ void notifyJournal(log(runtime), 'recordPlatformResource', () => input.onOutcome?.({ delivery: 'skipped', message }));
76
86
  return;
77
87
  }
78
88
  const effectiveHardware = input.hardware ?? 'cloud';
@@ -102,13 +112,21 @@ export function recordPlatformResource(runtime, input) {
102
112
  }
103
113
  }),
104
114
  signal
105
- }), { timeoutMs: USAGE_RECORD_TIMEOUT_MS, reason: 'account platform resource usage record' })).then(async (delivered) => {
106
- const failure = deliveryFailure(delivered);
107
- if (!failure) {
115
+ }).then(readUsageRecordDelivery), { timeoutMs: USAGE_RECORD_TIMEOUT_MS, reason: 'account platform resource usage record' })).then(async (settled) => {
116
+ const settlement = usageRecordSettlement(settled);
117
+ const context = { featureSlug: input.featureSlug, resourceId: input.resourceId };
118
+ if (settlement.delivered) {
119
+ // Delivered, so the journal row is done even when the charge was
120
+ // not collected: re-sending would write the usage row twice.
108
121
  await notifyJournal(log(runtime), 'recordPlatformResource', input.journal?.onSuccess);
122
+ const { outcome } = settlement;
123
+ if (outcome.status !== 'charged') {
124
+ log(runtime).warn('recordPlatformResource: usage delivered but not charged in full', { ...context, outcome });
125
+ }
126
+ await notifyJournal(log(runtime), 'recordPlatformResource', () => input.onOutcome?.({ delivery: 'delivered', outcome }));
109
127
  return;
110
128
  }
111
- const context = { featureSlug: input.featureSlug, resourceId: input.resourceId };
129
+ const { failure } = settlement;
112
130
  if (failure.reason === 'http') {
113
131
  log(runtime).warn('recordPlatformResource: non-2xx from account', { ...context, status: failure.status });
114
132
  }
@@ -120,6 +138,7 @@ export function recordPlatformResource(runtime, input) {
120
138
  }
121
139
  const message = deliveryFailureMessage(failure, USAGE_RECORD_TIMEOUT_MS);
122
140
  await notifyJournal(log(runtime), 'recordPlatformResource', () => input.journal?.onFailure?.({ reason: failure.reason, message }));
141
+ await notifyJournal(log(runtime), 'recordPlatformResource', () => input.onOutcome?.({ delivery: 'failed', failure }));
123
142
  });
124
143
  }
125
144
  //# sourceMappingURL=record-platform-resource.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"record-platform-resource.js","sourceRoot":"","sources":["../../../src/billing/usage/record-platform-resource.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"record-platform-resource.js","sourceRoot":"","sources":["../../../src/billing/usage/record-platform-resource.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAmB,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EACN,sBAAsB,EACtB,aAAa,EACb,uBAAuB,EACvB,qBAAqB,EAIrB,MAAM,eAAe,CAAC;AAavB,SAAS,GAAG,CAAC,OAAmB;IAC/B,OAAO,SAAS,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,0BAA0B,EAAE,CAAC,CAAC;AACrF,CAAC;AAED,MAAM,uBAAuB,GAAG,GAAG,CAAC;AAuEpC,SAAS,aAAa,CAAC,KAAoB;IAC1C,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1C,IAAI,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC;YAAE,KAAK,IAAI,KAAK,CAAC;IAChF,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAmB,EAAE,KAAkC;IAC7F,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IACjD,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QAChB,6DAA6D;QAC7D,8DAA8D;QAC9D,KAAK,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,wBAAwB,EAAE,GAAG,EAAE,CAC/D,KAAK,CAAC,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC,CACpE,CAAC;QACF,OAAO;IACR,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,aAAa,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC;QACnD,MAAM,OAAO,GAAG,2CAA2C,CAAC;QAC5D,GAAG,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,oCAAoC,GAAG,OAAO,GAAG,GAAG,EAAE;YACxE,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,MAAM,EAAE,KAAK,CAAC,MAAM;SACpB,CAAC,CAAC;QACH,KAAK,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,wBAAwB,EAAE,GAAG,EAAE,CAC/D,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CACvD,CAAC;QACF,KAAK,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,wBAAwB,EAAE,GAAG,EAAE,CAC/D,KAAK,CAAC,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CACnD,CAAC;QACF,OAAO;IACR,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC;QAC1B,MAAM,OAAO,GAAG,8BAA8B,CAAC;QAC/C,GAAG,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,oCAAoC,GAAG,OAAO,GAAG,GAAG,EAAE;YACxE,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,MAAM,EAAE,KAAK,CAAC,MAAM;SACpB,CAAC,CAAC;QACH,KAAK,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,wBAAwB,EAAE,GAAG,EAAE,CAC/D,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CACvD,CAAC;QACF,KAAK,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,wBAAwB,EAAE,GAAG,EAAE,CAC/D,KAAK,CAAC,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CACnD,CAAC;QACF,OAAO;IACR,CAAC;IACD,MAAM,aAAa,GAAG,KAAK,CAAC,aAAa,CAAC;IAC1C,IAAI,CAAC,KAAK,CAAC,oBAAoB,EAAE,CAAC;QACjC,MAAM,OAAO,GAAG,qCAAqC,CAAC;QACtD,GAAG,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,oCAAoC,GAAG,OAAO,GAAG,GAAG,EAAE;YACxE,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,MAAM,EAAE,KAAK,CAAC,MAAM;SACpB,CAAC,CAAC;QACH,KAAK,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,wBAAwB,EAAE,GAAG,EAAE,CAC/D,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CACvD,CAAC;QACF,KAAK,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,wBAAwB,EAAE,GAAG,EAAE,CAC/D,KAAK,CAAC,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CACnD,CAAC;QACF,OAAO;IACR,CAAC;IAED,MAAM,iBAAiB,GAAiB,KAAK,CAAC,QAAQ,IAAI,OAAO,CAAC;IAElE,MAAM,cAAc,GAAG;QACtB,cAAc,EAAE,kBAAkB;QAClC,MAAM,EAAE,kBAAkB;QAC1B,aAAa,EAAE,UAAU,KAAK,CAAC,oBAAoB,EAAE;KACpB,CAAC;IACnC,MAAM,OAAO,GAAG,KAAK,CAAC,aAAa;QAClC,CAAC,CAAC,EAAE,GAAG,cAAc,EAAE,iBAAiB,EAAE,KAAK,CAAC,aAAa,EAAE;QAC/D,CAAC,CAAC,cAAc,CAAC;IAElB,KAAK,MAAM,CAAC,GAAG,EAAE,CAChB,OAAO,CAAC,SAAS,CAAC,IAAI,CACrB,CAAC,MAAM,EAAE,EAAE,CACV,KAAK,CAAC,GAAG,aAAa,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,oCAAoC,EAAE;QAC9E,MAAM,EAAE,MAAM;QACd,OAAO;QACP,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACpB,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,aAAa,EAAE,KAAK,CAAC,aAAa;YAClC,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,QAAQ,EAAE,iBAAiB;YAC3B,cAAc,EAAE,KAAK,CAAC,cAAc,IAAI,IAAI;YAC5C,QAAQ,EAAE;gBACT,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,QAAQ,EAAE,iBAAiB;gBAC3B,GAAG,KAAK,CAAC,QAAQ;aACjB;SACD,CAAC;QACF,MAAM;KACN,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,EACjC,EAAE,SAAS,EAAE,uBAAuB,EAAE,MAAM,EAAE,wCAAwC,EAAE,CACxF,CACD,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QACxB,MAAM,UAAU,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;QAClD,MAAM,OAAO,GAAG,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC;QACjF,IAAI,UAAU,CAAC,SAAS,EAAE,CAAC;YAC1B,iEAAiE;YACjE,6DAA6D;YAC7D,MAAM,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,wBAAwB,EAAE,KAAK,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YACtF,MAAM,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC;YAC/B,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBAClC,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,iEAAiE,EAAE,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;YAC/G,CAAC;YACD,MAAM,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,wBAAwB,EAAE,GAAG,EAAE,CAChE,KAAK,CAAC,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CACrD,CAAC;YACF,OAAO;QACR,CAAC;QACD,MAAM,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC;QAC/B,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC/B,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,8CAA8C,EAAE,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QAC3G,CAAC;aAAM,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACzC,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,mCAAmC,EAAE,EAAE,GAAG,OAAO,EAAE,SAAS,EAAE,uBAAuB,EAAE,CAAC,CAAC;QAC5G,CAAC;aAAM,CAAC;YACP,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,sCAAsC,EAAE,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QACjG,CAAC;QACD,MAAM,OAAO,GAAG,sBAAsB,CAAC,OAAO,EAAE,uBAAuB,CAAC,CAAC;QACzE,MAAM,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,wBAAwB,EAAE,GAAG,EAAE,CAChE,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAC/D,CAAC;QACF,MAAM,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,wBAAwB,EAAE,GAAG,EAAE,CAChE,KAAK,CAAC,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAClD,CAAC;IACH,CAAC,CAAC,CAAC;AACJ,CAAC"}
@@ -18,14 +18,20 @@
18
18
  * Design constraints (same as record-generation-usage.ts)
19
19
  * - MUST NOT fail the heartbeat path. Always returns void; swallows
20
20
  * errors with structured log.
21
- * - MUST be time-bounded. 500ms hard cap via AbortController.
21
+ * - MUST be time-bounded. 500ms hard cap via AbortController, body
22
+ * read included.
23
+ * - A delivered record that could not be paid for is NOT success: the
24
+ * caller's `onOutcome` receives `shortfall` with the uncollected
25
+ * cost-basis USD.
22
26
  */
23
27
  import { type RuntimeRef } from '@vibesdotdev/kernel';
24
- import { type BillingEventMetadata } from './delivery.ts';
28
+ import { type BillingEventMetadata, type UsageEmissionOutcome, type UsageRecordOutcome } from './delivery.ts';
25
29
  import type { CostBasis } from '../rating/schemas/cost-basis.ts';
26
30
  import type { HardwarePath } from '../rating/schemas/rated-usage.ts';
27
31
  /** The metadata this emitter's input accepts: JSON values, undefined entries dropped. */
28
- export type { BillingEventMetadata };
32
+ export type { BillingEventMetadata, UsageRecordOutcome };
33
+ /** How one uptime emission ended; the shared record-internal outcome. */
34
+ export type SandboxUptimeOutcome = UsageEmissionOutcome;
29
35
  export interface RecordSandboxUptimeInput {
30
36
  /** Origin of the account app. Omit to skip metering (dev without account). */
31
37
  accountOrigin: string | null | undefined;
@@ -88,6 +94,13 @@ export interface RecordSandboxUptimeInput {
88
94
  message: string;
89
95
  }) => Promise<void> | void;
90
96
  };
97
+ /**
98
+ * Receives how the emission ended. The journal tracks DELIVERY (a
99
+ * delivered record must not be re-sent, or the usage row is written
100
+ * twice); this tracks whether the charge was collected. A `shortfall`
101
+ * outcome is delivered and still unpaid.
102
+ */
103
+ onOutcome?: (outcome: SandboxUptimeOutcome) => Promise<void> | void;
91
104
  }
92
105
  export declare function recordSandboxUptime(runtime: RuntimeRef, input: RecordSandboxUptimeInput): void;
93
106
  //# sourceMappingURL=record-sandbox-uptime.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"record-sandbox-uptime.d.ts","sourceRoot":"","sources":["../../../src/billing/usage/record-sandbox-uptime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,EAAU,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAIN,KAAK,oBAAoB,EACzB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAErE,yFAAyF;AACzF,YAAY,EAAE,oBAAoB,EAAE,CAAC;AASrC,MAAM,WAAW,wBAAwB;IACxC,8EAA8E;IAC9E,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACzC;;;;OAIG;IACH,oBAAoB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAChD;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,kEAAkE;IAClE,OAAO,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,+FAA+F;IAC/F,MAAM,EAAE,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,CAAC;IACxD;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC;IACxB,mDAAmD;IACnD,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,EAAE;QACT,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;QACvC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE;YAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;KAC/G,CAAC;CACF;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,wBAAwB,GAAG,IAAI,CAwG9F"}
1
+ {"version":3,"file":"record-sandbox-uptime.d.ts","sourceRoot":"","sources":["../../../src/billing/usage/record-sandbox-uptime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,OAAO,EAAU,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAKN,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAErE,yFAAyF;AACzF,YAAY,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,CAAC;AAEzD,yEAAyE;AACzE,MAAM,MAAM,oBAAoB,GAAG,oBAAoB,CAAC;AASxD,MAAM,WAAW,wBAAwB;IACxC,8EAA8E;IAC9E,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACzC;;;;OAIG;IACH,oBAAoB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAChD;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,kEAAkE;IAClE,OAAO,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,+FAA+F;IAC/F,MAAM,EAAE,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,CAAC;IACxD;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC;IACxB,mDAAmD;IACnD,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,EAAE;QACT,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;QACvC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE;YAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;KAC/G,CAAC;IACF;;;;;OAKG;IACH,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACpE;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,wBAAwB,GAAG,IAAI,CAiI9F"}