@usagekit/core 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/billing.d.ts +97 -0
- package/dist/billing.js +1 -0
- package/dist/contracts.d.ts +10 -1
- package/dist/index.d.ts +1 -0
- package/dist/policy.js +1 -1
- package/dist/wire.js +14 -0
- package/package.json +1 -1
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { BudgetAlertCrossed, Cost, FundingSource, Money, Operation, Receipt, Scope, ValidationFailure } from "./contracts.js";
|
|
2
|
+
import type { BillingLine } from "./providers.js";
|
|
3
|
+
/** Trusted historical attribution for calls the application did not observe. */
|
|
4
|
+
export type ImportAttribution = {
|
|
5
|
+
fundingSource: FundingSource;
|
|
6
|
+
costOwner: string;
|
|
7
|
+
creditAccountRef?: string;
|
|
8
|
+
customerPriceVersion?: string;
|
|
9
|
+
providerPriceVersion?: string;
|
|
10
|
+
platformPools?: readonly string[];
|
|
11
|
+
};
|
|
12
|
+
/** A complete export for one connection and half-open window. Never grants dispatch. */
|
|
13
|
+
export type BillingImportInput = {
|
|
14
|
+
scope: Scope;
|
|
15
|
+
provider: string;
|
|
16
|
+
/** Lower-case SHA-256 of the original file, computed before the atomic command. */
|
|
17
|
+
fileHash: string;
|
|
18
|
+
window: {
|
|
19
|
+
from: string;
|
|
20
|
+
to: string;
|
|
21
|
+
};
|
|
22
|
+
/** null for the first import; the current import id for a revision. Prevents lost updates. */
|
|
23
|
+
expectedPreviousImportId: string | null;
|
|
24
|
+
attribution: ImportAttribution;
|
|
25
|
+
lines: readonly BillingLine[];
|
|
26
|
+
};
|
|
27
|
+
/** Exact comparison. Unknown ledger cost remains unknown; signed differences are never prorated. */
|
|
28
|
+
export type ReconciliationEntry = {
|
|
29
|
+
id: string;
|
|
30
|
+
importId: string;
|
|
31
|
+
scope: Scope;
|
|
32
|
+
provider: string;
|
|
33
|
+
/** Present for operation-specific aggregate evidence. */
|
|
34
|
+
operation?: string;
|
|
35
|
+
window: {
|
|
36
|
+
from: string;
|
|
37
|
+
to: string;
|
|
38
|
+
};
|
|
39
|
+
kind: "aggregate" | "import_total";
|
|
40
|
+
ledgerTotal: Cost;
|
|
41
|
+
evidenceTotal: Money;
|
|
42
|
+
/** evidenceTotal - ledgerTotal, or null when any observed cost is unknown. */
|
|
43
|
+
differenceUnits: bigint | null;
|
|
44
|
+
unknownOperations: bigint;
|
|
45
|
+
evidenceRef: string;
|
|
46
|
+
};
|
|
47
|
+
export type BillingImportRecord = {
|
|
48
|
+
id: string;
|
|
49
|
+
scope: Scope;
|
|
50
|
+
provider: string;
|
|
51
|
+
fileHash: string;
|
|
52
|
+
window: {
|
|
53
|
+
from: string;
|
|
54
|
+
to: string;
|
|
55
|
+
};
|
|
56
|
+
recordedAt: string;
|
|
57
|
+
supersedes?: string;
|
|
58
|
+
/** Projected from the import family pointer; earlier evidence remains available. */
|
|
59
|
+
supersededBy?: string;
|
|
60
|
+
matchedOperationIds: readonly string[];
|
|
61
|
+
unobservedOperationIds: readonly string[];
|
|
62
|
+
reconciliations: readonly ReconciliationEntry[];
|
|
63
|
+
alerts: readonly BudgetAlertCrossed[];
|
|
64
|
+
};
|
|
65
|
+
export type BillingImportResult = ValidationFailure | {
|
|
66
|
+
outcome: "imported";
|
|
67
|
+
replayed: boolean;
|
|
68
|
+
record: BillingImportRecord;
|
|
69
|
+
} | {
|
|
70
|
+
outcome: "rejected";
|
|
71
|
+
reason: "previous_import_conflict" | "payload_conflict" | "ambiguous_request" | "active_operation" | "operation_state" | "evidence_conflict";
|
|
72
|
+
latestImportId: string | null;
|
|
73
|
+
line?: number;
|
|
74
|
+
};
|
|
75
|
+
export type BillingImportsQuery = {
|
|
76
|
+
scope: {
|
|
77
|
+
namespace: string;
|
|
78
|
+
principal: string;
|
|
79
|
+
};
|
|
80
|
+
connection: string;
|
|
81
|
+
from: string;
|
|
82
|
+
to: string;
|
|
83
|
+
/** Include superseded import evidence; defaults to false. */
|
|
84
|
+
history?: boolean;
|
|
85
|
+
limit?: number;
|
|
86
|
+
};
|
|
87
|
+
export type BillingImportsPage = {
|
|
88
|
+
records: readonly BillingImportRecord[];
|
|
89
|
+
asOf: string;
|
|
90
|
+
truncated: boolean;
|
|
91
|
+
};
|
|
92
|
+
/** Atomic adapter changes prepared against its transaction's operation snapshot. */
|
|
93
|
+
export type BillingOperationChange = {
|
|
94
|
+
before: Operation | null;
|
|
95
|
+
after: Operation;
|
|
96
|
+
receipt: Receipt;
|
|
97
|
+
};
|
package/dist/billing.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/contracts.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { BillingImportInput, BillingImportResult, BillingImportsQuery, BillingImportsPage } from "./billing.js";
|
|
1
2
|
export type ValidationFailure = {
|
|
2
3
|
outcome: "invalid";
|
|
3
4
|
field: string;
|
|
@@ -46,7 +47,7 @@ export type Scope = {
|
|
|
46
47
|
};
|
|
47
48
|
export type FundingSource = "byok" | "platform";
|
|
48
49
|
export type Surface = "app" | "programmatic";
|
|
49
|
-
export type Source = "app" | "worker" | "api" | "sdk" | "cli" | "mcp" | "proxy";
|
|
50
|
+
export type Source = "app" | "worker" | "api" | "sdk" | "cli" | "mcp" | "proxy" | "import";
|
|
50
51
|
/** Timestamps are UTC ISO strings. Resolved reservation epochs remain immutable. */
|
|
51
52
|
export type BudgetWindow = {
|
|
52
53
|
kind: "calendar_month";
|
|
@@ -163,6 +164,8 @@ export type Cost = {
|
|
|
163
164
|
*/
|
|
164
165
|
export type Receipt = {
|
|
165
166
|
id: string;
|
|
167
|
+
/** Existing receipts without this field are dispatch evidence. */
|
|
168
|
+
source?: "dispatch" | "probe" | "import";
|
|
166
169
|
supersedes?: string;
|
|
167
170
|
measurements: readonly Measurement[];
|
|
168
171
|
cost: Cost;
|
|
@@ -514,6 +517,8 @@ export type AccessContext = {
|
|
|
514
517
|
readablePools: readonly string[] | "*";
|
|
515
518
|
canReadBillingDetail: boolean;
|
|
516
519
|
canManageBudgets: boolean;
|
|
520
|
+
/** Explicit billing write permission. Read access or budget management does not imply it. */
|
|
521
|
+
canImportBilling?: boolean;
|
|
517
522
|
};
|
|
518
523
|
/**
|
|
519
524
|
* groupBy: "principal" is allowed only for group or namespace scope.
|
|
@@ -631,6 +636,10 @@ export type ExpireReservationsResult = ValidationFailure | {
|
|
|
631
636
|
* Admission sweeps at most one default batch. Maintenance owns the remaining expired backlog.
|
|
632
637
|
*/
|
|
633
638
|
export interface Meter {
|
|
639
|
+
importBilling(access: AccessContext, input: BillingImportInput): Promise<BillingImportResult | {
|
|
640
|
+
outcome: "forbidden";
|
|
641
|
+
}>;
|
|
642
|
+
billingImports(access: AccessContext, query: BillingImportsQuery): Promise<ReadResult<BillingImportsPage>>;
|
|
634
643
|
expireReservations(input: ExpireReservationsInput): Promise<ExpireReservationsResult>;
|
|
635
644
|
reserve(input: MeterReserveInput): Promise<ReserveResult>;
|
|
636
645
|
countRequest(input: CountRequestInput): Promise<CountRequestResult>;
|
package/dist/index.d.ts
CHANGED
|
@@ -10,3 +10,4 @@ export type { ExpireReservationsInput, ExpireReservationsResult } from "./contra
|
|
|
10
10
|
export { decodeMeterJson } from "./wire.js";
|
|
11
11
|
export type { ProviderId, OperationId, ProviderAuth, BillingUnit, ProviderPlan, PriceRow, RequestMatch, ProviderOperation, BalanceProbe, PriceListSource, BillingExport, ProviderDescriptor, BalanceSnapshot, BillingLine, DescriptorProblem, PricingCatalog, ConnectionPolicy, TrackingPolicy, MeasuredPrice, } from "./providers.js";
|
|
12
12
|
export { validateDescriptor } from "./providers.js";
|
|
13
|
+
export type { ImportAttribution, BillingImportInput, ReconciliationEntry, BillingImportRecord, BillingImportResult, BillingImportsQuery, BillingImportsPage, BillingOperationChange, } from "./billing.js";
|
package/dist/policy.js
CHANGED
|
@@ -19,7 +19,7 @@ export function normalizeTags(tags) {
|
|
|
19
19
|
}
|
|
20
20
|
const surfaceSources = Object.freeze({
|
|
21
21
|
app: Object.freeze(["app", "worker"]),
|
|
22
|
-
programmatic: Object.freeze(["api", "sdk", "cli", "mcp", "proxy"]),
|
|
22
|
+
programmatic: Object.freeze(["api", "sdk", "cli", "mcp", "proxy", "import"]),
|
|
23
23
|
});
|
|
24
24
|
/** Sources a surface budget covers. Every Source belongs to exactly one Surface. */
|
|
25
25
|
export const sourcesOf = (surface) => surfaceSources[surface];
|
package/dist/wire.js
CHANGED
|
@@ -29,6 +29,20 @@ export function decodeMeterJson(text) {
|
|
|
29
29
|
["passthrough", "unpriced", "cached", "rate_limited"].includes(String(v.state)) &&
|
|
30
30
|
decimal(v.count))
|
|
31
31
|
return { ...v, count: BigInt(v.count) };
|
|
32
|
+
if (typeof v.id === "string" &&
|
|
33
|
+
typeof v.importId === "string" &&
|
|
34
|
+
["aggregate", "import_total"].includes(String(v.kind)) &&
|
|
35
|
+
v.scope &&
|
|
36
|
+
v.window &&
|
|
37
|
+
v.ledgerTotal &&
|
|
38
|
+
v.evidenceTotal &&
|
|
39
|
+
decimal(v.unknownOperations) &&
|
|
40
|
+
(v.differenceUnits === null || decimal(v.differenceUnits)))
|
|
41
|
+
return {
|
|
42
|
+
...v,
|
|
43
|
+
unknownOperations: BigInt(v.unknownOperations),
|
|
44
|
+
differenceUnits: v.differenceUnits === null ? null : BigInt(v.differenceUnits),
|
|
45
|
+
};
|
|
32
46
|
return value;
|
|
33
47
|
});
|
|
34
48
|
}
|