@contractspec/lib.metering 3.7.20 → 3.7.22

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.
@@ -48,4 +48,4 @@ await aggregateUsage({
48
48
  - Keep metric keys stable; store quantities as decimals for currency/units.
49
49
  - Use idempotency keys for external ingestion; avoid PII in metric metadata.
50
50
  - Scope by org/user for multi-tenant isolation; emit audit + analytics events on changes.
51
- `}];qt(Vt);import{defineEntity as C,defineEntityEnum as J,field as b,index as K}from"@contractspec/lib.schema";var u=J({name:"AggregationType",values:["COUNT","SUM","AVG","MAX","MIN","LAST"],schema:"lssm_metering",description:"How to aggregate metric values."}),c=J({name:"ResetPeriod",values:["NEVER","HOURLY","DAILY","WEEKLY","MONTHLY","YEARLY"],schema:"lssm_metering",description:"When to reset metric counters."}),p=J({name:"PeriodType",values:["HOURLY","DAILY","WEEKLY","MONTHLY","YEARLY"],schema:"lssm_metering",description:"Time period for aggregation."}),y=J({name:"ThresholdAction",values:["NONE","ALERT","WARN","BLOCK","DOWNGRADE"],schema:"lssm_metering",description:"Action to take when threshold is exceeded."}),Ct=C({name:"MetricDefinition",description:"Definition of a usage metric.",schema:"lssm_metering",map:"metric_definition",fields:{id:b.id({description:"Unique identifier"}),key:b.string({isUnique:!0,description:"Metric key (e.g., api_calls, storage_gb)"}),name:b.string({description:"Human-readable name"}),description:b.string({isOptional:!0,description:"Metric description"}),unit:b.string({description:"Unit of measurement (calls, bytes, etc.)"}),aggregationType:b.enum("AggregationType",{default:"SUM",description:"How to aggregate values"}),resetPeriod:b.enum("ResetPeriod",{default:"MONTHLY",description:"When to reset counters"}),precision:b.int({default:2,description:"Decimal precision"}),orgId:b.string({isOptional:!0,description:"Organization scope (null = global metric)"}),category:b.string({isOptional:!0,description:"Category for grouping"}),displayOrder:b.int({default:0,description:"Order for display"}),metadata:b.json({isOptional:!0,description:"Additional metadata"}),isActive:b.boolean({default:!0,description:"Whether metric is active"}),createdAt:b.createdAt(),updatedAt:b.updatedAt(),usageRecords:b.hasMany("UsageRecord"),usageSummaries:b.hasMany("UsageSummary"),thresholds:b.hasMany("UsageThreshold")},indexes:[K.on(["orgId","key"]),K.on(["category"]),K.on(["isActive"])],enums:[u,c]}),it=C({name:"UsageRecord",description:"A single usage event.",schema:"lssm_metering",map:"usage_record",fields:{id:b.id({description:"Unique identifier"}),metricKey:b.string({description:"Metric being recorded"}),metricId:b.string({isOptional:!0,description:"Metric ID (for FK)"}),subjectType:b.string({description:"Subject type (org, user, project)"}),subjectId:b.string({description:"Subject identifier"}),quantity:b.decimal({description:"Usage quantity"}),source:b.string({isOptional:!0,description:"Source of usage (endpoint, feature, etc.)"}),resourceId:b.string({isOptional:!0,description:"Related resource ID"}),resourceType:b.string({isOptional:!0,description:"Related resource type"}),metadata:b.json({isOptional:!0,description:"Additional context"}),idempotencyKey:b.string({isOptional:!0,description:"Idempotency key for deduplication"}),timestamp:b.dateTime({description:"When usage occurred"}),createdAt:b.createdAt(),aggregated:b.boolean({default:!1,description:"Whether included in summary"}),aggregatedAt:b.dateTime({isOptional:!0,description:"When aggregated"})},indexes:[K.on(["metricKey","subjectType","subjectId","timestamp"]),K.on(["subjectType","subjectId","timestamp"]),K.on(["timestamp"]),K.on(["aggregated","timestamp"]),K.unique(["idempotencyKey"],{name:"usage_record_idempotency"})]}),zt=C({name:"UsageSummary",description:"Pre-aggregated usage summary.",schema:"lssm_metering",map:"usage_summary",fields:{id:b.id({description:"Unique identifier"}),metricKey:b.string({description:"Metric key"}),metricId:b.string({isOptional:!0,description:"Metric ID (for FK)"}),subjectType:b.string({description:"Subject type"}),subjectId:b.string({description:"Subject identifier"}),periodType:b.enum("PeriodType",{description:"Period type"}),periodStart:b.dateTime({description:"Period start time"}),periodEnd:b.dateTime({description:"Period end time"}),totalQuantity:b.decimal({description:"Total/aggregated quantity"}),recordCount:b.int({default:0,description:"Number of records aggregated"}),minQuantity:b.decimal({isOptional:!0,description:"Minimum value"}),maxQuantity:b.decimal({isOptional:!0,description:"Maximum value"}),avgQuantity:b.decimal({isOptional:!0,description:"Average value"}),metadata:b.json({isOptional:!0,description:"Additional metadata"}),createdAt:b.createdAt(),updatedAt:b.updatedAt()},indexes:[K.unique(["metricKey","subjectType","subjectId","periodType","periodStart"],{name:"usage_summary_unique"}),K.on(["subjectType","subjectId","periodType","periodStart"]),K.on(["metricKey","periodType","periodStart"])],enums:[p]}),Bt=C({name:"UsageThreshold",description:"Usage threshold configuration.",schema:"lssm_metering",map:"usage_threshold",fields:{id:b.id({description:"Unique identifier"}),metricKey:b.string({description:"Metric to monitor"}),metricId:b.string({isOptional:!0,description:"Metric ID (for FK)"}),subjectType:b.string({isOptional:!0,description:"Subject type"}),subjectId:b.string({isOptional:!0,description:"Subject identifier"}),name:b.string({description:"Threshold name"}),threshold:b.decimal({description:"Threshold value"}),warnThreshold:b.decimal({isOptional:!0,description:"Warning threshold (e.g., 80%)"}),periodType:b.enum("PeriodType",{default:"MONTHLY",description:"Period to evaluate"}),action:b.enum("ThresholdAction",{default:"ALERT",description:"Action when exceeded"}),notifyEmails:b.json({isOptional:!0,description:"Email addresses to notify"}),notifyWebhook:b.string({isOptional:!0,description:"Webhook URL to call"}),currentValue:b.decimal({default:0,description:"Current usage value"}),lastCheckedAt:b.dateTime({isOptional:!0,description:"Last threshold check"}),lastExceededAt:b.dateTime({isOptional:!0,description:"Last time threshold was exceeded"}),isActive:b.boolean({default:!0,description:"Whether threshold is active"}),metadata:b.json({isOptional:!0,description:"Additional metadata"}),createdAt:b.createdAt(),updatedAt:b.updatedAt()},indexes:[K.on(["metricKey"]),K.on(["subjectType","subjectId"]),K.on(["isActive","metricKey"])],enums:[y]}),Jt=C({name:"UsageAlert",description:"Alert generated when threshold is exceeded.",schema:"lssm_metering",map:"usage_alert",fields:{id:b.id({description:"Unique identifier"}),thresholdId:b.foreignKey({description:"Threshold that triggered alert"}),metricKey:b.string({description:"Metric key"}),subjectType:b.string({isOptional:!0,description:"Subject type"}),subjectId:b.string({isOptional:!0,description:"Subject identifier"}),alertType:b.string({description:"Alert type (warn, exceed, etc.)"}),threshold:b.decimal({description:"Threshold value"}),actualValue:b.decimal({description:"Actual usage value"}),percentageUsed:b.decimal({description:"Percentage of threshold used"}),status:b.string({default:'"pending"',description:"Alert status (pending, acknowledged, resolved)"}),acknowledgedBy:b.string({isOptional:!0,description:"User who acknowledged"}),acknowledgedAt:b.dateTime({isOptional:!0,description:"When acknowledged"}),resolvedAt:b.dateTime({isOptional:!0,description:"When resolved"}),notificationsSent:b.json({isOptional:!0,description:"Notifications sent"}),triggeredAt:b.dateTime({description:"When alert was triggered"}),createdAt:b.createdAt(),thresholdRelation:b.belongsTo("UsageThreshold",["thresholdId"],["id"],{onDelete:"Cascade"})},indexes:[K.on(["thresholdId","status"]),K.on(["metricKey","triggeredAt"]),K.on(["status","triggeredAt"])]}),Xt=[Ct,it,zt,Bt,Jt],_s={moduleId:"@contractspec/lib.metering",entities:Xt,enums:[u,c,p,y]};import{defineEvent as w}from"@contractspec/lib.contracts-spec";import{defineSchemaModel as H,ScalarTypeEnum as j}from"@contractspec/lib.schema";var Yt=H({name:"MetricDefinedEventPayload",description:"Payload when a metric is defined",fields:{metricId:{type:j.String_unsecure(),isOptional:!1},key:{type:j.String_unsecure(),isOptional:!1},name:{type:j.String_unsecure(),isOptional:!1},unit:{type:j.String_unsecure(),isOptional:!1},aggregationType:{type:j.String_unsecure(),isOptional:!1},orgId:{type:j.String_unsecure(),isOptional:!0},createdBy:{type:j.String_unsecure(),isOptional:!0},createdAt:{type:j.DateTime(),isOptional:!1}}}),Zt=H({name:"MetricUpdatedEventPayload",description:"Payload when a metric is updated",fields:{metricId:{type:j.String_unsecure(),isOptional:!1},key:{type:j.String_unsecure(),isOptional:!1},changes:{type:j.JSON(),isOptional:!1},updatedBy:{type:j.String_unsecure(),isOptional:!0},updatedAt:{type:j.DateTime(),isOptional:!1}}}),vt=H({name:"UsageRecordedEventPayload",description:"Payload when usage is recorded",fields:{recordId:{type:j.String_unsecure(),isOptional:!1},metricKey:{type:j.String_unsecure(),isOptional:!1},subjectType:{type:j.String_unsecure(),isOptional:!1},subjectId:{type:j.String_unsecure(),isOptional:!1},quantity:{type:j.Float_unsecure(),isOptional:!1},source:{type:j.String_unsecure(),isOptional:!0},timestamp:{type:j.DateTime(),isOptional:!1}}}),Gt=H({name:"UsageBatchRecordedEventPayload",description:"Payload when a batch of usage is recorded",fields:{recordCount:{type:j.Int_unsecure(),isOptional:!1},metricKeys:{type:j.JSON(),isOptional:!1},totalQuantity:{type:j.Float_unsecure(),isOptional:!1},timestamp:{type:j.DateTime(),isOptional:!1}}}),xt=H({name:"UsageAggregatedEventPayload",description:"Payload when usage is aggregated",fields:{summaryId:{type:j.String_unsecure(),isOptional:!1},metricKey:{type:j.String_unsecure(),isOptional:!1},subjectType:{type:j.String_unsecure(),isOptional:!1},subjectId:{type:j.String_unsecure(),isOptional:!1},periodType:{type:j.String_unsecure(),isOptional:!1},periodStart:{type:j.DateTime(),isOptional:!1},periodEnd:{type:j.DateTime(),isOptional:!1},totalQuantity:{type:j.Float_unsecure(),isOptional:!1},recordCount:{type:j.Int_unsecure(),isOptional:!1},aggregatedAt:{type:j.DateTime(),isOptional:!1}}}),Ot=H({name:"ThresholdCreatedEventPayload",description:"Payload when a threshold is created",fields:{thresholdId:{type:j.String_unsecure(),isOptional:!1},metricKey:{type:j.String_unsecure(),isOptional:!1},subjectType:{type:j.String_unsecure(),isOptional:!0},subjectId:{type:j.String_unsecure(),isOptional:!0},threshold:{type:j.Float_unsecure(),isOptional:!1},action:{type:j.String_unsecure(),isOptional:!1},createdAt:{type:j.DateTime(),isOptional:!1}}}),Nt=H({name:"ThresholdExceededEventPayload",description:"Payload when a threshold is exceeded",fields:{alertId:{type:j.String_unsecure(),isOptional:!1},thresholdId:{type:j.String_unsecure(),isOptional:!1},metricKey:{type:j.String_unsecure(),isOptional:!1},subjectType:{type:j.String_unsecure(),isOptional:!0},subjectId:{type:j.String_unsecure(),isOptional:!0},threshold:{type:j.Float_unsecure(),isOptional:!1},actualValue:{type:j.Float_unsecure(),isOptional:!1},percentageUsed:{type:j.Float_unsecure(),isOptional:!1},action:{type:j.String_unsecure(),isOptional:!1},triggeredAt:{type:j.DateTime(),isOptional:!1}}}),Wt=H({name:"ThresholdApproachingEventPayload",description:"Payload when usage is approaching a threshold",fields:{thresholdId:{type:j.String_unsecure(),isOptional:!1},metricKey:{type:j.String_unsecure(),isOptional:!1},subjectType:{type:j.String_unsecure(),isOptional:!0},subjectId:{type:j.String_unsecure(),isOptional:!0},threshold:{type:j.Float_unsecure(),isOptional:!1},currentValue:{type:j.Float_unsecure(),isOptional:!1},percentageUsed:{type:j.Float_unsecure(),isOptional:!1},triggeredAt:{type:j.DateTime(),isOptional:!1}}}),Mt=w({meta:{key:"metric.defined",version:"1.0.0",description:"A metric has been defined.",stability:"stable",owners:["@platform.metering"],tags:["metering","metric"]},payload:Yt}),ht=w({meta:{key:"metric.updated",version:"1.0.0",description:"A metric has been updated.",stability:"stable",owners:["@platform.metering"],tags:["metering","metric"]},payload:Zt}),nt=w({meta:{key:"usage.recorded",version:"1.0.0",description:"Usage has been recorded.",stability:"stable",owners:["@platform.metering"],tags:["metering","usage"]},payload:vt}),ft=w({meta:{key:"usage.batch_recorded",version:"1.0.0",description:"A batch of usage has been recorded.",stability:"stable",owners:["@platform.metering"],tags:["metering","usage"]},payload:Gt}),ut=w({meta:{key:"usage.aggregated",version:"1.0.0",description:"Usage has been aggregated into a summary.",stability:"stable",owners:["@platform.metering"],tags:["metering","usage"]},payload:xt}),ct=w({meta:{key:"threshold.created",version:"1.0.0",description:"A usage threshold has been created.",stability:"stable",owners:["@platform.metering"],tags:["metering","threshold"]},payload:Ot}),pt=w({meta:{key:"threshold.exceeded",version:"1.0.0",description:"Usage has exceeded a threshold.",stability:"stable",owners:["@platform.metering"],tags:["metering","threshold"]},payload:Nt}),yt=w({meta:{key:"threshold.approaching",version:"1.0.0",description:"Usage is approaching a threshold.",stability:"stable",owners:["@platform.metering"],tags:["metering","threshold"]},payload:Wt}),et=H({name:"ModelSelectionEventPayload",description:"Payload when an AI model is selected via ranking",fields:{modelId:{type:j.String_unsecure(),isOptional:!1},providerKey:{type:j.String_unsecure(),isOptional:!1},dimension:{type:j.String_unsecure(),isOptional:!0},score:{type:j.Float_unsecure(),isOptional:!1},reason:{type:j.String_unsecure(),isOptional:!1},alternativesCount:{type:j.Int_unsecure(),isOptional:!1},costEstimateInput:{type:j.Float_unsecure(),isOptional:!0},costEstimateOutput:{type:j.Float_unsecure(),isOptional:!0},selectionDurationMs:{type:j.Float_unsecure(),isOptional:!0},timestamp:{type:j.DateTime(),isOptional:!1}}}),dt=w({meta:{key:"model.selected",version:"1.0.0",description:"An AI model has been selected via ranking-driven selection.",stability:"experimental",owners:["@platform.metering"],tags:["metering","ai","model-selection"]},payload:et}),Us={MetricDefinedEvent:Mt,MetricUpdatedEvent:ht,UsageRecordedEvent:nt,UsageBatchRecordedEvent:ft,UsageAggregatedEvent:ut,ThresholdCreatedEvent:ct,ThresholdExceededEvent:pt,ThresholdApproachingEvent:yt,ModelSelectionEvent:dt};import{defineFeature as Tt}from"@contractspec/lib.contracts-spec";var Cs=Tt({meta:{key:"metrics",version:"1.0.0",title:"Usage Metering",description:"Usage metering, metric definitions, and threshold alerting",domain:"platform",owners:["@platform.metering"],tags:["metering","usage","billing","thresholds"],stability:"stable"},operations:[{key:"metric.define",version:"1.0.0"},{key:"metric.update",version:"1.0.0"},{key:"metric.delete",version:"1.0.0"},{key:"metric.get",version:"1.0.0"},{key:"metric.list",version:"1.0.0"},{key:"usage.record",version:"1.0.0"},{key:"usage.recordBatch",version:"1.0.0"},{key:"usage.get",version:"1.0.0"},{key:"usage.getSummary",version:"1.0.0"},{key:"threshold.create",version:"1.0.0"},{key:"threshold.update",version:"1.0.0"},{key:"threshold.delete",version:"1.0.0"},{key:"threshold.list",version:"1.0.0"}],events:[{key:"metric.defined",version:"1.0.0"},{key:"metric.updated",version:"1.0.0"},{key:"usage.recorded",version:"1.0.0"},{key:"usage.batch_recorded",version:"1.0.0"},{key:"usage.aggregated",version:"1.0.0"},{key:"threshold.created",version:"1.0.0"},{key:"threshold.exceeded",version:"1.0.0"},{key:"threshold.approaching",version:"1.0.0"},{key:"model.selected",version:"1.0.0"}],presentations:[],opToPresentation:[],presentationsTargets:[],capabilities:{provides:[{key:"metering",version:"1.0.0"},{key:"thresholds",version:"1.0.0"}],requires:[]}});export{_s as meteringSchemaContribution,Xt as meteringEntities,Z as getPeriodStart,N as getPeriodEnd,e as formatPeriodKey,x as UsageThresholdModel,Bt as UsageThresholdEntity,jt as UsageSummaryModel,zt as UsageSummaryEntity,nt as UsageRecordedEvent,h as UsageRecordModel,it as UsageRecordEntity,ft as UsageBatchRecordedEvent,Jt as UsageAlertEntity,T as UsageAggregator,ut as UsageAggregatedEvent,Qs as UpdateThresholdContract,ss as UpdateMetricContract,pt as ThresholdExceededEvent,ct as ThresholdCreatedEvent,yt as ThresholdApproachingEvent,y as ThresholdActionEnum,c as ResetPeriodEnum,Is as RecordUsageContract,rs as RecordBatchUsageContract,bt as PosthogMeteringReporter,m as PosthogMeteringReader,p as PeriodTypeEnum,dt as ModelSelectionEvent,ht as MetricUpdatedEvent,B as MetricDefinitionModel,Ct as MetricDefinitionEntity,Mt as MetricDefinedEvent,Cs as MeteringFeature,Us as MeteringEvents,Ks as ListThresholdsContract,js as ListMetricsContract,S as InMemoryUsageStorage,As as GetUsageSummaryContract,os as GetUsageContract,bs as GetMetricContract,ks as DeleteThresholdContract,gs as DeleteMetricContract,ts as DefineMetricContract,Rs as CreateThresholdContract,u as AggregationTypeEnum};
51
+ `}];qt(Vt);import{defineEntity as C,defineEntityEnum as J,field as b,index as K}from"@contractspec/lib.schema";var u=J({name:"AggregationType",values:["COUNT","SUM","AVG","MAX","MIN","LAST"],schema:"lssm_metering",description:"How to aggregate metric values."}),c=J({name:"ResetPeriod",values:["NEVER","HOURLY","DAILY","WEEKLY","MONTHLY","YEARLY"],schema:"lssm_metering",description:"When to reset metric counters."}),p=J({name:"PeriodType",values:["HOURLY","DAILY","WEEKLY","MONTHLY","YEARLY"],schema:"lssm_metering",description:"Time period for aggregation."}),y=J({name:"ThresholdAction",values:["NONE","ALERT","WARN","BLOCK","DOWNGRADE"],schema:"lssm_metering",description:"Action to take when threshold is exceeded."}),Ct=C({name:"MetricDefinition",description:"Definition of a usage metric.",schema:"lssm_metering",map:"metric_definition",fields:{id:b.id({description:"Unique identifier"}),key:b.string({isUnique:!0,description:"Metric key (e.g., api_calls, storage_gb)"}),name:b.string({description:"Human-readable name"}),description:b.string({isOptional:!0,description:"Metric description"}),unit:b.string({description:"Unit of measurement (calls, bytes, etc.)"}),aggregationType:b.enum("AggregationType",{default:"SUM",description:"How to aggregate values"}),resetPeriod:b.enum("ResetPeriod",{default:"MONTHLY",description:"When to reset counters"}),precision:b.int({default:2,description:"Decimal precision"}),orgId:b.string({isOptional:!0,description:"Organization scope (null = global metric)"}),category:b.string({isOptional:!0,description:"Category for grouping"}),displayOrder:b.int({default:0,description:"Order for display"}),metadata:b.json({isOptional:!0,description:"Additional metadata"}),isActive:b.boolean({default:!0,description:"Whether metric is active"}),createdAt:b.createdAt(),updatedAt:b.updatedAt(),usageRecords:b.hasMany("UsageRecord"),usageSummaries:b.hasMany("UsageSummary"),thresholds:b.hasMany("UsageThreshold")},indexes:[K.on(["orgId","key"]),K.on(["category"]),K.on(["isActive"])],enums:[u,c]}),it=C({name:"UsageRecord",description:"A single usage event.",schema:"lssm_metering",map:"usage_record",fields:{id:b.id({description:"Unique identifier"}),metricKey:b.string({description:"Metric being recorded"}),metricId:b.string({isOptional:!0,description:"Metric ID (for FK)"}),subjectType:b.string({description:"Subject type (org, user, project)"}),subjectId:b.string({description:"Subject identifier"}),quantity:b.decimal({description:"Usage quantity"}),source:b.string({isOptional:!0,description:"Source of usage (endpoint, feature, etc.)"}),resourceId:b.string({isOptional:!0,description:"Related resource ID"}),resourceType:b.string({isOptional:!0,description:"Related resource type"}),metadata:b.json({isOptional:!0,description:"Additional context"}),idempotencyKey:b.string({isOptional:!0,description:"Idempotency key for deduplication"}),timestamp:b.dateTime({description:"When usage occurred"}),createdAt:b.createdAt(),aggregated:b.boolean({default:!1,description:"Whether included in summary"}),aggregatedAt:b.dateTime({isOptional:!0,description:"When aggregated"})},indexes:[K.on(["metricKey","subjectType","subjectId","timestamp"]),K.on(["subjectType","subjectId","timestamp"]),K.on(["timestamp"]),K.on(["aggregated","timestamp"]),K.unique(["idempotencyKey"],{name:"usage_record_idempotency"})]}),zt=C({name:"UsageSummary",description:"Pre-aggregated usage summary.",schema:"lssm_metering",map:"usage_summary",fields:{id:b.id({description:"Unique identifier"}),metricKey:b.string({description:"Metric key"}),metricId:b.string({isOptional:!0,description:"Metric ID (for FK)"}),subjectType:b.string({description:"Subject type"}),subjectId:b.string({description:"Subject identifier"}),periodType:b.enum("PeriodType",{description:"Period type"}),periodStart:b.dateTime({description:"Period start time"}),periodEnd:b.dateTime({description:"Period end time"}),totalQuantity:b.decimal({description:"Total/aggregated quantity"}),recordCount:b.int({default:0,description:"Number of records aggregated"}),minQuantity:b.decimal({isOptional:!0,description:"Minimum value"}),maxQuantity:b.decimal({isOptional:!0,description:"Maximum value"}),avgQuantity:b.decimal({isOptional:!0,description:"Average value"}),metadata:b.json({isOptional:!0,description:"Additional metadata"}),createdAt:b.createdAt(),updatedAt:b.updatedAt()},indexes:[K.unique(["metricKey","subjectType","subjectId","periodType","periodStart"],{name:"usage_summary_unique"}),K.on(["subjectType","subjectId","periodType","periodStart"]),K.on(["metricKey","periodType","periodStart"])],enums:[p]}),Bt=C({name:"UsageThreshold",description:"Usage threshold configuration.",schema:"lssm_metering",map:"usage_threshold",fields:{id:b.id({description:"Unique identifier"}),metricKey:b.string({description:"Metric to monitor"}),metricId:b.string({isOptional:!0,description:"Metric ID (for FK)"}),subjectType:b.string({isOptional:!0,description:"Subject type"}),subjectId:b.string({isOptional:!0,description:"Subject identifier"}),name:b.string({description:"Threshold name"}),threshold:b.decimal({description:"Threshold value"}),warnThreshold:b.decimal({isOptional:!0,description:"Warning threshold (e.g., 80%)"}),periodType:b.enum("PeriodType",{default:"MONTHLY",description:"Period to evaluate"}),action:b.enum("ThresholdAction",{default:"ALERT",description:"Action when exceeded"}),notifyEmails:b.json({isOptional:!0,description:"Email addresses to notify"}),notifyWebhook:b.string({isOptional:!0,description:"Webhook URL to call"}),currentValue:b.decimal({default:0,description:"Current usage value"}),lastCheckedAt:b.dateTime({isOptional:!0,description:"Last threshold check"}),lastExceededAt:b.dateTime({isOptional:!0,description:"Last time threshold was exceeded"}),isActive:b.boolean({default:!0,description:"Whether threshold is active"}),metadata:b.json({isOptional:!0,description:"Additional metadata"}),createdAt:b.createdAt(),updatedAt:b.updatedAt()},indexes:[K.on(["metricKey"]),K.on(["subjectType","subjectId"]),K.on(["isActive","metricKey"])],enums:[y]}),Jt=C({name:"UsageAlert",description:"Alert generated when threshold is exceeded.",schema:"lssm_metering",map:"usage_alert",fields:{id:b.id({description:"Unique identifier"}),thresholdId:b.foreignKey({description:"Threshold that triggered alert"}),metricKey:b.string({description:"Metric key"}),subjectType:b.string({isOptional:!0,description:"Subject type"}),subjectId:b.string({isOptional:!0,description:"Subject identifier"}),alertType:b.string({description:"Alert type (warn, exceed, etc.)"}),threshold:b.decimal({description:"Threshold value"}),actualValue:b.decimal({description:"Actual usage value"}),percentageUsed:b.decimal({description:"Percentage of threshold used"}),status:b.string({default:'"pending"',description:"Alert status (pending, acknowledged, resolved)"}),acknowledgedBy:b.string({isOptional:!0,description:"User who acknowledged"}),acknowledgedAt:b.dateTime({isOptional:!0,description:"When acknowledged"}),resolvedAt:b.dateTime({isOptional:!0,description:"When resolved"}),notificationsSent:b.json({isOptional:!0,description:"Notifications sent"}),triggeredAt:b.dateTime({description:"When alert was triggered"}),createdAt:b.createdAt(),thresholdRelation:b.belongsTo("UsageThreshold",["thresholdId"],["id"],{onDelete:"Cascade"})},indexes:[K.on(["thresholdId","status"]),K.on(["metricKey","triggeredAt"]),K.on(["status","triggeredAt"])]}),Xt=[Ct,it,zt,Bt,Jt],_s={moduleId:"@contractspec/lib.metering",entities:Xt,enums:[u,c,p,y]};import{defineEvent as w}from"@contractspec/lib.contracts-spec";import{defineSchemaModel as H,ScalarTypeEnum as j}from"@contractspec/lib.schema";var Yt=H({name:"MetricDefinedEventPayload",description:"Payload when a metric is defined",fields:{metricId:{type:j.String_unsecure(),isOptional:!1},key:{type:j.String_unsecure(),isOptional:!1},name:{type:j.String_unsecure(),isOptional:!1},unit:{type:j.String_unsecure(),isOptional:!1},aggregationType:{type:j.String_unsecure(),isOptional:!1},orgId:{type:j.String_unsecure(),isOptional:!0},createdBy:{type:j.String_unsecure(),isOptional:!0},createdAt:{type:j.DateTime(),isOptional:!1}}}),Zt=H({name:"MetricUpdatedEventPayload",description:"Payload when a metric is updated",fields:{metricId:{type:j.String_unsecure(),isOptional:!1},key:{type:j.String_unsecure(),isOptional:!1},changes:{type:j.JSON(),isOptional:!1},updatedBy:{type:j.String_unsecure(),isOptional:!0},updatedAt:{type:j.DateTime(),isOptional:!1}}}),vt=H({name:"UsageRecordedEventPayload",description:"Payload when usage is recorded",fields:{recordId:{type:j.String_unsecure(),isOptional:!1},metricKey:{type:j.String_unsecure(),isOptional:!1},subjectType:{type:j.String_unsecure(),isOptional:!1},subjectId:{type:j.String_unsecure(),isOptional:!1},quantity:{type:j.Float_unsecure(),isOptional:!1},source:{type:j.String_unsecure(),isOptional:!0},timestamp:{type:j.DateTime(),isOptional:!1}}}),Gt=H({name:"UsageBatchRecordedEventPayload",description:"Payload when a batch of usage is recorded",fields:{recordCount:{type:j.Int_unsecure(),isOptional:!1},metricKeys:{type:j.JSON(),isOptional:!1},totalQuantity:{type:j.Float_unsecure(),isOptional:!1},timestamp:{type:j.DateTime(),isOptional:!1}}}),xt=H({name:"UsageAggregatedEventPayload",description:"Payload when usage is aggregated",fields:{summaryId:{type:j.String_unsecure(),isOptional:!1},metricKey:{type:j.String_unsecure(),isOptional:!1},subjectType:{type:j.String_unsecure(),isOptional:!1},subjectId:{type:j.String_unsecure(),isOptional:!1},periodType:{type:j.String_unsecure(),isOptional:!1},periodStart:{type:j.DateTime(),isOptional:!1},periodEnd:{type:j.DateTime(),isOptional:!1},totalQuantity:{type:j.Float_unsecure(),isOptional:!1},recordCount:{type:j.Int_unsecure(),isOptional:!1},aggregatedAt:{type:j.DateTime(),isOptional:!1}}}),Ot=H({name:"ThresholdCreatedEventPayload",description:"Payload when a threshold is created",fields:{thresholdId:{type:j.String_unsecure(),isOptional:!1},metricKey:{type:j.String_unsecure(),isOptional:!1},subjectType:{type:j.String_unsecure(),isOptional:!0},subjectId:{type:j.String_unsecure(),isOptional:!0},threshold:{type:j.Float_unsecure(),isOptional:!1},action:{type:j.String_unsecure(),isOptional:!1},createdAt:{type:j.DateTime(),isOptional:!1}}}),Nt=H({name:"ThresholdExceededEventPayload",description:"Payload when a threshold is exceeded",fields:{alertId:{type:j.String_unsecure(),isOptional:!1},thresholdId:{type:j.String_unsecure(),isOptional:!1},metricKey:{type:j.String_unsecure(),isOptional:!1},subjectType:{type:j.String_unsecure(),isOptional:!0},subjectId:{type:j.String_unsecure(),isOptional:!0},threshold:{type:j.Float_unsecure(),isOptional:!1},actualValue:{type:j.Float_unsecure(),isOptional:!1},percentageUsed:{type:j.Float_unsecure(),isOptional:!1},action:{type:j.String_unsecure(),isOptional:!1},triggeredAt:{type:j.DateTime(),isOptional:!1}}}),Wt=H({name:"ThresholdApproachingEventPayload",description:"Payload when usage is approaching a threshold",fields:{thresholdId:{type:j.String_unsecure(),isOptional:!1},metricKey:{type:j.String_unsecure(),isOptional:!1},subjectType:{type:j.String_unsecure(),isOptional:!0},subjectId:{type:j.String_unsecure(),isOptional:!0},threshold:{type:j.Float_unsecure(),isOptional:!1},currentValue:{type:j.Float_unsecure(),isOptional:!1},percentageUsed:{type:j.Float_unsecure(),isOptional:!1},triggeredAt:{type:j.DateTime(),isOptional:!1}}}),Mt=w({meta:{key:"metric.defined",version:"1.0.0",description:"A metric has been defined.",stability:"stable",owners:["@platform.metering"],tags:["metering","metric"]},payload:Yt}),ht=w({meta:{key:"metric.updated",version:"1.0.0",description:"A metric has been updated.",stability:"stable",owners:["@platform.metering"],tags:["metering","metric"]},payload:Zt}),nt=w({meta:{key:"usage.recorded",version:"1.0.0",description:"Usage has been recorded.",stability:"stable",owners:["@platform.metering"],tags:["metering","usage"]},payload:vt}),ft=w({meta:{key:"usage.batch_recorded",version:"1.0.0",description:"A batch of usage has been recorded.",stability:"stable",owners:["@platform.metering"],tags:["metering","usage"]},payload:Gt}),ut=w({meta:{key:"usage.aggregated",version:"1.0.0",description:"Usage has been aggregated into a summary.",stability:"stable",owners:["@platform.metering"],tags:["metering","usage"]},payload:xt}),ct=w({meta:{key:"threshold.created",version:"1.0.0",description:"A usage threshold has been created.",stability:"stable",owners:["@platform.metering"],tags:["metering","threshold"]},payload:Ot}),pt=w({meta:{key:"threshold.exceeded",version:"1.0.0",description:"Usage has exceeded a threshold.",stability:"stable",owners:["@platform.metering"],tags:["metering","threshold"]},payload:Nt}),yt=w({meta:{key:"threshold.approaching",version:"1.0.0",description:"Usage is approaching a threshold.",stability:"stable",owners:["@platform.metering"],tags:["metering","threshold"]},payload:Wt}),et=H({name:"ModelSelectionEventPayload",description:"Payload when an AI model is selected via ranking",fields:{modelId:{type:j.String_unsecure(),isOptional:!1},providerKey:{type:j.String_unsecure(),isOptional:!1},dimension:{type:j.String_unsecure(),isOptional:!0},score:{type:j.Float_unsecure(),isOptional:!1},reason:{type:j.String_unsecure(),isOptional:!1},alternativesCount:{type:j.Int_unsecure(),isOptional:!1},costEstimateInput:{type:j.Float_unsecure(),isOptional:!0},costEstimateOutput:{type:j.Float_unsecure(),isOptional:!0},selectionDurationMs:{type:j.Float_unsecure(),isOptional:!0},timestamp:{type:j.DateTime(),isOptional:!1}}}),dt=w({meta:{key:"model.selected",version:"1.0.0",description:"An AI model has been selected via ranking-driven selection.",stability:"experimental",owners:["@platform.metering"],tags:["metering","ai","model-selection"]},payload:et}),Us={MetricDefinedEvent:Mt,MetricUpdatedEvent:ht,UsageRecordedEvent:nt,UsageBatchRecordedEvent:ft,UsageAggregatedEvent:ut,ThresholdCreatedEvent:ct,ThresholdExceededEvent:pt,ThresholdApproachingEvent:yt,ModelSelectionEvent:dt};import{defineFeature as Tt}from"@contractspec/lib.contracts-spec/features";var Cs=Tt({meta:{key:"libs.metering",version:"1.0.0",title:"Metering",description:"Usage metering and billing core module for ContractSpec applications",domain:"metering",owners:["@contractspec-core"],tags:["package","libs","metering"],stability:"experimental"},operations:[{key:"metric.define",version:"1.0.0"},{key:"metric.update",version:"1.0.0"},{key:"metric.delete",version:"1.0.0"},{key:"metric.get",version:"1.0.0"},{key:"metric.list",version:"1.0.0"},{key:"usage.record",version:"1.0.0"},{key:"usage.recordBatch",version:"1.0.0"},{key:"usage.get",version:"1.0.0"},{key:"usage.getSummary",version:"1.0.0"},{key:"threshold.create",version:"1.0.0"},{key:"threshold.update",version:"1.0.0"},{key:"threshold.delete",version:"1.0.0"},{key:"threshold.list",version:"1.0.0"}],events:[{key:"metric.defined",version:"1.0.0"},{key:"metric.updated",version:"1.0.0"},{key:"usage.recorded",version:"1.0.0"},{key:"usage.batch_recorded",version:"1.0.0"},{key:"usage.aggregated",version:"1.0.0"},{key:"threshold.created",version:"1.0.0"},{key:"threshold.exceeded",version:"1.0.0"},{key:"threshold.approaching",version:"1.0.0"},{key:"model.selected",version:"1.0.0"}]});export{_s as meteringSchemaContribution,Xt as meteringEntities,Z as getPeriodStart,N as getPeriodEnd,e as formatPeriodKey,x as UsageThresholdModel,Bt as UsageThresholdEntity,jt as UsageSummaryModel,zt as UsageSummaryEntity,nt as UsageRecordedEvent,h as UsageRecordModel,it as UsageRecordEntity,ft as UsageBatchRecordedEvent,Jt as UsageAlertEntity,T as UsageAggregator,ut as UsageAggregatedEvent,Qs as UpdateThresholdContract,ss as UpdateMetricContract,pt as ThresholdExceededEvent,ct as ThresholdCreatedEvent,yt as ThresholdApproachingEvent,y as ThresholdActionEnum,c as ResetPeriodEnum,Is as RecordUsageContract,rs as RecordBatchUsageContract,bt as PosthogMeteringReporter,m as PosthogMeteringReader,p as PeriodTypeEnum,dt as ModelSelectionEvent,ht as MetricUpdatedEvent,B as MetricDefinitionModel,Ct as MetricDefinitionEntity,Mt as MetricDefinedEvent,Cs as MeteringFeature,Us as MeteringEvents,Ks as ListThresholdsContract,js as ListMetricsContract,S as InMemoryUsageStorage,As as GetUsageSummaryContract,os as GetUsageContract,bs as GetMetricContract,ks as DeleteThresholdContract,gs as DeleteMetricContract,ts as DefineMetricContract,Rs as CreateThresholdContract,u as AggregationTypeEnum};
@@ -1 +1 @@
1
- import{defineFeature as g}from"@contractspec/lib.contracts-spec";var j=g({meta:{key:"metrics",version:"1.0.0",title:"Usage Metering",description:"Usage metering, metric definitions, and threshold alerting",domain:"platform",owners:["@platform.metering"],tags:["metering","usage","billing","thresholds"],stability:"stable"},operations:[{key:"metric.define",version:"1.0.0"},{key:"metric.update",version:"1.0.0"},{key:"metric.delete",version:"1.0.0"},{key:"metric.get",version:"1.0.0"},{key:"metric.list",version:"1.0.0"},{key:"usage.record",version:"1.0.0"},{key:"usage.recordBatch",version:"1.0.0"},{key:"usage.get",version:"1.0.0"},{key:"usage.getSummary",version:"1.0.0"},{key:"threshold.create",version:"1.0.0"},{key:"threshold.update",version:"1.0.0"},{key:"threshold.delete",version:"1.0.0"},{key:"threshold.list",version:"1.0.0"}],events:[{key:"metric.defined",version:"1.0.0"},{key:"metric.updated",version:"1.0.0"},{key:"usage.recorded",version:"1.0.0"},{key:"usage.batch_recorded",version:"1.0.0"},{key:"usage.aggregated",version:"1.0.0"},{key:"threshold.created",version:"1.0.0"},{key:"threshold.exceeded",version:"1.0.0"},{key:"threshold.approaching",version:"1.0.0"},{key:"model.selected",version:"1.0.0"}],presentations:[],opToPresentation:[],presentationsTargets:[],capabilities:{provides:[{key:"metering",version:"1.0.0"},{key:"thresholds",version:"1.0.0"}],requires:[]}});export{j as MeteringFeature};
1
+ import{defineFeature as g}from"@contractspec/lib.contracts-spec/features";var j=g({meta:{key:"libs.metering",version:"1.0.0",title:"Metering",description:"Usage metering and billing core module for ContractSpec applications",domain:"metering",owners:["@contractspec-core"],tags:["package","libs","metering"],stability:"experimental"},operations:[{key:"metric.define",version:"1.0.0"},{key:"metric.update",version:"1.0.0"},{key:"metric.delete",version:"1.0.0"},{key:"metric.get",version:"1.0.0"},{key:"metric.list",version:"1.0.0"},{key:"usage.record",version:"1.0.0"},{key:"usage.recordBatch",version:"1.0.0"},{key:"usage.get",version:"1.0.0"},{key:"usage.getSummary",version:"1.0.0"},{key:"threshold.create",version:"1.0.0"},{key:"threshold.update",version:"1.0.0"},{key:"threshold.delete",version:"1.0.0"},{key:"threshold.list",version:"1.0.0"}],events:[{key:"metric.defined",version:"1.0.0"},{key:"metric.updated",version:"1.0.0"},{key:"usage.recorded",version:"1.0.0"},{key:"usage.batch_recorded",version:"1.0.0"},{key:"usage.aggregated",version:"1.0.0"},{key:"threshold.created",version:"1.0.0"},{key:"threshold.exceeded",version:"1.0.0"},{key:"threshold.approaching",version:"1.0.0"},{key:"model.selected",version:"1.0.0"}]});export{j as MeteringFeature};
package/dist/index.js CHANGED
@@ -49,4 +49,4 @@ await aggregateUsage({
49
49
  - Keep metric keys stable; store quantities as decimals for currency/units.
50
50
  - Use idempotency keys for external ingestion; avoid PII in metric metadata.
51
51
  - Scope by org/user for multi-tenant isolation; emit audit + analytics events on changes.
52
- `}];qt(Vt);import{defineEntity as C,defineEntityEnum as J,field as b,index as K}from"@contractspec/lib.schema";var u=J({name:"AggregationType",values:["COUNT","SUM","AVG","MAX","MIN","LAST"],schema:"lssm_metering",description:"How to aggregate metric values."}),c=J({name:"ResetPeriod",values:["NEVER","HOURLY","DAILY","WEEKLY","MONTHLY","YEARLY"],schema:"lssm_metering",description:"When to reset metric counters."}),p=J({name:"PeriodType",values:["HOURLY","DAILY","WEEKLY","MONTHLY","YEARLY"],schema:"lssm_metering",description:"Time period for aggregation."}),y=J({name:"ThresholdAction",values:["NONE","ALERT","WARN","BLOCK","DOWNGRADE"],schema:"lssm_metering",description:"Action to take when threshold is exceeded."}),Ct=C({name:"MetricDefinition",description:"Definition of a usage metric.",schema:"lssm_metering",map:"metric_definition",fields:{id:b.id({description:"Unique identifier"}),key:b.string({isUnique:!0,description:"Metric key (e.g., api_calls, storage_gb)"}),name:b.string({description:"Human-readable name"}),description:b.string({isOptional:!0,description:"Metric description"}),unit:b.string({description:"Unit of measurement (calls, bytes, etc.)"}),aggregationType:b.enum("AggregationType",{default:"SUM",description:"How to aggregate values"}),resetPeriod:b.enum("ResetPeriod",{default:"MONTHLY",description:"When to reset counters"}),precision:b.int({default:2,description:"Decimal precision"}),orgId:b.string({isOptional:!0,description:"Organization scope (null = global metric)"}),category:b.string({isOptional:!0,description:"Category for grouping"}),displayOrder:b.int({default:0,description:"Order for display"}),metadata:b.json({isOptional:!0,description:"Additional metadata"}),isActive:b.boolean({default:!0,description:"Whether metric is active"}),createdAt:b.createdAt(),updatedAt:b.updatedAt(),usageRecords:b.hasMany("UsageRecord"),usageSummaries:b.hasMany("UsageSummary"),thresholds:b.hasMany("UsageThreshold")},indexes:[K.on(["orgId","key"]),K.on(["category"]),K.on(["isActive"])],enums:[u,c]}),it=C({name:"UsageRecord",description:"A single usage event.",schema:"lssm_metering",map:"usage_record",fields:{id:b.id({description:"Unique identifier"}),metricKey:b.string({description:"Metric being recorded"}),metricId:b.string({isOptional:!0,description:"Metric ID (for FK)"}),subjectType:b.string({description:"Subject type (org, user, project)"}),subjectId:b.string({description:"Subject identifier"}),quantity:b.decimal({description:"Usage quantity"}),source:b.string({isOptional:!0,description:"Source of usage (endpoint, feature, etc.)"}),resourceId:b.string({isOptional:!0,description:"Related resource ID"}),resourceType:b.string({isOptional:!0,description:"Related resource type"}),metadata:b.json({isOptional:!0,description:"Additional context"}),idempotencyKey:b.string({isOptional:!0,description:"Idempotency key for deduplication"}),timestamp:b.dateTime({description:"When usage occurred"}),createdAt:b.createdAt(),aggregated:b.boolean({default:!1,description:"Whether included in summary"}),aggregatedAt:b.dateTime({isOptional:!0,description:"When aggregated"})},indexes:[K.on(["metricKey","subjectType","subjectId","timestamp"]),K.on(["subjectType","subjectId","timestamp"]),K.on(["timestamp"]),K.on(["aggregated","timestamp"]),K.unique(["idempotencyKey"],{name:"usage_record_idempotency"})]}),zt=C({name:"UsageSummary",description:"Pre-aggregated usage summary.",schema:"lssm_metering",map:"usage_summary",fields:{id:b.id({description:"Unique identifier"}),metricKey:b.string({description:"Metric key"}),metricId:b.string({isOptional:!0,description:"Metric ID (for FK)"}),subjectType:b.string({description:"Subject type"}),subjectId:b.string({description:"Subject identifier"}),periodType:b.enum("PeriodType",{description:"Period type"}),periodStart:b.dateTime({description:"Period start time"}),periodEnd:b.dateTime({description:"Period end time"}),totalQuantity:b.decimal({description:"Total/aggregated quantity"}),recordCount:b.int({default:0,description:"Number of records aggregated"}),minQuantity:b.decimal({isOptional:!0,description:"Minimum value"}),maxQuantity:b.decimal({isOptional:!0,description:"Maximum value"}),avgQuantity:b.decimal({isOptional:!0,description:"Average value"}),metadata:b.json({isOptional:!0,description:"Additional metadata"}),createdAt:b.createdAt(),updatedAt:b.updatedAt()},indexes:[K.unique(["metricKey","subjectType","subjectId","periodType","periodStart"],{name:"usage_summary_unique"}),K.on(["subjectType","subjectId","periodType","periodStart"]),K.on(["metricKey","periodType","periodStart"])],enums:[p]}),Bt=C({name:"UsageThreshold",description:"Usage threshold configuration.",schema:"lssm_metering",map:"usage_threshold",fields:{id:b.id({description:"Unique identifier"}),metricKey:b.string({description:"Metric to monitor"}),metricId:b.string({isOptional:!0,description:"Metric ID (for FK)"}),subjectType:b.string({isOptional:!0,description:"Subject type"}),subjectId:b.string({isOptional:!0,description:"Subject identifier"}),name:b.string({description:"Threshold name"}),threshold:b.decimal({description:"Threshold value"}),warnThreshold:b.decimal({isOptional:!0,description:"Warning threshold (e.g., 80%)"}),periodType:b.enum("PeriodType",{default:"MONTHLY",description:"Period to evaluate"}),action:b.enum("ThresholdAction",{default:"ALERT",description:"Action when exceeded"}),notifyEmails:b.json({isOptional:!0,description:"Email addresses to notify"}),notifyWebhook:b.string({isOptional:!0,description:"Webhook URL to call"}),currentValue:b.decimal({default:0,description:"Current usage value"}),lastCheckedAt:b.dateTime({isOptional:!0,description:"Last threshold check"}),lastExceededAt:b.dateTime({isOptional:!0,description:"Last time threshold was exceeded"}),isActive:b.boolean({default:!0,description:"Whether threshold is active"}),metadata:b.json({isOptional:!0,description:"Additional metadata"}),createdAt:b.createdAt(),updatedAt:b.updatedAt()},indexes:[K.on(["metricKey"]),K.on(["subjectType","subjectId"]),K.on(["isActive","metricKey"])],enums:[y]}),Jt=C({name:"UsageAlert",description:"Alert generated when threshold is exceeded.",schema:"lssm_metering",map:"usage_alert",fields:{id:b.id({description:"Unique identifier"}),thresholdId:b.foreignKey({description:"Threshold that triggered alert"}),metricKey:b.string({description:"Metric key"}),subjectType:b.string({isOptional:!0,description:"Subject type"}),subjectId:b.string({isOptional:!0,description:"Subject identifier"}),alertType:b.string({description:"Alert type (warn, exceed, etc.)"}),threshold:b.decimal({description:"Threshold value"}),actualValue:b.decimal({description:"Actual usage value"}),percentageUsed:b.decimal({description:"Percentage of threshold used"}),status:b.string({default:'"pending"',description:"Alert status (pending, acknowledged, resolved)"}),acknowledgedBy:b.string({isOptional:!0,description:"User who acknowledged"}),acknowledgedAt:b.dateTime({isOptional:!0,description:"When acknowledged"}),resolvedAt:b.dateTime({isOptional:!0,description:"When resolved"}),notificationsSent:b.json({isOptional:!0,description:"Notifications sent"}),triggeredAt:b.dateTime({description:"When alert was triggered"}),createdAt:b.createdAt(),thresholdRelation:b.belongsTo("UsageThreshold",["thresholdId"],["id"],{onDelete:"Cascade"})},indexes:[K.on(["thresholdId","status"]),K.on(["metricKey","triggeredAt"]),K.on(["status","triggeredAt"])]}),Xt=[Ct,it,zt,Bt,Jt],_s={moduleId:"@contractspec/lib.metering",entities:Xt,enums:[u,c,p,y]};import{defineEvent as w}from"@contractspec/lib.contracts-spec";import{defineSchemaModel as H,ScalarTypeEnum as j}from"@contractspec/lib.schema";var Yt=H({name:"MetricDefinedEventPayload",description:"Payload when a metric is defined",fields:{metricId:{type:j.String_unsecure(),isOptional:!1},key:{type:j.String_unsecure(),isOptional:!1},name:{type:j.String_unsecure(),isOptional:!1},unit:{type:j.String_unsecure(),isOptional:!1},aggregationType:{type:j.String_unsecure(),isOptional:!1},orgId:{type:j.String_unsecure(),isOptional:!0},createdBy:{type:j.String_unsecure(),isOptional:!0},createdAt:{type:j.DateTime(),isOptional:!1}}}),Zt=H({name:"MetricUpdatedEventPayload",description:"Payload when a metric is updated",fields:{metricId:{type:j.String_unsecure(),isOptional:!1},key:{type:j.String_unsecure(),isOptional:!1},changes:{type:j.JSON(),isOptional:!1},updatedBy:{type:j.String_unsecure(),isOptional:!0},updatedAt:{type:j.DateTime(),isOptional:!1}}}),vt=H({name:"UsageRecordedEventPayload",description:"Payload when usage is recorded",fields:{recordId:{type:j.String_unsecure(),isOptional:!1},metricKey:{type:j.String_unsecure(),isOptional:!1},subjectType:{type:j.String_unsecure(),isOptional:!1},subjectId:{type:j.String_unsecure(),isOptional:!1},quantity:{type:j.Float_unsecure(),isOptional:!1},source:{type:j.String_unsecure(),isOptional:!0},timestamp:{type:j.DateTime(),isOptional:!1}}}),Gt=H({name:"UsageBatchRecordedEventPayload",description:"Payload when a batch of usage is recorded",fields:{recordCount:{type:j.Int_unsecure(),isOptional:!1},metricKeys:{type:j.JSON(),isOptional:!1},totalQuantity:{type:j.Float_unsecure(),isOptional:!1},timestamp:{type:j.DateTime(),isOptional:!1}}}),xt=H({name:"UsageAggregatedEventPayload",description:"Payload when usage is aggregated",fields:{summaryId:{type:j.String_unsecure(),isOptional:!1},metricKey:{type:j.String_unsecure(),isOptional:!1},subjectType:{type:j.String_unsecure(),isOptional:!1},subjectId:{type:j.String_unsecure(),isOptional:!1},periodType:{type:j.String_unsecure(),isOptional:!1},periodStart:{type:j.DateTime(),isOptional:!1},periodEnd:{type:j.DateTime(),isOptional:!1},totalQuantity:{type:j.Float_unsecure(),isOptional:!1},recordCount:{type:j.Int_unsecure(),isOptional:!1},aggregatedAt:{type:j.DateTime(),isOptional:!1}}}),Ot=H({name:"ThresholdCreatedEventPayload",description:"Payload when a threshold is created",fields:{thresholdId:{type:j.String_unsecure(),isOptional:!1},metricKey:{type:j.String_unsecure(),isOptional:!1},subjectType:{type:j.String_unsecure(),isOptional:!0},subjectId:{type:j.String_unsecure(),isOptional:!0},threshold:{type:j.Float_unsecure(),isOptional:!1},action:{type:j.String_unsecure(),isOptional:!1},createdAt:{type:j.DateTime(),isOptional:!1}}}),Nt=H({name:"ThresholdExceededEventPayload",description:"Payload when a threshold is exceeded",fields:{alertId:{type:j.String_unsecure(),isOptional:!1},thresholdId:{type:j.String_unsecure(),isOptional:!1},metricKey:{type:j.String_unsecure(),isOptional:!1},subjectType:{type:j.String_unsecure(),isOptional:!0},subjectId:{type:j.String_unsecure(),isOptional:!0},threshold:{type:j.Float_unsecure(),isOptional:!1},actualValue:{type:j.Float_unsecure(),isOptional:!1},percentageUsed:{type:j.Float_unsecure(),isOptional:!1},action:{type:j.String_unsecure(),isOptional:!1},triggeredAt:{type:j.DateTime(),isOptional:!1}}}),Wt=H({name:"ThresholdApproachingEventPayload",description:"Payload when usage is approaching a threshold",fields:{thresholdId:{type:j.String_unsecure(),isOptional:!1},metricKey:{type:j.String_unsecure(),isOptional:!1},subjectType:{type:j.String_unsecure(),isOptional:!0},subjectId:{type:j.String_unsecure(),isOptional:!0},threshold:{type:j.Float_unsecure(),isOptional:!1},currentValue:{type:j.Float_unsecure(),isOptional:!1},percentageUsed:{type:j.Float_unsecure(),isOptional:!1},triggeredAt:{type:j.DateTime(),isOptional:!1}}}),Mt=w({meta:{key:"metric.defined",version:"1.0.0",description:"A metric has been defined.",stability:"stable",owners:["@platform.metering"],tags:["metering","metric"]},payload:Yt}),ht=w({meta:{key:"metric.updated",version:"1.0.0",description:"A metric has been updated.",stability:"stable",owners:["@platform.metering"],tags:["metering","metric"]},payload:Zt}),nt=w({meta:{key:"usage.recorded",version:"1.0.0",description:"Usage has been recorded.",stability:"stable",owners:["@platform.metering"],tags:["metering","usage"]},payload:vt}),ft=w({meta:{key:"usage.batch_recorded",version:"1.0.0",description:"A batch of usage has been recorded.",stability:"stable",owners:["@platform.metering"],tags:["metering","usage"]},payload:Gt}),ut=w({meta:{key:"usage.aggregated",version:"1.0.0",description:"Usage has been aggregated into a summary.",stability:"stable",owners:["@platform.metering"],tags:["metering","usage"]},payload:xt}),ct=w({meta:{key:"threshold.created",version:"1.0.0",description:"A usage threshold has been created.",stability:"stable",owners:["@platform.metering"],tags:["metering","threshold"]},payload:Ot}),pt=w({meta:{key:"threshold.exceeded",version:"1.0.0",description:"Usage has exceeded a threshold.",stability:"stable",owners:["@platform.metering"],tags:["metering","threshold"]},payload:Nt}),yt=w({meta:{key:"threshold.approaching",version:"1.0.0",description:"Usage is approaching a threshold.",stability:"stable",owners:["@platform.metering"],tags:["metering","threshold"]},payload:Wt}),et=H({name:"ModelSelectionEventPayload",description:"Payload when an AI model is selected via ranking",fields:{modelId:{type:j.String_unsecure(),isOptional:!1},providerKey:{type:j.String_unsecure(),isOptional:!1},dimension:{type:j.String_unsecure(),isOptional:!0},score:{type:j.Float_unsecure(),isOptional:!1},reason:{type:j.String_unsecure(),isOptional:!1},alternativesCount:{type:j.Int_unsecure(),isOptional:!1},costEstimateInput:{type:j.Float_unsecure(),isOptional:!0},costEstimateOutput:{type:j.Float_unsecure(),isOptional:!0},selectionDurationMs:{type:j.Float_unsecure(),isOptional:!0},timestamp:{type:j.DateTime(),isOptional:!1}}}),dt=w({meta:{key:"model.selected",version:"1.0.0",description:"An AI model has been selected via ranking-driven selection.",stability:"experimental",owners:["@platform.metering"],tags:["metering","ai","model-selection"]},payload:et}),Us={MetricDefinedEvent:Mt,MetricUpdatedEvent:ht,UsageRecordedEvent:nt,UsageBatchRecordedEvent:ft,UsageAggregatedEvent:ut,ThresholdCreatedEvent:ct,ThresholdExceededEvent:pt,ThresholdApproachingEvent:yt,ModelSelectionEvent:dt};import{defineFeature as Tt}from"@contractspec/lib.contracts-spec";var Cs=Tt({meta:{key:"metrics",version:"1.0.0",title:"Usage Metering",description:"Usage metering, metric definitions, and threshold alerting",domain:"platform",owners:["@platform.metering"],tags:["metering","usage","billing","thresholds"],stability:"stable"},operations:[{key:"metric.define",version:"1.0.0"},{key:"metric.update",version:"1.0.0"},{key:"metric.delete",version:"1.0.0"},{key:"metric.get",version:"1.0.0"},{key:"metric.list",version:"1.0.0"},{key:"usage.record",version:"1.0.0"},{key:"usage.recordBatch",version:"1.0.0"},{key:"usage.get",version:"1.0.0"},{key:"usage.getSummary",version:"1.0.0"},{key:"threshold.create",version:"1.0.0"},{key:"threshold.update",version:"1.0.0"},{key:"threshold.delete",version:"1.0.0"},{key:"threshold.list",version:"1.0.0"}],events:[{key:"metric.defined",version:"1.0.0"},{key:"metric.updated",version:"1.0.0"},{key:"usage.recorded",version:"1.0.0"},{key:"usage.batch_recorded",version:"1.0.0"},{key:"usage.aggregated",version:"1.0.0"},{key:"threshold.created",version:"1.0.0"},{key:"threshold.exceeded",version:"1.0.0"},{key:"threshold.approaching",version:"1.0.0"},{key:"model.selected",version:"1.0.0"}],presentations:[],opToPresentation:[],presentationsTargets:[],capabilities:{provides:[{key:"metering",version:"1.0.0"},{key:"thresholds",version:"1.0.0"}],requires:[]}});export{_s as meteringSchemaContribution,Xt as meteringEntities,Z as getPeriodStart,N as getPeriodEnd,e as formatPeriodKey,x as UsageThresholdModel,Bt as UsageThresholdEntity,jt as UsageSummaryModel,zt as UsageSummaryEntity,nt as UsageRecordedEvent,h as UsageRecordModel,it as UsageRecordEntity,ft as UsageBatchRecordedEvent,Jt as UsageAlertEntity,T as UsageAggregator,ut as UsageAggregatedEvent,Qs as UpdateThresholdContract,ss as UpdateMetricContract,pt as ThresholdExceededEvent,ct as ThresholdCreatedEvent,yt as ThresholdApproachingEvent,y as ThresholdActionEnum,c as ResetPeriodEnum,Is as RecordUsageContract,rs as RecordBatchUsageContract,bt as PosthogMeteringReporter,m as PosthogMeteringReader,p as PeriodTypeEnum,dt as ModelSelectionEvent,ht as MetricUpdatedEvent,B as MetricDefinitionModel,Ct as MetricDefinitionEntity,Mt as MetricDefinedEvent,Cs as MeteringFeature,Us as MeteringEvents,Ks as ListThresholdsContract,js as ListMetricsContract,S as InMemoryUsageStorage,As as GetUsageSummaryContract,os as GetUsageContract,bs as GetMetricContract,ks as DeleteThresholdContract,gs as DeleteMetricContract,ts as DefineMetricContract,Rs as CreateThresholdContract,u as AggregationTypeEnum};
52
+ `}];qt(Vt);import{defineEntity as C,defineEntityEnum as J,field as b,index as K}from"@contractspec/lib.schema";var u=J({name:"AggregationType",values:["COUNT","SUM","AVG","MAX","MIN","LAST"],schema:"lssm_metering",description:"How to aggregate metric values."}),c=J({name:"ResetPeriod",values:["NEVER","HOURLY","DAILY","WEEKLY","MONTHLY","YEARLY"],schema:"lssm_metering",description:"When to reset metric counters."}),p=J({name:"PeriodType",values:["HOURLY","DAILY","WEEKLY","MONTHLY","YEARLY"],schema:"lssm_metering",description:"Time period for aggregation."}),y=J({name:"ThresholdAction",values:["NONE","ALERT","WARN","BLOCK","DOWNGRADE"],schema:"lssm_metering",description:"Action to take when threshold is exceeded."}),Ct=C({name:"MetricDefinition",description:"Definition of a usage metric.",schema:"lssm_metering",map:"metric_definition",fields:{id:b.id({description:"Unique identifier"}),key:b.string({isUnique:!0,description:"Metric key (e.g., api_calls, storage_gb)"}),name:b.string({description:"Human-readable name"}),description:b.string({isOptional:!0,description:"Metric description"}),unit:b.string({description:"Unit of measurement (calls, bytes, etc.)"}),aggregationType:b.enum("AggregationType",{default:"SUM",description:"How to aggregate values"}),resetPeriod:b.enum("ResetPeriod",{default:"MONTHLY",description:"When to reset counters"}),precision:b.int({default:2,description:"Decimal precision"}),orgId:b.string({isOptional:!0,description:"Organization scope (null = global metric)"}),category:b.string({isOptional:!0,description:"Category for grouping"}),displayOrder:b.int({default:0,description:"Order for display"}),metadata:b.json({isOptional:!0,description:"Additional metadata"}),isActive:b.boolean({default:!0,description:"Whether metric is active"}),createdAt:b.createdAt(),updatedAt:b.updatedAt(),usageRecords:b.hasMany("UsageRecord"),usageSummaries:b.hasMany("UsageSummary"),thresholds:b.hasMany("UsageThreshold")},indexes:[K.on(["orgId","key"]),K.on(["category"]),K.on(["isActive"])],enums:[u,c]}),it=C({name:"UsageRecord",description:"A single usage event.",schema:"lssm_metering",map:"usage_record",fields:{id:b.id({description:"Unique identifier"}),metricKey:b.string({description:"Metric being recorded"}),metricId:b.string({isOptional:!0,description:"Metric ID (for FK)"}),subjectType:b.string({description:"Subject type (org, user, project)"}),subjectId:b.string({description:"Subject identifier"}),quantity:b.decimal({description:"Usage quantity"}),source:b.string({isOptional:!0,description:"Source of usage (endpoint, feature, etc.)"}),resourceId:b.string({isOptional:!0,description:"Related resource ID"}),resourceType:b.string({isOptional:!0,description:"Related resource type"}),metadata:b.json({isOptional:!0,description:"Additional context"}),idempotencyKey:b.string({isOptional:!0,description:"Idempotency key for deduplication"}),timestamp:b.dateTime({description:"When usage occurred"}),createdAt:b.createdAt(),aggregated:b.boolean({default:!1,description:"Whether included in summary"}),aggregatedAt:b.dateTime({isOptional:!0,description:"When aggregated"})},indexes:[K.on(["metricKey","subjectType","subjectId","timestamp"]),K.on(["subjectType","subjectId","timestamp"]),K.on(["timestamp"]),K.on(["aggregated","timestamp"]),K.unique(["idempotencyKey"],{name:"usage_record_idempotency"})]}),zt=C({name:"UsageSummary",description:"Pre-aggregated usage summary.",schema:"lssm_metering",map:"usage_summary",fields:{id:b.id({description:"Unique identifier"}),metricKey:b.string({description:"Metric key"}),metricId:b.string({isOptional:!0,description:"Metric ID (for FK)"}),subjectType:b.string({description:"Subject type"}),subjectId:b.string({description:"Subject identifier"}),periodType:b.enum("PeriodType",{description:"Period type"}),periodStart:b.dateTime({description:"Period start time"}),periodEnd:b.dateTime({description:"Period end time"}),totalQuantity:b.decimal({description:"Total/aggregated quantity"}),recordCount:b.int({default:0,description:"Number of records aggregated"}),minQuantity:b.decimal({isOptional:!0,description:"Minimum value"}),maxQuantity:b.decimal({isOptional:!0,description:"Maximum value"}),avgQuantity:b.decimal({isOptional:!0,description:"Average value"}),metadata:b.json({isOptional:!0,description:"Additional metadata"}),createdAt:b.createdAt(),updatedAt:b.updatedAt()},indexes:[K.unique(["metricKey","subjectType","subjectId","periodType","periodStart"],{name:"usage_summary_unique"}),K.on(["subjectType","subjectId","periodType","periodStart"]),K.on(["metricKey","periodType","periodStart"])],enums:[p]}),Bt=C({name:"UsageThreshold",description:"Usage threshold configuration.",schema:"lssm_metering",map:"usage_threshold",fields:{id:b.id({description:"Unique identifier"}),metricKey:b.string({description:"Metric to monitor"}),metricId:b.string({isOptional:!0,description:"Metric ID (for FK)"}),subjectType:b.string({isOptional:!0,description:"Subject type"}),subjectId:b.string({isOptional:!0,description:"Subject identifier"}),name:b.string({description:"Threshold name"}),threshold:b.decimal({description:"Threshold value"}),warnThreshold:b.decimal({isOptional:!0,description:"Warning threshold (e.g., 80%)"}),periodType:b.enum("PeriodType",{default:"MONTHLY",description:"Period to evaluate"}),action:b.enum("ThresholdAction",{default:"ALERT",description:"Action when exceeded"}),notifyEmails:b.json({isOptional:!0,description:"Email addresses to notify"}),notifyWebhook:b.string({isOptional:!0,description:"Webhook URL to call"}),currentValue:b.decimal({default:0,description:"Current usage value"}),lastCheckedAt:b.dateTime({isOptional:!0,description:"Last threshold check"}),lastExceededAt:b.dateTime({isOptional:!0,description:"Last time threshold was exceeded"}),isActive:b.boolean({default:!0,description:"Whether threshold is active"}),metadata:b.json({isOptional:!0,description:"Additional metadata"}),createdAt:b.createdAt(),updatedAt:b.updatedAt()},indexes:[K.on(["metricKey"]),K.on(["subjectType","subjectId"]),K.on(["isActive","metricKey"])],enums:[y]}),Jt=C({name:"UsageAlert",description:"Alert generated when threshold is exceeded.",schema:"lssm_metering",map:"usage_alert",fields:{id:b.id({description:"Unique identifier"}),thresholdId:b.foreignKey({description:"Threshold that triggered alert"}),metricKey:b.string({description:"Metric key"}),subjectType:b.string({isOptional:!0,description:"Subject type"}),subjectId:b.string({isOptional:!0,description:"Subject identifier"}),alertType:b.string({description:"Alert type (warn, exceed, etc.)"}),threshold:b.decimal({description:"Threshold value"}),actualValue:b.decimal({description:"Actual usage value"}),percentageUsed:b.decimal({description:"Percentage of threshold used"}),status:b.string({default:'"pending"',description:"Alert status (pending, acknowledged, resolved)"}),acknowledgedBy:b.string({isOptional:!0,description:"User who acknowledged"}),acknowledgedAt:b.dateTime({isOptional:!0,description:"When acknowledged"}),resolvedAt:b.dateTime({isOptional:!0,description:"When resolved"}),notificationsSent:b.json({isOptional:!0,description:"Notifications sent"}),triggeredAt:b.dateTime({description:"When alert was triggered"}),createdAt:b.createdAt(),thresholdRelation:b.belongsTo("UsageThreshold",["thresholdId"],["id"],{onDelete:"Cascade"})},indexes:[K.on(["thresholdId","status"]),K.on(["metricKey","triggeredAt"]),K.on(["status","triggeredAt"])]}),Xt=[Ct,it,zt,Bt,Jt],_s={moduleId:"@contractspec/lib.metering",entities:Xt,enums:[u,c,p,y]};import{defineEvent as w}from"@contractspec/lib.contracts-spec";import{defineSchemaModel as H,ScalarTypeEnum as j}from"@contractspec/lib.schema";var Yt=H({name:"MetricDefinedEventPayload",description:"Payload when a metric is defined",fields:{metricId:{type:j.String_unsecure(),isOptional:!1},key:{type:j.String_unsecure(),isOptional:!1},name:{type:j.String_unsecure(),isOptional:!1},unit:{type:j.String_unsecure(),isOptional:!1},aggregationType:{type:j.String_unsecure(),isOptional:!1},orgId:{type:j.String_unsecure(),isOptional:!0},createdBy:{type:j.String_unsecure(),isOptional:!0},createdAt:{type:j.DateTime(),isOptional:!1}}}),Zt=H({name:"MetricUpdatedEventPayload",description:"Payload when a metric is updated",fields:{metricId:{type:j.String_unsecure(),isOptional:!1},key:{type:j.String_unsecure(),isOptional:!1},changes:{type:j.JSON(),isOptional:!1},updatedBy:{type:j.String_unsecure(),isOptional:!0},updatedAt:{type:j.DateTime(),isOptional:!1}}}),vt=H({name:"UsageRecordedEventPayload",description:"Payload when usage is recorded",fields:{recordId:{type:j.String_unsecure(),isOptional:!1},metricKey:{type:j.String_unsecure(),isOptional:!1},subjectType:{type:j.String_unsecure(),isOptional:!1},subjectId:{type:j.String_unsecure(),isOptional:!1},quantity:{type:j.Float_unsecure(),isOptional:!1},source:{type:j.String_unsecure(),isOptional:!0},timestamp:{type:j.DateTime(),isOptional:!1}}}),Gt=H({name:"UsageBatchRecordedEventPayload",description:"Payload when a batch of usage is recorded",fields:{recordCount:{type:j.Int_unsecure(),isOptional:!1},metricKeys:{type:j.JSON(),isOptional:!1},totalQuantity:{type:j.Float_unsecure(),isOptional:!1},timestamp:{type:j.DateTime(),isOptional:!1}}}),xt=H({name:"UsageAggregatedEventPayload",description:"Payload when usage is aggregated",fields:{summaryId:{type:j.String_unsecure(),isOptional:!1},metricKey:{type:j.String_unsecure(),isOptional:!1},subjectType:{type:j.String_unsecure(),isOptional:!1},subjectId:{type:j.String_unsecure(),isOptional:!1},periodType:{type:j.String_unsecure(),isOptional:!1},periodStart:{type:j.DateTime(),isOptional:!1},periodEnd:{type:j.DateTime(),isOptional:!1},totalQuantity:{type:j.Float_unsecure(),isOptional:!1},recordCount:{type:j.Int_unsecure(),isOptional:!1},aggregatedAt:{type:j.DateTime(),isOptional:!1}}}),Ot=H({name:"ThresholdCreatedEventPayload",description:"Payload when a threshold is created",fields:{thresholdId:{type:j.String_unsecure(),isOptional:!1},metricKey:{type:j.String_unsecure(),isOptional:!1},subjectType:{type:j.String_unsecure(),isOptional:!0},subjectId:{type:j.String_unsecure(),isOptional:!0},threshold:{type:j.Float_unsecure(),isOptional:!1},action:{type:j.String_unsecure(),isOptional:!1},createdAt:{type:j.DateTime(),isOptional:!1}}}),Nt=H({name:"ThresholdExceededEventPayload",description:"Payload when a threshold is exceeded",fields:{alertId:{type:j.String_unsecure(),isOptional:!1},thresholdId:{type:j.String_unsecure(),isOptional:!1},metricKey:{type:j.String_unsecure(),isOptional:!1},subjectType:{type:j.String_unsecure(),isOptional:!0},subjectId:{type:j.String_unsecure(),isOptional:!0},threshold:{type:j.Float_unsecure(),isOptional:!1},actualValue:{type:j.Float_unsecure(),isOptional:!1},percentageUsed:{type:j.Float_unsecure(),isOptional:!1},action:{type:j.String_unsecure(),isOptional:!1},triggeredAt:{type:j.DateTime(),isOptional:!1}}}),Wt=H({name:"ThresholdApproachingEventPayload",description:"Payload when usage is approaching a threshold",fields:{thresholdId:{type:j.String_unsecure(),isOptional:!1},metricKey:{type:j.String_unsecure(),isOptional:!1},subjectType:{type:j.String_unsecure(),isOptional:!0},subjectId:{type:j.String_unsecure(),isOptional:!0},threshold:{type:j.Float_unsecure(),isOptional:!1},currentValue:{type:j.Float_unsecure(),isOptional:!1},percentageUsed:{type:j.Float_unsecure(),isOptional:!1},triggeredAt:{type:j.DateTime(),isOptional:!1}}}),Mt=w({meta:{key:"metric.defined",version:"1.0.0",description:"A metric has been defined.",stability:"stable",owners:["@platform.metering"],tags:["metering","metric"]},payload:Yt}),ht=w({meta:{key:"metric.updated",version:"1.0.0",description:"A metric has been updated.",stability:"stable",owners:["@platform.metering"],tags:["metering","metric"]},payload:Zt}),nt=w({meta:{key:"usage.recorded",version:"1.0.0",description:"Usage has been recorded.",stability:"stable",owners:["@platform.metering"],tags:["metering","usage"]},payload:vt}),ft=w({meta:{key:"usage.batch_recorded",version:"1.0.0",description:"A batch of usage has been recorded.",stability:"stable",owners:["@platform.metering"],tags:["metering","usage"]},payload:Gt}),ut=w({meta:{key:"usage.aggregated",version:"1.0.0",description:"Usage has been aggregated into a summary.",stability:"stable",owners:["@platform.metering"],tags:["metering","usage"]},payload:xt}),ct=w({meta:{key:"threshold.created",version:"1.0.0",description:"A usage threshold has been created.",stability:"stable",owners:["@platform.metering"],tags:["metering","threshold"]},payload:Ot}),pt=w({meta:{key:"threshold.exceeded",version:"1.0.0",description:"Usage has exceeded a threshold.",stability:"stable",owners:["@platform.metering"],tags:["metering","threshold"]},payload:Nt}),yt=w({meta:{key:"threshold.approaching",version:"1.0.0",description:"Usage is approaching a threshold.",stability:"stable",owners:["@platform.metering"],tags:["metering","threshold"]},payload:Wt}),et=H({name:"ModelSelectionEventPayload",description:"Payload when an AI model is selected via ranking",fields:{modelId:{type:j.String_unsecure(),isOptional:!1},providerKey:{type:j.String_unsecure(),isOptional:!1},dimension:{type:j.String_unsecure(),isOptional:!0},score:{type:j.Float_unsecure(),isOptional:!1},reason:{type:j.String_unsecure(),isOptional:!1},alternativesCount:{type:j.Int_unsecure(),isOptional:!1},costEstimateInput:{type:j.Float_unsecure(),isOptional:!0},costEstimateOutput:{type:j.Float_unsecure(),isOptional:!0},selectionDurationMs:{type:j.Float_unsecure(),isOptional:!0},timestamp:{type:j.DateTime(),isOptional:!1}}}),dt=w({meta:{key:"model.selected",version:"1.0.0",description:"An AI model has been selected via ranking-driven selection.",stability:"experimental",owners:["@platform.metering"],tags:["metering","ai","model-selection"]},payload:et}),Us={MetricDefinedEvent:Mt,MetricUpdatedEvent:ht,UsageRecordedEvent:nt,UsageBatchRecordedEvent:ft,UsageAggregatedEvent:ut,ThresholdCreatedEvent:ct,ThresholdExceededEvent:pt,ThresholdApproachingEvent:yt,ModelSelectionEvent:dt};import{defineFeature as Tt}from"@contractspec/lib.contracts-spec/features";var Cs=Tt({meta:{key:"libs.metering",version:"1.0.0",title:"Metering",description:"Usage metering and billing core module for ContractSpec applications",domain:"metering",owners:["@contractspec-core"],tags:["package","libs","metering"],stability:"experimental"},operations:[{key:"metric.define",version:"1.0.0"},{key:"metric.update",version:"1.0.0"},{key:"metric.delete",version:"1.0.0"},{key:"metric.get",version:"1.0.0"},{key:"metric.list",version:"1.0.0"},{key:"usage.record",version:"1.0.0"},{key:"usage.recordBatch",version:"1.0.0"},{key:"usage.get",version:"1.0.0"},{key:"usage.getSummary",version:"1.0.0"},{key:"threshold.create",version:"1.0.0"},{key:"threshold.update",version:"1.0.0"},{key:"threshold.delete",version:"1.0.0"},{key:"threshold.list",version:"1.0.0"}],events:[{key:"metric.defined",version:"1.0.0"},{key:"metric.updated",version:"1.0.0"},{key:"usage.recorded",version:"1.0.0"},{key:"usage.batch_recorded",version:"1.0.0"},{key:"usage.aggregated",version:"1.0.0"},{key:"threshold.created",version:"1.0.0"},{key:"threshold.exceeded",version:"1.0.0"},{key:"threshold.approaching",version:"1.0.0"},{key:"model.selected",version:"1.0.0"}]});export{_s as meteringSchemaContribution,Xt as meteringEntities,Z as getPeriodStart,N as getPeriodEnd,e as formatPeriodKey,x as UsageThresholdModel,Bt as UsageThresholdEntity,jt as UsageSummaryModel,zt as UsageSummaryEntity,nt as UsageRecordedEvent,h as UsageRecordModel,it as UsageRecordEntity,ft as UsageBatchRecordedEvent,Jt as UsageAlertEntity,T as UsageAggregator,ut as UsageAggregatedEvent,Qs as UpdateThresholdContract,ss as UpdateMetricContract,pt as ThresholdExceededEvent,ct as ThresholdCreatedEvent,yt as ThresholdApproachingEvent,y as ThresholdActionEnum,c as ResetPeriodEnum,Is as RecordUsageContract,rs as RecordBatchUsageContract,bt as PosthogMeteringReporter,m as PosthogMeteringReader,p as PeriodTypeEnum,dt as ModelSelectionEvent,ht as MetricUpdatedEvent,B as MetricDefinitionModel,Ct as MetricDefinitionEntity,Mt as MetricDefinedEvent,Cs as MeteringFeature,Us as MeteringEvents,Ks as ListThresholdsContract,js as ListMetricsContract,S as InMemoryUsageStorage,As as GetUsageSummaryContract,os as GetUsageContract,bs as GetMetricContract,ks as DeleteThresholdContract,gs as DeleteMetricContract,ts as DefineMetricContract,Rs as CreateThresholdContract,u as AggregationTypeEnum};
@@ -1,5 +1 @@
1
- /**
2
- * Metering feature module that bundles usage tracking,
3
- * metrics definitions, and billing capabilities.
4
- */
5
1
  export declare const MeteringFeature: import("@contractspec/lib.contracts-spec").FeatureModuleSpec;
@@ -1,2 +1,2 @@
1
1
  // @bun
2
- import{defineFeature as g}from"@contractspec/lib.contracts-spec";var j=g({meta:{key:"metrics",version:"1.0.0",title:"Usage Metering",description:"Usage metering, metric definitions, and threshold alerting",domain:"platform",owners:["@platform.metering"],tags:["metering","usage","billing","thresholds"],stability:"stable"},operations:[{key:"metric.define",version:"1.0.0"},{key:"metric.update",version:"1.0.0"},{key:"metric.delete",version:"1.0.0"},{key:"metric.get",version:"1.0.0"},{key:"metric.list",version:"1.0.0"},{key:"usage.record",version:"1.0.0"},{key:"usage.recordBatch",version:"1.0.0"},{key:"usage.get",version:"1.0.0"},{key:"usage.getSummary",version:"1.0.0"},{key:"threshold.create",version:"1.0.0"},{key:"threshold.update",version:"1.0.0"},{key:"threshold.delete",version:"1.0.0"},{key:"threshold.list",version:"1.0.0"}],events:[{key:"metric.defined",version:"1.0.0"},{key:"metric.updated",version:"1.0.0"},{key:"usage.recorded",version:"1.0.0"},{key:"usage.batch_recorded",version:"1.0.0"},{key:"usage.aggregated",version:"1.0.0"},{key:"threshold.created",version:"1.0.0"},{key:"threshold.exceeded",version:"1.0.0"},{key:"threshold.approaching",version:"1.0.0"},{key:"model.selected",version:"1.0.0"}],presentations:[],opToPresentation:[],presentationsTargets:[],capabilities:{provides:[{key:"metering",version:"1.0.0"},{key:"thresholds",version:"1.0.0"}],requires:[]}});export{j as MeteringFeature};
2
+ import{defineFeature as g}from"@contractspec/lib.contracts-spec/features";var j=g({meta:{key:"libs.metering",version:"1.0.0",title:"Metering",description:"Usage metering and billing core module for ContractSpec applications",domain:"metering",owners:["@contractspec-core"],tags:["package","libs","metering"],stability:"experimental"},operations:[{key:"metric.define",version:"1.0.0"},{key:"metric.update",version:"1.0.0"},{key:"metric.delete",version:"1.0.0"},{key:"metric.get",version:"1.0.0"},{key:"metric.list",version:"1.0.0"},{key:"usage.record",version:"1.0.0"},{key:"usage.recordBatch",version:"1.0.0"},{key:"usage.get",version:"1.0.0"},{key:"usage.getSummary",version:"1.0.0"},{key:"threshold.create",version:"1.0.0"},{key:"threshold.update",version:"1.0.0"},{key:"threshold.delete",version:"1.0.0"},{key:"threshold.list",version:"1.0.0"}],events:[{key:"metric.defined",version:"1.0.0"},{key:"metric.updated",version:"1.0.0"},{key:"usage.recorded",version:"1.0.0"},{key:"usage.batch_recorded",version:"1.0.0"},{key:"usage.aggregated",version:"1.0.0"},{key:"threshold.created",version:"1.0.0"},{key:"threshold.exceeded",version:"1.0.0"},{key:"threshold.approaching",version:"1.0.0"},{key:"model.selected",version:"1.0.0"}]});export{j as MeteringFeature};
@@ -48,4 +48,4 @@ await aggregateUsage({
48
48
  - Keep metric keys stable; store quantities as decimals for currency/units.
49
49
  - Use idempotency keys for external ingestion; avoid PII in metric metadata.
50
50
  - Scope by org/user for multi-tenant isolation; emit audit + analytics events on changes.
51
- `}];qt(Vt);import{defineEntity as C,defineEntityEnum as J,field as b,index as K}from"@contractspec/lib.schema";var u=J({name:"AggregationType",values:["COUNT","SUM","AVG","MAX","MIN","LAST"],schema:"lssm_metering",description:"How to aggregate metric values."}),c=J({name:"ResetPeriod",values:["NEVER","HOURLY","DAILY","WEEKLY","MONTHLY","YEARLY"],schema:"lssm_metering",description:"When to reset metric counters."}),p=J({name:"PeriodType",values:["HOURLY","DAILY","WEEKLY","MONTHLY","YEARLY"],schema:"lssm_metering",description:"Time period for aggregation."}),y=J({name:"ThresholdAction",values:["NONE","ALERT","WARN","BLOCK","DOWNGRADE"],schema:"lssm_metering",description:"Action to take when threshold is exceeded."}),Ct=C({name:"MetricDefinition",description:"Definition of a usage metric.",schema:"lssm_metering",map:"metric_definition",fields:{id:b.id({description:"Unique identifier"}),key:b.string({isUnique:!0,description:"Metric key (e.g., api_calls, storage_gb)"}),name:b.string({description:"Human-readable name"}),description:b.string({isOptional:!0,description:"Metric description"}),unit:b.string({description:"Unit of measurement (calls, bytes, etc.)"}),aggregationType:b.enum("AggregationType",{default:"SUM",description:"How to aggregate values"}),resetPeriod:b.enum("ResetPeriod",{default:"MONTHLY",description:"When to reset counters"}),precision:b.int({default:2,description:"Decimal precision"}),orgId:b.string({isOptional:!0,description:"Organization scope (null = global metric)"}),category:b.string({isOptional:!0,description:"Category for grouping"}),displayOrder:b.int({default:0,description:"Order for display"}),metadata:b.json({isOptional:!0,description:"Additional metadata"}),isActive:b.boolean({default:!0,description:"Whether metric is active"}),createdAt:b.createdAt(),updatedAt:b.updatedAt(),usageRecords:b.hasMany("UsageRecord"),usageSummaries:b.hasMany("UsageSummary"),thresholds:b.hasMany("UsageThreshold")},indexes:[K.on(["orgId","key"]),K.on(["category"]),K.on(["isActive"])],enums:[u,c]}),it=C({name:"UsageRecord",description:"A single usage event.",schema:"lssm_metering",map:"usage_record",fields:{id:b.id({description:"Unique identifier"}),metricKey:b.string({description:"Metric being recorded"}),metricId:b.string({isOptional:!0,description:"Metric ID (for FK)"}),subjectType:b.string({description:"Subject type (org, user, project)"}),subjectId:b.string({description:"Subject identifier"}),quantity:b.decimal({description:"Usage quantity"}),source:b.string({isOptional:!0,description:"Source of usage (endpoint, feature, etc.)"}),resourceId:b.string({isOptional:!0,description:"Related resource ID"}),resourceType:b.string({isOptional:!0,description:"Related resource type"}),metadata:b.json({isOptional:!0,description:"Additional context"}),idempotencyKey:b.string({isOptional:!0,description:"Idempotency key for deduplication"}),timestamp:b.dateTime({description:"When usage occurred"}),createdAt:b.createdAt(),aggregated:b.boolean({default:!1,description:"Whether included in summary"}),aggregatedAt:b.dateTime({isOptional:!0,description:"When aggregated"})},indexes:[K.on(["metricKey","subjectType","subjectId","timestamp"]),K.on(["subjectType","subjectId","timestamp"]),K.on(["timestamp"]),K.on(["aggregated","timestamp"]),K.unique(["idempotencyKey"],{name:"usage_record_idempotency"})]}),zt=C({name:"UsageSummary",description:"Pre-aggregated usage summary.",schema:"lssm_metering",map:"usage_summary",fields:{id:b.id({description:"Unique identifier"}),metricKey:b.string({description:"Metric key"}),metricId:b.string({isOptional:!0,description:"Metric ID (for FK)"}),subjectType:b.string({description:"Subject type"}),subjectId:b.string({description:"Subject identifier"}),periodType:b.enum("PeriodType",{description:"Period type"}),periodStart:b.dateTime({description:"Period start time"}),periodEnd:b.dateTime({description:"Period end time"}),totalQuantity:b.decimal({description:"Total/aggregated quantity"}),recordCount:b.int({default:0,description:"Number of records aggregated"}),minQuantity:b.decimal({isOptional:!0,description:"Minimum value"}),maxQuantity:b.decimal({isOptional:!0,description:"Maximum value"}),avgQuantity:b.decimal({isOptional:!0,description:"Average value"}),metadata:b.json({isOptional:!0,description:"Additional metadata"}),createdAt:b.createdAt(),updatedAt:b.updatedAt()},indexes:[K.unique(["metricKey","subjectType","subjectId","periodType","periodStart"],{name:"usage_summary_unique"}),K.on(["subjectType","subjectId","periodType","periodStart"]),K.on(["metricKey","periodType","periodStart"])],enums:[p]}),Bt=C({name:"UsageThreshold",description:"Usage threshold configuration.",schema:"lssm_metering",map:"usage_threshold",fields:{id:b.id({description:"Unique identifier"}),metricKey:b.string({description:"Metric to monitor"}),metricId:b.string({isOptional:!0,description:"Metric ID (for FK)"}),subjectType:b.string({isOptional:!0,description:"Subject type"}),subjectId:b.string({isOptional:!0,description:"Subject identifier"}),name:b.string({description:"Threshold name"}),threshold:b.decimal({description:"Threshold value"}),warnThreshold:b.decimal({isOptional:!0,description:"Warning threshold (e.g., 80%)"}),periodType:b.enum("PeriodType",{default:"MONTHLY",description:"Period to evaluate"}),action:b.enum("ThresholdAction",{default:"ALERT",description:"Action when exceeded"}),notifyEmails:b.json({isOptional:!0,description:"Email addresses to notify"}),notifyWebhook:b.string({isOptional:!0,description:"Webhook URL to call"}),currentValue:b.decimal({default:0,description:"Current usage value"}),lastCheckedAt:b.dateTime({isOptional:!0,description:"Last threshold check"}),lastExceededAt:b.dateTime({isOptional:!0,description:"Last time threshold was exceeded"}),isActive:b.boolean({default:!0,description:"Whether threshold is active"}),metadata:b.json({isOptional:!0,description:"Additional metadata"}),createdAt:b.createdAt(),updatedAt:b.updatedAt()},indexes:[K.on(["metricKey"]),K.on(["subjectType","subjectId"]),K.on(["isActive","metricKey"])],enums:[y]}),Jt=C({name:"UsageAlert",description:"Alert generated when threshold is exceeded.",schema:"lssm_metering",map:"usage_alert",fields:{id:b.id({description:"Unique identifier"}),thresholdId:b.foreignKey({description:"Threshold that triggered alert"}),metricKey:b.string({description:"Metric key"}),subjectType:b.string({isOptional:!0,description:"Subject type"}),subjectId:b.string({isOptional:!0,description:"Subject identifier"}),alertType:b.string({description:"Alert type (warn, exceed, etc.)"}),threshold:b.decimal({description:"Threshold value"}),actualValue:b.decimal({description:"Actual usage value"}),percentageUsed:b.decimal({description:"Percentage of threshold used"}),status:b.string({default:'"pending"',description:"Alert status (pending, acknowledged, resolved)"}),acknowledgedBy:b.string({isOptional:!0,description:"User who acknowledged"}),acknowledgedAt:b.dateTime({isOptional:!0,description:"When acknowledged"}),resolvedAt:b.dateTime({isOptional:!0,description:"When resolved"}),notificationsSent:b.json({isOptional:!0,description:"Notifications sent"}),triggeredAt:b.dateTime({description:"When alert was triggered"}),createdAt:b.createdAt(),thresholdRelation:b.belongsTo("UsageThreshold",["thresholdId"],["id"],{onDelete:"Cascade"})},indexes:[K.on(["thresholdId","status"]),K.on(["metricKey","triggeredAt"]),K.on(["status","triggeredAt"])]}),Xt=[Ct,it,zt,Bt,Jt],_s={moduleId:"@contractspec/lib.metering",entities:Xt,enums:[u,c,p,y]};import{defineEvent as w}from"@contractspec/lib.contracts-spec";import{defineSchemaModel as H,ScalarTypeEnum as j}from"@contractspec/lib.schema";var Yt=H({name:"MetricDefinedEventPayload",description:"Payload when a metric is defined",fields:{metricId:{type:j.String_unsecure(),isOptional:!1},key:{type:j.String_unsecure(),isOptional:!1},name:{type:j.String_unsecure(),isOptional:!1},unit:{type:j.String_unsecure(),isOptional:!1},aggregationType:{type:j.String_unsecure(),isOptional:!1},orgId:{type:j.String_unsecure(),isOptional:!0},createdBy:{type:j.String_unsecure(),isOptional:!0},createdAt:{type:j.DateTime(),isOptional:!1}}}),Zt=H({name:"MetricUpdatedEventPayload",description:"Payload when a metric is updated",fields:{metricId:{type:j.String_unsecure(),isOptional:!1},key:{type:j.String_unsecure(),isOptional:!1},changes:{type:j.JSON(),isOptional:!1},updatedBy:{type:j.String_unsecure(),isOptional:!0},updatedAt:{type:j.DateTime(),isOptional:!1}}}),vt=H({name:"UsageRecordedEventPayload",description:"Payload when usage is recorded",fields:{recordId:{type:j.String_unsecure(),isOptional:!1},metricKey:{type:j.String_unsecure(),isOptional:!1},subjectType:{type:j.String_unsecure(),isOptional:!1},subjectId:{type:j.String_unsecure(),isOptional:!1},quantity:{type:j.Float_unsecure(),isOptional:!1},source:{type:j.String_unsecure(),isOptional:!0},timestamp:{type:j.DateTime(),isOptional:!1}}}),Gt=H({name:"UsageBatchRecordedEventPayload",description:"Payload when a batch of usage is recorded",fields:{recordCount:{type:j.Int_unsecure(),isOptional:!1},metricKeys:{type:j.JSON(),isOptional:!1},totalQuantity:{type:j.Float_unsecure(),isOptional:!1},timestamp:{type:j.DateTime(),isOptional:!1}}}),xt=H({name:"UsageAggregatedEventPayload",description:"Payload when usage is aggregated",fields:{summaryId:{type:j.String_unsecure(),isOptional:!1},metricKey:{type:j.String_unsecure(),isOptional:!1},subjectType:{type:j.String_unsecure(),isOptional:!1},subjectId:{type:j.String_unsecure(),isOptional:!1},periodType:{type:j.String_unsecure(),isOptional:!1},periodStart:{type:j.DateTime(),isOptional:!1},periodEnd:{type:j.DateTime(),isOptional:!1},totalQuantity:{type:j.Float_unsecure(),isOptional:!1},recordCount:{type:j.Int_unsecure(),isOptional:!1},aggregatedAt:{type:j.DateTime(),isOptional:!1}}}),Ot=H({name:"ThresholdCreatedEventPayload",description:"Payload when a threshold is created",fields:{thresholdId:{type:j.String_unsecure(),isOptional:!1},metricKey:{type:j.String_unsecure(),isOptional:!1},subjectType:{type:j.String_unsecure(),isOptional:!0},subjectId:{type:j.String_unsecure(),isOptional:!0},threshold:{type:j.Float_unsecure(),isOptional:!1},action:{type:j.String_unsecure(),isOptional:!1},createdAt:{type:j.DateTime(),isOptional:!1}}}),Nt=H({name:"ThresholdExceededEventPayload",description:"Payload when a threshold is exceeded",fields:{alertId:{type:j.String_unsecure(),isOptional:!1},thresholdId:{type:j.String_unsecure(),isOptional:!1},metricKey:{type:j.String_unsecure(),isOptional:!1},subjectType:{type:j.String_unsecure(),isOptional:!0},subjectId:{type:j.String_unsecure(),isOptional:!0},threshold:{type:j.Float_unsecure(),isOptional:!1},actualValue:{type:j.Float_unsecure(),isOptional:!1},percentageUsed:{type:j.Float_unsecure(),isOptional:!1},action:{type:j.String_unsecure(),isOptional:!1},triggeredAt:{type:j.DateTime(),isOptional:!1}}}),Wt=H({name:"ThresholdApproachingEventPayload",description:"Payload when usage is approaching a threshold",fields:{thresholdId:{type:j.String_unsecure(),isOptional:!1},metricKey:{type:j.String_unsecure(),isOptional:!1},subjectType:{type:j.String_unsecure(),isOptional:!0},subjectId:{type:j.String_unsecure(),isOptional:!0},threshold:{type:j.Float_unsecure(),isOptional:!1},currentValue:{type:j.Float_unsecure(),isOptional:!1},percentageUsed:{type:j.Float_unsecure(),isOptional:!1},triggeredAt:{type:j.DateTime(),isOptional:!1}}}),Mt=w({meta:{key:"metric.defined",version:"1.0.0",description:"A metric has been defined.",stability:"stable",owners:["@platform.metering"],tags:["metering","metric"]},payload:Yt}),ht=w({meta:{key:"metric.updated",version:"1.0.0",description:"A metric has been updated.",stability:"stable",owners:["@platform.metering"],tags:["metering","metric"]},payload:Zt}),nt=w({meta:{key:"usage.recorded",version:"1.0.0",description:"Usage has been recorded.",stability:"stable",owners:["@platform.metering"],tags:["metering","usage"]},payload:vt}),ft=w({meta:{key:"usage.batch_recorded",version:"1.0.0",description:"A batch of usage has been recorded.",stability:"stable",owners:["@platform.metering"],tags:["metering","usage"]},payload:Gt}),ut=w({meta:{key:"usage.aggregated",version:"1.0.0",description:"Usage has been aggregated into a summary.",stability:"stable",owners:["@platform.metering"],tags:["metering","usage"]},payload:xt}),ct=w({meta:{key:"threshold.created",version:"1.0.0",description:"A usage threshold has been created.",stability:"stable",owners:["@platform.metering"],tags:["metering","threshold"]},payload:Ot}),pt=w({meta:{key:"threshold.exceeded",version:"1.0.0",description:"Usage has exceeded a threshold.",stability:"stable",owners:["@platform.metering"],tags:["metering","threshold"]},payload:Nt}),yt=w({meta:{key:"threshold.approaching",version:"1.0.0",description:"Usage is approaching a threshold.",stability:"stable",owners:["@platform.metering"],tags:["metering","threshold"]},payload:Wt}),et=H({name:"ModelSelectionEventPayload",description:"Payload when an AI model is selected via ranking",fields:{modelId:{type:j.String_unsecure(),isOptional:!1},providerKey:{type:j.String_unsecure(),isOptional:!1},dimension:{type:j.String_unsecure(),isOptional:!0},score:{type:j.Float_unsecure(),isOptional:!1},reason:{type:j.String_unsecure(),isOptional:!1},alternativesCount:{type:j.Int_unsecure(),isOptional:!1},costEstimateInput:{type:j.Float_unsecure(),isOptional:!0},costEstimateOutput:{type:j.Float_unsecure(),isOptional:!0},selectionDurationMs:{type:j.Float_unsecure(),isOptional:!0},timestamp:{type:j.DateTime(),isOptional:!1}}}),dt=w({meta:{key:"model.selected",version:"1.0.0",description:"An AI model has been selected via ranking-driven selection.",stability:"experimental",owners:["@platform.metering"],tags:["metering","ai","model-selection"]},payload:et}),Us={MetricDefinedEvent:Mt,MetricUpdatedEvent:ht,UsageRecordedEvent:nt,UsageBatchRecordedEvent:ft,UsageAggregatedEvent:ut,ThresholdCreatedEvent:ct,ThresholdExceededEvent:pt,ThresholdApproachingEvent:yt,ModelSelectionEvent:dt};import{defineFeature as Tt}from"@contractspec/lib.contracts-spec";var Cs=Tt({meta:{key:"metrics",version:"1.0.0",title:"Usage Metering",description:"Usage metering, metric definitions, and threshold alerting",domain:"platform",owners:["@platform.metering"],tags:["metering","usage","billing","thresholds"],stability:"stable"},operations:[{key:"metric.define",version:"1.0.0"},{key:"metric.update",version:"1.0.0"},{key:"metric.delete",version:"1.0.0"},{key:"metric.get",version:"1.0.0"},{key:"metric.list",version:"1.0.0"},{key:"usage.record",version:"1.0.0"},{key:"usage.recordBatch",version:"1.0.0"},{key:"usage.get",version:"1.0.0"},{key:"usage.getSummary",version:"1.0.0"},{key:"threshold.create",version:"1.0.0"},{key:"threshold.update",version:"1.0.0"},{key:"threshold.delete",version:"1.0.0"},{key:"threshold.list",version:"1.0.0"}],events:[{key:"metric.defined",version:"1.0.0"},{key:"metric.updated",version:"1.0.0"},{key:"usage.recorded",version:"1.0.0"},{key:"usage.batch_recorded",version:"1.0.0"},{key:"usage.aggregated",version:"1.0.0"},{key:"threshold.created",version:"1.0.0"},{key:"threshold.exceeded",version:"1.0.0"},{key:"threshold.approaching",version:"1.0.0"},{key:"model.selected",version:"1.0.0"}],presentations:[],opToPresentation:[],presentationsTargets:[],capabilities:{provides:[{key:"metering",version:"1.0.0"},{key:"thresholds",version:"1.0.0"}],requires:[]}});export{_s as meteringSchemaContribution,Xt as meteringEntities,Z as getPeriodStart,N as getPeriodEnd,e as formatPeriodKey,x as UsageThresholdModel,Bt as UsageThresholdEntity,jt as UsageSummaryModel,zt as UsageSummaryEntity,nt as UsageRecordedEvent,h as UsageRecordModel,it as UsageRecordEntity,ft as UsageBatchRecordedEvent,Jt as UsageAlertEntity,T as UsageAggregator,ut as UsageAggregatedEvent,Qs as UpdateThresholdContract,ss as UpdateMetricContract,pt as ThresholdExceededEvent,ct as ThresholdCreatedEvent,yt as ThresholdApproachingEvent,y as ThresholdActionEnum,c as ResetPeriodEnum,Is as RecordUsageContract,rs as RecordBatchUsageContract,bt as PosthogMeteringReporter,m as PosthogMeteringReader,p as PeriodTypeEnum,dt as ModelSelectionEvent,ht as MetricUpdatedEvent,B as MetricDefinitionModel,Ct as MetricDefinitionEntity,Mt as MetricDefinedEvent,Cs as MeteringFeature,Us as MeteringEvents,Ks as ListThresholdsContract,js as ListMetricsContract,S as InMemoryUsageStorage,As as GetUsageSummaryContract,os as GetUsageContract,bs as GetMetricContract,ks as DeleteThresholdContract,gs as DeleteMetricContract,ts as DefineMetricContract,Rs as CreateThresholdContract,u as AggregationTypeEnum};
51
+ `}];qt(Vt);import{defineEntity as C,defineEntityEnum as J,field as b,index as K}from"@contractspec/lib.schema";var u=J({name:"AggregationType",values:["COUNT","SUM","AVG","MAX","MIN","LAST"],schema:"lssm_metering",description:"How to aggregate metric values."}),c=J({name:"ResetPeriod",values:["NEVER","HOURLY","DAILY","WEEKLY","MONTHLY","YEARLY"],schema:"lssm_metering",description:"When to reset metric counters."}),p=J({name:"PeriodType",values:["HOURLY","DAILY","WEEKLY","MONTHLY","YEARLY"],schema:"lssm_metering",description:"Time period for aggregation."}),y=J({name:"ThresholdAction",values:["NONE","ALERT","WARN","BLOCK","DOWNGRADE"],schema:"lssm_metering",description:"Action to take when threshold is exceeded."}),Ct=C({name:"MetricDefinition",description:"Definition of a usage metric.",schema:"lssm_metering",map:"metric_definition",fields:{id:b.id({description:"Unique identifier"}),key:b.string({isUnique:!0,description:"Metric key (e.g., api_calls, storage_gb)"}),name:b.string({description:"Human-readable name"}),description:b.string({isOptional:!0,description:"Metric description"}),unit:b.string({description:"Unit of measurement (calls, bytes, etc.)"}),aggregationType:b.enum("AggregationType",{default:"SUM",description:"How to aggregate values"}),resetPeriod:b.enum("ResetPeriod",{default:"MONTHLY",description:"When to reset counters"}),precision:b.int({default:2,description:"Decimal precision"}),orgId:b.string({isOptional:!0,description:"Organization scope (null = global metric)"}),category:b.string({isOptional:!0,description:"Category for grouping"}),displayOrder:b.int({default:0,description:"Order for display"}),metadata:b.json({isOptional:!0,description:"Additional metadata"}),isActive:b.boolean({default:!0,description:"Whether metric is active"}),createdAt:b.createdAt(),updatedAt:b.updatedAt(),usageRecords:b.hasMany("UsageRecord"),usageSummaries:b.hasMany("UsageSummary"),thresholds:b.hasMany("UsageThreshold")},indexes:[K.on(["orgId","key"]),K.on(["category"]),K.on(["isActive"])],enums:[u,c]}),it=C({name:"UsageRecord",description:"A single usage event.",schema:"lssm_metering",map:"usage_record",fields:{id:b.id({description:"Unique identifier"}),metricKey:b.string({description:"Metric being recorded"}),metricId:b.string({isOptional:!0,description:"Metric ID (for FK)"}),subjectType:b.string({description:"Subject type (org, user, project)"}),subjectId:b.string({description:"Subject identifier"}),quantity:b.decimal({description:"Usage quantity"}),source:b.string({isOptional:!0,description:"Source of usage (endpoint, feature, etc.)"}),resourceId:b.string({isOptional:!0,description:"Related resource ID"}),resourceType:b.string({isOptional:!0,description:"Related resource type"}),metadata:b.json({isOptional:!0,description:"Additional context"}),idempotencyKey:b.string({isOptional:!0,description:"Idempotency key for deduplication"}),timestamp:b.dateTime({description:"When usage occurred"}),createdAt:b.createdAt(),aggregated:b.boolean({default:!1,description:"Whether included in summary"}),aggregatedAt:b.dateTime({isOptional:!0,description:"When aggregated"})},indexes:[K.on(["metricKey","subjectType","subjectId","timestamp"]),K.on(["subjectType","subjectId","timestamp"]),K.on(["timestamp"]),K.on(["aggregated","timestamp"]),K.unique(["idempotencyKey"],{name:"usage_record_idempotency"})]}),zt=C({name:"UsageSummary",description:"Pre-aggregated usage summary.",schema:"lssm_metering",map:"usage_summary",fields:{id:b.id({description:"Unique identifier"}),metricKey:b.string({description:"Metric key"}),metricId:b.string({isOptional:!0,description:"Metric ID (for FK)"}),subjectType:b.string({description:"Subject type"}),subjectId:b.string({description:"Subject identifier"}),periodType:b.enum("PeriodType",{description:"Period type"}),periodStart:b.dateTime({description:"Period start time"}),periodEnd:b.dateTime({description:"Period end time"}),totalQuantity:b.decimal({description:"Total/aggregated quantity"}),recordCount:b.int({default:0,description:"Number of records aggregated"}),minQuantity:b.decimal({isOptional:!0,description:"Minimum value"}),maxQuantity:b.decimal({isOptional:!0,description:"Maximum value"}),avgQuantity:b.decimal({isOptional:!0,description:"Average value"}),metadata:b.json({isOptional:!0,description:"Additional metadata"}),createdAt:b.createdAt(),updatedAt:b.updatedAt()},indexes:[K.unique(["metricKey","subjectType","subjectId","periodType","periodStart"],{name:"usage_summary_unique"}),K.on(["subjectType","subjectId","periodType","periodStart"]),K.on(["metricKey","periodType","periodStart"])],enums:[p]}),Bt=C({name:"UsageThreshold",description:"Usage threshold configuration.",schema:"lssm_metering",map:"usage_threshold",fields:{id:b.id({description:"Unique identifier"}),metricKey:b.string({description:"Metric to monitor"}),metricId:b.string({isOptional:!0,description:"Metric ID (for FK)"}),subjectType:b.string({isOptional:!0,description:"Subject type"}),subjectId:b.string({isOptional:!0,description:"Subject identifier"}),name:b.string({description:"Threshold name"}),threshold:b.decimal({description:"Threshold value"}),warnThreshold:b.decimal({isOptional:!0,description:"Warning threshold (e.g., 80%)"}),periodType:b.enum("PeriodType",{default:"MONTHLY",description:"Period to evaluate"}),action:b.enum("ThresholdAction",{default:"ALERT",description:"Action when exceeded"}),notifyEmails:b.json({isOptional:!0,description:"Email addresses to notify"}),notifyWebhook:b.string({isOptional:!0,description:"Webhook URL to call"}),currentValue:b.decimal({default:0,description:"Current usage value"}),lastCheckedAt:b.dateTime({isOptional:!0,description:"Last threshold check"}),lastExceededAt:b.dateTime({isOptional:!0,description:"Last time threshold was exceeded"}),isActive:b.boolean({default:!0,description:"Whether threshold is active"}),metadata:b.json({isOptional:!0,description:"Additional metadata"}),createdAt:b.createdAt(),updatedAt:b.updatedAt()},indexes:[K.on(["metricKey"]),K.on(["subjectType","subjectId"]),K.on(["isActive","metricKey"])],enums:[y]}),Jt=C({name:"UsageAlert",description:"Alert generated when threshold is exceeded.",schema:"lssm_metering",map:"usage_alert",fields:{id:b.id({description:"Unique identifier"}),thresholdId:b.foreignKey({description:"Threshold that triggered alert"}),metricKey:b.string({description:"Metric key"}),subjectType:b.string({isOptional:!0,description:"Subject type"}),subjectId:b.string({isOptional:!0,description:"Subject identifier"}),alertType:b.string({description:"Alert type (warn, exceed, etc.)"}),threshold:b.decimal({description:"Threshold value"}),actualValue:b.decimal({description:"Actual usage value"}),percentageUsed:b.decimal({description:"Percentage of threshold used"}),status:b.string({default:'"pending"',description:"Alert status (pending, acknowledged, resolved)"}),acknowledgedBy:b.string({isOptional:!0,description:"User who acknowledged"}),acknowledgedAt:b.dateTime({isOptional:!0,description:"When acknowledged"}),resolvedAt:b.dateTime({isOptional:!0,description:"When resolved"}),notificationsSent:b.json({isOptional:!0,description:"Notifications sent"}),triggeredAt:b.dateTime({description:"When alert was triggered"}),createdAt:b.createdAt(),thresholdRelation:b.belongsTo("UsageThreshold",["thresholdId"],["id"],{onDelete:"Cascade"})},indexes:[K.on(["thresholdId","status"]),K.on(["metricKey","triggeredAt"]),K.on(["status","triggeredAt"])]}),Xt=[Ct,it,zt,Bt,Jt],_s={moduleId:"@contractspec/lib.metering",entities:Xt,enums:[u,c,p,y]};import{defineEvent as w}from"@contractspec/lib.contracts-spec";import{defineSchemaModel as H,ScalarTypeEnum as j}from"@contractspec/lib.schema";var Yt=H({name:"MetricDefinedEventPayload",description:"Payload when a metric is defined",fields:{metricId:{type:j.String_unsecure(),isOptional:!1},key:{type:j.String_unsecure(),isOptional:!1},name:{type:j.String_unsecure(),isOptional:!1},unit:{type:j.String_unsecure(),isOptional:!1},aggregationType:{type:j.String_unsecure(),isOptional:!1},orgId:{type:j.String_unsecure(),isOptional:!0},createdBy:{type:j.String_unsecure(),isOptional:!0},createdAt:{type:j.DateTime(),isOptional:!1}}}),Zt=H({name:"MetricUpdatedEventPayload",description:"Payload when a metric is updated",fields:{metricId:{type:j.String_unsecure(),isOptional:!1},key:{type:j.String_unsecure(),isOptional:!1},changes:{type:j.JSON(),isOptional:!1},updatedBy:{type:j.String_unsecure(),isOptional:!0},updatedAt:{type:j.DateTime(),isOptional:!1}}}),vt=H({name:"UsageRecordedEventPayload",description:"Payload when usage is recorded",fields:{recordId:{type:j.String_unsecure(),isOptional:!1},metricKey:{type:j.String_unsecure(),isOptional:!1},subjectType:{type:j.String_unsecure(),isOptional:!1},subjectId:{type:j.String_unsecure(),isOptional:!1},quantity:{type:j.Float_unsecure(),isOptional:!1},source:{type:j.String_unsecure(),isOptional:!0},timestamp:{type:j.DateTime(),isOptional:!1}}}),Gt=H({name:"UsageBatchRecordedEventPayload",description:"Payload when a batch of usage is recorded",fields:{recordCount:{type:j.Int_unsecure(),isOptional:!1},metricKeys:{type:j.JSON(),isOptional:!1},totalQuantity:{type:j.Float_unsecure(),isOptional:!1},timestamp:{type:j.DateTime(),isOptional:!1}}}),xt=H({name:"UsageAggregatedEventPayload",description:"Payload when usage is aggregated",fields:{summaryId:{type:j.String_unsecure(),isOptional:!1},metricKey:{type:j.String_unsecure(),isOptional:!1},subjectType:{type:j.String_unsecure(),isOptional:!1},subjectId:{type:j.String_unsecure(),isOptional:!1},periodType:{type:j.String_unsecure(),isOptional:!1},periodStart:{type:j.DateTime(),isOptional:!1},periodEnd:{type:j.DateTime(),isOptional:!1},totalQuantity:{type:j.Float_unsecure(),isOptional:!1},recordCount:{type:j.Int_unsecure(),isOptional:!1},aggregatedAt:{type:j.DateTime(),isOptional:!1}}}),Ot=H({name:"ThresholdCreatedEventPayload",description:"Payload when a threshold is created",fields:{thresholdId:{type:j.String_unsecure(),isOptional:!1},metricKey:{type:j.String_unsecure(),isOptional:!1},subjectType:{type:j.String_unsecure(),isOptional:!0},subjectId:{type:j.String_unsecure(),isOptional:!0},threshold:{type:j.Float_unsecure(),isOptional:!1},action:{type:j.String_unsecure(),isOptional:!1},createdAt:{type:j.DateTime(),isOptional:!1}}}),Nt=H({name:"ThresholdExceededEventPayload",description:"Payload when a threshold is exceeded",fields:{alertId:{type:j.String_unsecure(),isOptional:!1},thresholdId:{type:j.String_unsecure(),isOptional:!1},metricKey:{type:j.String_unsecure(),isOptional:!1},subjectType:{type:j.String_unsecure(),isOptional:!0},subjectId:{type:j.String_unsecure(),isOptional:!0},threshold:{type:j.Float_unsecure(),isOptional:!1},actualValue:{type:j.Float_unsecure(),isOptional:!1},percentageUsed:{type:j.Float_unsecure(),isOptional:!1},action:{type:j.String_unsecure(),isOptional:!1},triggeredAt:{type:j.DateTime(),isOptional:!1}}}),Wt=H({name:"ThresholdApproachingEventPayload",description:"Payload when usage is approaching a threshold",fields:{thresholdId:{type:j.String_unsecure(),isOptional:!1},metricKey:{type:j.String_unsecure(),isOptional:!1},subjectType:{type:j.String_unsecure(),isOptional:!0},subjectId:{type:j.String_unsecure(),isOptional:!0},threshold:{type:j.Float_unsecure(),isOptional:!1},currentValue:{type:j.Float_unsecure(),isOptional:!1},percentageUsed:{type:j.Float_unsecure(),isOptional:!1},triggeredAt:{type:j.DateTime(),isOptional:!1}}}),Mt=w({meta:{key:"metric.defined",version:"1.0.0",description:"A metric has been defined.",stability:"stable",owners:["@platform.metering"],tags:["metering","metric"]},payload:Yt}),ht=w({meta:{key:"metric.updated",version:"1.0.0",description:"A metric has been updated.",stability:"stable",owners:["@platform.metering"],tags:["metering","metric"]},payload:Zt}),nt=w({meta:{key:"usage.recorded",version:"1.0.0",description:"Usage has been recorded.",stability:"stable",owners:["@platform.metering"],tags:["metering","usage"]},payload:vt}),ft=w({meta:{key:"usage.batch_recorded",version:"1.0.0",description:"A batch of usage has been recorded.",stability:"stable",owners:["@platform.metering"],tags:["metering","usage"]},payload:Gt}),ut=w({meta:{key:"usage.aggregated",version:"1.0.0",description:"Usage has been aggregated into a summary.",stability:"stable",owners:["@platform.metering"],tags:["metering","usage"]},payload:xt}),ct=w({meta:{key:"threshold.created",version:"1.0.0",description:"A usage threshold has been created.",stability:"stable",owners:["@platform.metering"],tags:["metering","threshold"]},payload:Ot}),pt=w({meta:{key:"threshold.exceeded",version:"1.0.0",description:"Usage has exceeded a threshold.",stability:"stable",owners:["@platform.metering"],tags:["metering","threshold"]},payload:Nt}),yt=w({meta:{key:"threshold.approaching",version:"1.0.0",description:"Usage is approaching a threshold.",stability:"stable",owners:["@platform.metering"],tags:["metering","threshold"]},payload:Wt}),et=H({name:"ModelSelectionEventPayload",description:"Payload when an AI model is selected via ranking",fields:{modelId:{type:j.String_unsecure(),isOptional:!1},providerKey:{type:j.String_unsecure(),isOptional:!1},dimension:{type:j.String_unsecure(),isOptional:!0},score:{type:j.Float_unsecure(),isOptional:!1},reason:{type:j.String_unsecure(),isOptional:!1},alternativesCount:{type:j.Int_unsecure(),isOptional:!1},costEstimateInput:{type:j.Float_unsecure(),isOptional:!0},costEstimateOutput:{type:j.Float_unsecure(),isOptional:!0},selectionDurationMs:{type:j.Float_unsecure(),isOptional:!0},timestamp:{type:j.DateTime(),isOptional:!1}}}),dt=w({meta:{key:"model.selected",version:"1.0.0",description:"An AI model has been selected via ranking-driven selection.",stability:"experimental",owners:["@platform.metering"],tags:["metering","ai","model-selection"]},payload:et}),Us={MetricDefinedEvent:Mt,MetricUpdatedEvent:ht,UsageRecordedEvent:nt,UsageBatchRecordedEvent:ft,UsageAggregatedEvent:ut,ThresholdCreatedEvent:ct,ThresholdExceededEvent:pt,ThresholdApproachingEvent:yt,ModelSelectionEvent:dt};import{defineFeature as Tt}from"@contractspec/lib.contracts-spec/features";var Cs=Tt({meta:{key:"libs.metering",version:"1.0.0",title:"Metering",description:"Usage metering and billing core module for ContractSpec applications",domain:"metering",owners:["@contractspec-core"],tags:["package","libs","metering"],stability:"experimental"},operations:[{key:"metric.define",version:"1.0.0"},{key:"metric.update",version:"1.0.0"},{key:"metric.delete",version:"1.0.0"},{key:"metric.get",version:"1.0.0"},{key:"metric.list",version:"1.0.0"},{key:"usage.record",version:"1.0.0"},{key:"usage.recordBatch",version:"1.0.0"},{key:"usage.get",version:"1.0.0"},{key:"usage.getSummary",version:"1.0.0"},{key:"threshold.create",version:"1.0.0"},{key:"threshold.update",version:"1.0.0"},{key:"threshold.delete",version:"1.0.0"},{key:"threshold.list",version:"1.0.0"}],events:[{key:"metric.defined",version:"1.0.0"},{key:"metric.updated",version:"1.0.0"},{key:"usage.recorded",version:"1.0.0"},{key:"usage.batch_recorded",version:"1.0.0"},{key:"usage.aggregated",version:"1.0.0"},{key:"threshold.created",version:"1.0.0"},{key:"threshold.exceeded",version:"1.0.0"},{key:"threshold.approaching",version:"1.0.0"},{key:"model.selected",version:"1.0.0"}]});export{_s as meteringSchemaContribution,Xt as meteringEntities,Z as getPeriodStart,N as getPeriodEnd,e as formatPeriodKey,x as UsageThresholdModel,Bt as UsageThresholdEntity,jt as UsageSummaryModel,zt as UsageSummaryEntity,nt as UsageRecordedEvent,h as UsageRecordModel,it as UsageRecordEntity,ft as UsageBatchRecordedEvent,Jt as UsageAlertEntity,T as UsageAggregator,ut as UsageAggregatedEvent,Qs as UpdateThresholdContract,ss as UpdateMetricContract,pt as ThresholdExceededEvent,ct as ThresholdCreatedEvent,yt as ThresholdApproachingEvent,y as ThresholdActionEnum,c as ResetPeriodEnum,Is as RecordUsageContract,rs as RecordBatchUsageContract,bt as PosthogMeteringReporter,m as PosthogMeteringReader,p as PeriodTypeEnum,dt as ModelSelectionEvent,ht as MetricUpdatedEvent,B as MetricDefinitionModel,Ct as MetricDefinitionEntity,Mt as MetricDefinedEvent,Cs as MeteringFeature,Us as MeteringEvents,Ks as ListThresholdsContract,js as ListMetricsContract,S as InMemoryUsageStorage,As as GetUsageSummaryContract,os as GetUsageContract,bs as GetMetricContract,ks as DeleteThresholdContract,gs as DeleteMetricContract,ts as DefineMetricContract,Rs as CreateThresholdContract,u as AggregationTypeEnum};
@@ -1 +1 @@
1
- import{defineFeature as g}from"@contractspec/lib.contracts-spec";var j=g({meta:{key:"metrics",version:"1.0.0",title:"Usage Metering",description:"Usage metering, metric definitions, and threshold alerting",domain:"platform",owners:["@platform.metering"],tags:["metering","usage","billing","thresholds"],stability:"stable"},operations:[{key:"metric.define",version:"1.0.0"},{key:"metric.update",version:"1.0.0"},{key:"metric.delete",version:"1.0.0"},{key:"metric.get",version:"1.0.0"},{key:"metric.list",version:"1.0.0"},{key:"usage.record",version:"1.0.0"},{key:"usage.recordBatch",version:"1.0.0"},{key:"usage.get",version:"1.0.0"},{key:"usage.getSummary",version:"1.0.0"},{key:"threshold.create",version:"1.0.0"},{key:"threshold.update",version:"1.0.0"},{key:"threshold.delete",version:"1.0.0"},{key:"threshold.list",version:"1.0.0"}],events:[{key:"metric.defined",version:"1.0.0"},{key:"metric.updated",version:"1.0.0"},{key:"usage.recorded",version:"1.0.0"},{key:"usage.batch_recorded",version:"1.0.0"},{key:"usage.aggregated",version:"1.0.0"},{key:"threshold.created",version:"1.0.0"},{key:"threshold.exceeded",version:"1.0.0"},{key:"threshold.approaching",version:"1.0.0"},{key:"model.selected",version:"1.0.0"}],presentations:[],opToPresentation:[],presentationsTargets:[],capabilities:{provides:[{key:"metering",version:"1.0.0"},{key:"thresholds",version:"1.0.0"}],requires:[]}});export{j as MeteringFeature};
1
+ import{defineFeature as g}from"@contractspec/lib.contracts-spec/features";var j=g({meta:{key:"libs.metering",version:"1.0.0",title:"Metering",description:"Usage metering and billing core module for ContractSpec applications",domain:"metering",owners:["@contractspec-core"],tags:["package","libs","metering"],stability:"experimental"},operations:[{key:"metric.define",version:"1.0.0"},{key:"metric.update",version:"1.0.0"},{key:"metric.delete",version:"1.0.0"},{key:"metric.get",version:"1.0.0"},{key:"metric.list",version:"1.0.0"},{key:"usage.record",version:"1.0.0"},{key:"usage.recordBatch",version:"1.0.0"},{key:"usage.get",version:"1.0.0"},{key:"usage.getSummary",version:"1.0.0"},{key:"threshold.create",version:"1.0.0"},{key:"threshold.update",version:"1.0.0"},{key:"threshold.delete",version:"1.0.0"},{key:"threshold.list",version:"1.0.0"}],events:[{key:"metric.defined",version:"1.0.0"},{key:"metric.updated",version:"1.0.0"},{key:"usage.recorded",version:"1.0.0"},{key:"usage.batch_recorded",version:"1.0.0"},{key:"usage.aggregated",version:"1.0.0"},{key:"threshold.created",version:"1.0.0"},{key:"threshold.exceeded",version:"1.0.0"},{key:"threshold.approaching",version:"1.0.0"},{key:"model.selected",version:"1.0.0"}]});export{j as MeteringFeature};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contractspec/lib.metering",
3
- "version": "3.7.20",
3
+ "version": "3.7.22",
4
4
  "description": "Usage metering and billing core module for ContractSpec applications",
5
5
  "keywords": [
6
6
  "contractspec",
@@ -28,14 +28,14 @@
28
28
  },
29
29
  "dependencies": {
30
30
  "@contractspec/lib.schema": "3.7.14",
31
- "@contractspec/lib.contracts-spec": "5.4.0",
32
- "@contractspec/lib.contracts-integrations": "3.8.12",
31
+ "@contractspec/lib.contracts-spec": "5.5.1",
32
+ "@contractspec/lib.contracts-integrations": "3.8.14",
33
33
  "zod": "^4.3.5"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@contractspec/tool.typescript": "3.7.13",
37
37
  "typescript": "^5.9.3",
38
- "@contractspec/tool.bun": "3.7.14"
38
+ "@contractspec/tool.bun": "3.7.17"
39
39
  },
40
40
  "exports": {
41
41
  ".": {