@sovr/engine 3.7.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -2768,6 +2768,42 @@ interface AuditEvent {
2768
2768
  * Users can extend or override these.
2769
2769
  */
2770
2770
  declare const DEFAULT_RULES: PolicyRule[];
2771
+ /**
2772
+ * SOVR Billing Event Types — aligned with the pricing model:
2773
+ * 1. gate.check — low price or included in quota (every policy evaluation)
2774
+ * 2. gate.block — usually free or very low price (blocked requests)
2775
+ * 3. irreversible.allowed — HIGH PRICE core tax base (allowed irreversible ops)
2776
+ * 4. trust_bundle.issued — medium-high price (Trust Bundle generation)
2777
+ * 5. trust_bundle.exported — higher price (audit necessity)
2778
+ * 6. replay.requested — optional, per-use or monthly (trace replay)
2779
+ * 7. auditor.session — enterprise billing (external audit sessions)
2780
+ */
2781
+ type BillingEventType = 'gate.check' | 'gate.block' | 'irreversible.allowed' | 'trust_bundle.issued' | 'trust_bundle.exported' | 'replay.requested' | 'auditor.session';
2782
+ interface BillingEvent {
2783
+ event_type: BillingEventType;
2784
+ action: string;
2785
+ resource: string;
2786
+ verdict: string;
2787
+ api_key: string;
2788
+ timestamp: number;
2789
+ metadata?: Record<string, unknown>;
2790
+ }
2791
+ interface BillingConfig {
2792
+ /** Enable billing event reporting (default: true) */
2793
+ enabled?: boolean;
2794
+ /** Metering endpoint URL (default: SOVR cloud) */
2795
+ meteringEndpoint?: string;
2796
+ /** Batch flush interval in milliseconds (default: 10000) */
2797
+ flushIntervalMs?: number;
2798
+ /** Maximum events in buffer before auto-flush (default: 500) */
2799
+ bufferMax?: number;
2800
+ }
2801
+ interface BillingStats {
2802
+ eventsReported: number;
2803
+ eventsDropped: number;
2804
+ bufferSize: number;
2805
+ byType: Record<BillingEventType, number>;
2806
+ }
2771
2807
  type EngineTier = 'free' | 'personal' | 'starter' | 'pro' | 'enterprise';
2772
2808
  interface EngineTierLimits {
2773
2809
  evaluationsPerMonth: number;
@@ -2782,12 +2818,51 @@ declare class PolicyEngine {
2782
2818
  private _usage;
2783
2819
  private _apiKey;
2784
2820
  private _versionChecked;
2821
+ private _billingEnabled;
2822
+ private _billingEndpoint;
2823
+ private _billingBuffer;
2824
+ private _billingFlushTimer;
2825
+ private _billingFlushInterval;
2826
+ private _billingBufferMax;
2827
+ private _billingStats;
2828
+ private _loginValidated;
2785
2829
  constructor(config: EngineConfig & {
2786
2830
  tier?: EngineTier;
2787
2831
  apiKey?: string;
2832
+ billing?: BillingConfig;
2788
2833
  });
2789
2834
  /** v3.1.0: Async version check — blocks evaluate() on first call if deprecated */
2790
2835
  private _asyncVersionCheck;
2836
+ /**
2837
+ * Async login validation — verifies API Key is bound to a registered user.
2838
+ * Runs once at startup. On failure: logs warning but allows operation (fail-open).
2839
+ * On success: sets tier from server response.
2840
+ */
2841
+ private _asyncLoginValidation;
2842
+ /** Get login validation status */
2843
+ get loginValidated(): boolean;
2844
+ /**
2845
+ * Record a billing event into the buffer.
2846
+ * Fire-and-forget — never blocks the main request flow.
2847
+ */
2848
+ recordBillingEvent(event_type: BillingEventType, action: string, resource: string, verdict: string, metadata?: Record<string, unknown>): void;
2849
+ /**
2850
+ * Flush billing buffer to the metering endpoint.
2851
+ * Batch POST — fire-and-forget with re-queue on failure.
2852
+ */
2853
+ private _flushBillingBuffer;
2854
+ /**
2855
+ * Classify an evaluate() call into the appropriate billing event type.
2856
+ * Key pricing principle: "放行的不可逆动作" is the highest-price tax base.
2857
+ */
2858
+ private _classifyBillingEvent;
2859
+ /** Get billing statistics */
2860
+ get billingStats(): BillingStats;
2861
+ /**
2862
+ * Flush remaining billing events and stop the timer.
2863
+ * Call this before process exit for clean shutdown.
2864
+ */
2865
+ shutdown(): Promise<void>;
2791
2866
  /** Set the current tier (e.g., after API key verification) */
2792
2867
  setTier(tier: EngineTier): void;
2793
2868
  /** Get current tier */
@@ -2831,4 +2906,4 @@ declare class PolicyEngine {
2831
2906
  }): void;
2832
2907
  }
2833
2908
 
2834
- export { type ABTestConfig, AdaptiveThresholdManager, type AdaptiveThresholdOptions, type AdjustmentResult, type AggregateSnapshot, type AggregationResult, type AggregationType, type AggregationWindow, type AlertEvent, type AlertSeverity$1 as AlertSeverity, type AlertThreshold, type AlertType, type AssembledContext, type AttributionRule, type AuditEvent, AutoHardenEngine, type BudgetAlert, type BudgetConfig, type BudgetLevel, type BudgetNode, type CacheConfig, type CacheEntry, type CacheLayer, type CacheStrategy, type CapabilityFlags, type CapitalizationResult, type Channel, type ChecklistItem, type ChecklistItemStatus, type CircuitBreakerState, type CircuitState, type ClockDriftReport, type CockpitMetric, type CockpitTimeWindow, type ComparableInput, type ComparableResult, type ComparisonNode, type CompiledExpression, type ConsistencyMismatch, type ConsistencyResult, type ConstraintCheckResult, type ConstraintConfig, type ConstraintDecision, type ConstraintLevel, type ConstraintMode, type ConstraintState, type ConstraintTrigger, ContextAccelerator, type ContextAcceleratorConfig, type ContextFragment, type ContextPriority, type ContributionDimension, type ContributionEvent, type ContributionScore, ContributionSettlementEngine, type CostAlert, type CostAuditEvent, type CostCategory$1 as CostCategory, type CostEntry, type CostEstimate, type CostEstimateRequest, type CostGateEnhancedConfig, CostGateEnhancedEngine, type CostRecord, type CostReport, type CostSummary, type DCFInput, type DCFResult, DEFAULT_CA_CONFIG, DEFAULT_GE_CONFIG, DEFAULT_HARD_RULES, DEFAULT_RULES, DEFAULT_SCORING_WEIGHTS, DEFAULT_TSA_CONFIG, type DataPoint, type DecisionFeedback, type DegradationLevel, type DegradeState, type DriftAlert, type DriftAnalyzerConfig, type DriftConfig, type DriftIndex, type DriftPattern, type DriftResult, type DriftWindow, type EligibilityResult, type EngineConfig, type EngineTier, type EngineTierLimits, type EntityType, type EstimateAccuracy, type EvalContext, type EvalRequest, type EvalResult, type EventOrderValidation, type EvictionPolicy, EvolutionChannelEngine, type EvolutionConfig, type EvolutionEvent, type ExecContext, type ExprTreePolicyRule, type ExpressionNode, type FailureBudget, type FailureCategory, type FailureRecord, type FailureSeverity, type FeasibilityCheck, type FeatureSwitchDef, type FeatureSwitchState, FeatureSwitchesManager, type FeatureSwitchesOptions, type CostCategory as FinOpsCostCategory, type FreezeType, type FunctionNode, type PolicyVersion as GovPolicyVersion, type GovernanceDecision, GovernanceEnhancer, type GovernanceEnhancerConfig, type GovernanceRule, type HardRule, type HardenConfig, type HardenEvent, type HardenLevel, type HardenMeasure, type HardenMeasureType, type HardenState, type HealthScore, type HttpContext, type KillSwitchState, type LiteralNode, type LogicalNode, type MarketSize, type McpContext, type MetricPoint, type ModelCandidate, type ModelPricing, type ModelTier, type MonitoringMetrics, type MultiLevelBudgetConfig, MultiLevelBudgetEngine, type NetworkEffectInput, type NetworkEffectResult, type NotNode, OverrideDriftAnalyzer, type OverrideEvent, type PenaltyCheck, PolicyEngine, type PolicyRule, type PolicySnapshot, type PolicyVersion$1 as PolicyVersion, type PrefetchRule, type PricingEvalRequest, type PricingEvalResult, type PricingRule, PricingRulesEngine, type ProtectiveAction, type RankResult, type RankableItem, type RankingConfig, type RankingSnapshot, type RealityConstraint, type ReasonCode, type RecalcEngineConfig, type RecalcGranularity, type RecalcHandler, type RecalcTask, type RecalcTaskStatus, type RecalcTriggerType, RecalculationEngine, type ReleasePhase, type ReleaseVersion, type RiskLevel, type RoutingDecision, type RoutingRequest, type RuleCondition, type RuleEvalResult, SOVR_FEATURE_SWITCHES, type ScoreConfigVersion, type ScoringResult, type ScoringWeights, SelfConstraintEngine, SemanticDriftDetectorEngine, type SemanticFingerprint, type SensitivityResult, type SettlementContext, type SqlContext, type SystemState, TIME_WINDOWS, type ThresholdConfig, type TighteningThresholds, type TimeConsistencyConfig, TimeSeriesAggregator, type TimeSeriesAggregatorConfig, type TimestampRecord, type ToolPricing, TrendAlertEngine, type TrendMetric, TwoPhaseRouter, type TwoPhaseRouterConfig, type UnitEconomics, ValuationModel, type ValuationModelConfig, type VariableNode, type Verdict, type WindowType, compileFromJSON, compileRuleSet, createAutoHardenEngine, createCostGateEnhanced, createEvolutionChannel, createMultiLevelBudget, createRecalculationEngine, createSemanticDriftDetector, PolicyEngine as default, estimateCost, evaluateRules, getAccuracyStats, getModelPricingTable, getToolPricingTable, recordActualCost, registerFunction, updateModelPricing, updateToolPricing };
2909
+ export { type ABTestConfig, AdaptiveThresholdManager, type AdaptiveThresholdOptions, type AdjustmentResult, type AggregateSnapshot, type AggregationResult, type AggregationType, type AggregationWindow, type AlertEvent, type AlertSeverity$1 as AlertSeverity, type AlertThreshold, type AlertType, type AssembledContext, type AttributionRule, type AuditEvent, AutoHardenEngine, type BillingConfig, type BillingEvent, type BillingEventType, type BillingStats, type BudgetAlert, type BudgetConfig, type BudgetLevel, type BudgetNode, type CacheConfig, type CacheEntry, type CacheLayer, type CacheStrategy, type CapabilityFlags, type CapitalizationResult, type Channel, type ChecklistItem, type ChecklistItemStatus, type CircuitBreakerState, type CircuitState, type ClockDriftReport, type CockpitMetric, type CockpitTimeWindow, type ComparableInput, type ComparableResult, type ComparisonNode, type CompiledExpression, type ConsistencyMismatch, type ConsistencyResult, type ConstraintCheckResult, type ConstraintConfig, type ConstraintDecision, type ConstraintLevel, type ConstraintMode, type ConstraintState, type ConstraintTrigger, ContextAccelerator, type ContextAcceleratorConfig, type ContextFragment, type ContextPriority, type ContributionDimension, type ContributionEvent, type ContributionScore, ContributionSettlementEngine, type CostAlert, type CostAuditEvent, type CostCategory$1 as CostCategory, type CostEntry, type CostEstimate, type CostEstimateRequest, type CostGateEnhancedConfig, CostGateEnhancedEngine, type CostRecord, type CostReport, type CostSummary, type DCFInput, type DCFResult, DEFAULT_CA_CONFIG, DEFAULT_GE_CONFIG, DEFAULT_HARD_RULES, DEFAULT_RULES, DEFAULT_SCORING_WEIGHTS, DEFAULT_TSA_CONFIG, type DataPoint, type DecisionFeedback, type DegradationLevel, type DegradeState, type DriftAlert, type DriftAnalyzerConfig, type DriftConfig, type DriftIndex, type DriftPattern, type DriftResult, type DriftWindow, type EligibilityResult, type EngineConfig, type EngineTier, type EngineTierLimits, type EntityType, type EstimateAccuracy, type EvalContext, type EvalRequest, type EvalResult, type EventOrderValidation, type EvictionPolicy, EvolutionChannelEngine, type EvolutionConfig, type EvolutionEvent, type ExecContext, type ExprTreePolicyRule, type ExpressionNode, type FailureBudget, type FailureCategory, type FailureRecord, type FailureSeverity, type FeasibilityCheck, type FeatureSwitchDef, type FeatureSwitchState, FeatureSwitchesManager, type FeatureSwitchesOptions, type CostCategory as FinOpsCostCategory, type FreezeType, type FunctionNode, type PolicyVersion as GovPolicyVersion, type GovernanceDecision, GovernanceEnhancer, type GovernanceEnhancerConfig, type GovernanceRule, type HardRule, type HardenConfig, type HardenEvent, type HardenLevel, type HardenMeasure, type HardenMeasureType, type HardenState, type HealthScore, type HttpContext, type KillSwitchState, type LiteralNode, type LogicalNode, type MarketSize, type McpContext, type MetricPoint, type ModelCandidate, type ModelPricing, type ModelTier, type MonitoringMetrics, type MultiLevelBudgetConfig, MultiLevelBudgetEngine, type NetworkEffectInput, type NetworkEffectResult, type NotNode, OverrideDriftAnalyzer, type OverrideEvent, type PenaltyCheck, PolicyEngine, type PolicyRule, type PolicySnapshot, type PolicyVersion$1 as PolicyVersion, type PrefetchRule, type PricingEvalRequest, type PricingEvalResult, type PricingRule, PricingRulesEngine, type ProtectiveAction, type RankResult, type RankableItem, type RankingConfig, type RankingSnapshot, type RealityConstraint, type ReasonCode, type RecalcEngineConfig, type RecalcGranularity, type RecalcHandler, type RecalcTask, type RecalcTaskStatus, type RecalcTriggerType, RecalculationEngine, type ReleasePhase, type ReleaseVersion, type RiskLevel, type RoutingDecision, type RoutingRequest, type RuleCondition, type RuleEvalResult, SOVR_FEATURE_SWITCHES, type ScoreConfigVersion, type ScoringResult, type ScoringWeights, SelfConstraintEngine, SemanticDriftDetectorEngine, type SemanticFingerprint, type SensitivityResult, type SettlementContext, type SqlContext, type SystemState, TIME_WINDOWS, type ThresholdConfig, type TighteningThresholds, type TimeConsistencyConfig, TimeSeriesAggregator, type TimeSeriesAggregatorConfig, type TimestampRecord, type ToolPricing, TrendAlertEngine, type TrendMetric, TwoPhaseRouter, type TwoPhaseRouterConfig, type UnitEconomics, ValuationModel, type ValuationModelConfig, type VariableNode, type Verdict, type WindowType, compileFromJSON, compileRuleSet, createAutoHardenEngine, createCostGateEnhanced, createEvolutionChannel, createMultiLevelBudget, createRecalculationEngine, createSemanticDriftDetector, PolicyEngine as default, estimateCost, evaluateRules, getAccuracyStats, getModelPricingTable, getToolPricingTable, recordActualCost, registerFunction, updateModelPricing, updateToolPricing };
package/dist/index.d.ts CHANGED
@@ -2768,6 +2768,42 @@ interface AuditEvent {
2768
2768
  * Users can extend or override these.
2769
2769
  */
2770
2770
  declare const DEFAULT_RULES: PolicyRule[];
2771
+ /**
2772
+ * SOVR Billing Event Types — aligned with the pricing model:
2773
+ * 1. gate.check — low price or included in quota (every policy evaluation)
2774
+ * 2. gate.block — usually free or very low price (blocked requests)
2775
+ * 3. irreversible.allowed — HIGH PRICE core tax base (allowed irreversible ops)
2776
+ * 4. trust_bundle.issued — medium-high price (Trust Bundle generation)
2777
+ * 5. trust_bundle.exported — higher price (audit necessity)
2778
+ * 6. replay.requested — optional, per-use or monthly (trace replay)
2779
+ * 7. auditor.session — enterprise billing (external audit sessions)
2780
+ */
2781
+ type BillingEventType = 'gate.check' | 'gate.block' | 'irreversible.allowed' | 'trust_bundle.issued' | 'trust_bundle.exported' | 'replay.requested' | 'auditor.session';
2782
+ interface BillingEvent {
2783
+ event_type: BillingEventType;
2784
+ action: string;
2785
+ resource: string;
2786
+ verdict: string;
2787
+ api_key: string;
2788
+ timestamp: number;
2789
+ metadata?: Record<string, unknown>;
2790
+ }
2791
+ interface BillingConfig {
2792
+ /** Enable billing event reporting (default: true) */
2793
+ enabled?: boolean;
2794
+ /** Metering endpoint URL (default: SOVR cloud) */
2795
+ meteringEndpoint?: string;
2796
+ /** Batch flush interval in milliseconds (default: 10000) */
2797
+ flushIntervalMs?: number;
2798
+ /** Maximum events in buffer before auto-flush (default: 500) */
2799
+ bufferMax?: number;
2800
+ }
2801
+ interface BillingStats {
2802
+ eventsReported: number;
2803
+ eventsDropped: number;
2804
+ bufferSize: number;
2805
+ byType: Record<BillingEventType, number>;
2806
+ }
2771
2807
  type EngineTier = 'free' | 'personal' | 'starter' | 'pro' | 'enterprise';
2772
2808
  interface EngineTierLimits {
2773
2809
  evaluationsPerMonth: number;
@@ -2782,12 +2818,51 @@ declare class PolicyEngine {
2782
2818
  private _usage;
2783
2819
  private _apiKey;
2784
2820
  private _versionChecked;
2821
+ private _billingEnabled;
2822
+ private _billingEndpoint;
2823
+ private _billingBuffer;
2824
+ private _billingFlushTimer;
2825
+ private _billingFlushInterval;
2826
+ private _billingBufferMax;
2827
+ private _billingStats;
2828
+ private _loginValidated;
2785
2829
  constructor(config: EngineConfig & {
2786
2830
  tier?: EngineTier;
2787
2831
  apiKey?: string;
2832
+ billing?: BillingConfig;
2788
2833
  });
2789
2834
  /** v3.1.0: Async version check — blocks evaluate() on first call if deprecated */
2790
2835
  private _asyncVersionCheck;
2836
+ /**
2837
+ * Async login validation — verifies API Key is bound to a registered user.
2838
+ * Runs once at startup. On failure: logs warning but allows operation (fail-open).
2839
+ * On success: sets tier from server response.
2840
+ */
2841
+ private _asyncLoginValidation;
2842
+ /** Get login validation status */
2843
+ get loginValidated(): boolean;
2844
+ /**
2845
+ * Record a billing event into the buffer.
2846
+ * Fire-and-forget — never blocks the main request flow.
2847
+ */
2848
+ recordBillingEvent(event_type: BillingEventType, action: string, resource: string, verdict: string, metadata?: Record<string, unknown>): void;
2849
+ /**
2850
+ * Flush billing buffer to the metering endpoint.
2851
+ * Batch POST — fire-and-forget with re-queue on failure.
2852
+ */
2853
+ private _flushBillingBuffer;
2854
+ /**
2855
+ * Classify an evaluate() call into the appropriate billing event type.
2856
+ * Key pricing principle: "放行的不可逆动作" is the highest-price tax base.
2857
+ */
2858
+ private _classifyBillingEvent;
2859
+ /** Get billing statistics */
2860
+ get billingStats(): BillingStats;
2861
+ /**
2862
+ * Flush remaining billing events and stop the timer.
2863
+ * Call this before process exit for clean shutdown.
2864
+ */
2865
+ shutdown(): Promise<void>;
2791
2866
  /** Set the current tier (e.g., after API key verification) */
2792
2867
  setTier(tier: EngineTier): void;
2793
2868
  /** Get current tier */
@@ -2831,4 +2906,4 @@ declare class PolicyEngine {
2831
2906
  }): void;
2832
2907
  }
2833
2908
 
2834
- export { type ABTestConfig, AdaptiveThresholdManager, type AdaptiveThresholdOptions, type AdjustmentResult, type AggregateSnapshot, type AggregationResult, type AggregationType, type AggregationWindow, type AlertEvent, type AlertSeverity$1 as AlertSeverity, type AlertThreshold, type AlertType, type AssembledContext, type AttributionRule, type AuditEvent, AutoHardenEngine, type BudgetAlert, type BudgetConfig, type BudgetLevel, type BudgetNode, type CacheConfig, type CacheEntry, type CacheLayer, type CacheStrategy, type CapabilityFlags, type CapitalizationResult, type Channel, type ChecklistItem, type ChecklistItemStatus, type CircuitBreakerState, type CircuitState, type ClockDriftReport, type CockpitMetric, type CockpitTimeWindow, type ComparableInput, type ComparableResult, type ComparisonNode, type CompiledExpression, type ConsistencyMismatch, type ConsistencyResult, type ConstraintCheckResult, type ConstraintConfig, type ConstraintDecision, type ConstraintLevel, type ConstraintMode, type ConstraintState, type ConstraintTrigger, ContextAccelerator, type ContextAcceleratorConfig, type ContextFragment, type ContextPriority, type ContributionDimension, type ContributionEvent, type ContributionScore, ContributionSettlementEngine, type CostAlert, type CostAuditEvent, type CostCategory$1 as CostCategory, type CostEntry, type CostEstimate, type CostEstimateRequest, type CostGateEnhancedConfig, CostGateEnhancedEngine, type CostRecord, type CostReport, type CostSummary, type DCFInput, type DCFResult, DEFAULT_CA_CONFIG, DEFAULT_GE_CONFIG, DEFAULT_HARD_RULES, DEFAULT_RULES, DEFAULT_SCORING_WEIGHTS, DEFAULT_TSA_CONFIG, type DataPoint, type DecisionFeedback, type DegradationLevel, type DegradeState, type DriftAlert, type DriftAnalyzerConfig, type DriftConfig, type DriftIndex, type DriftPattern, type DriftResult, type DriftWindow, type EligibilityResult, type EngineConfig, type EngineTier, type EngineTierLimits, type EntityType, type EstimateAccuracy, type EvalContext, type EvalRequest, type EvalResult, type EventOrderValidation, type EvictionPolicy, EvolutionChannelEngine, type EvolutionConfig, type EvolutionEvent, type ExecContext, type ExprTreePolicyRule, type ExpressionNode, type FailureBudget, type FailureCategory, type FailureRecord, type FailureSeverity, type FeasibilityCheck, type FeatureSwitchDef, type FeatureSwitchState, FeatureSwitchesManager, type FeatureSwitchesOptions, type CostCategory as FinOpsCostCategory, type FreezeType, type FunctionNode, type PolicyVersion as GovPolicyVersion, type GovernanceDecision, GovernanceEnhancer, type GovernanceEnhancerConfig, type GovernanceRule, type HardRule, type HardenConfig, type HardenEvent, type HardenLevel, type HardenMeasure, type HardenMeasureType, type HardenState, type HealthScore, type HttpContext, type KillSwitchState, type LiteralNode, type LogicalNode, type MarketSize, type McpContext, type MetricPoint, type ModelCandidate, type ModelPricing, type ModelTier, type MonitoringMetrics, type MultiLevelBudgetConfig, MultiLevelBudgetEngine, type NetworkEffectInput, type NetworkEffectResult, type NotNode, OverrideDriftAnalyzer, type OverrideEvent, type PenaltyCheck, PolicyEngine, type PolicyRule, type PolicySnapshot, type PolicyVersion$1 as PolicyVersion, type PrefetchRule, type PricingEvalRequest, type PricingEvalResult, type PricingRule, PricingRulesEngine, type ProtectiveAction, type RankResult, type RankableItem, type RankingConfig, type RankingSnapshot, type RealityConstraint, type ReasonCode, type RecalcEngineConfig, type RecalcGranularity, type RecalcHandler, type RecalcTask, type RecalcTaskStatus, type RecalcTriggerType, RecalculationEngine, type ReleasePhase, type ReleaseVersion, type RiskLevel, type RoutingDecision, type RoutingRequest, type RuleCondition, type RuleEvalResult, SOVR_FEATURE_SWITCHES, type ScoreConfigVersion, type ScoringResult, type ScoringWeights, SelfConstraintEngine, SemanticDriftDetectorEngine, type SemanticFingerprint, type SensitivityResult, type SettlementContext, type SqlContext, type SystemState, TIME_WINDOWS, type ThresholdConfig, type TighteningThresholds, type TimeConsistencyConfig, TimeSeriesAggregator, type TimeSeriesAggregatorConfig, type TimestampRecord, type ToolPricing, TrendAlertEngine, type TrendMetric, TwoPhaseRouter, type TwoPhaseRouterConfig, type UnitEconomics, ValuationModel, type ValuationModelConfig, type VariableNode, type Verdict, type WindowType, compileFromJSON, compileRuleSet, createAutoHardenEngine, createCostGateEnhanced, createEvolutionChannel, createMultiLevelBudget, createRecalculationEngine, createSemanticDriftDetector, PolicyEngine as default, estimateCost, evaluateRules, getAccuracyStats, getModelPricingTable, getToolPricingTable, recordActualCost, registerFunction, updateModelPricing, updateToolPricing };
2909
+ export { type ABTestConfig, AdaptiveThresholdManager, type AdaptiveThresholdOptions, type AdjustmentResult, type AggregateSnapshot, type AggregationResult, type AggregationType, type AggregationWindow, type AlertEvent, type AlertSeverity$1 as AlertSeverity, type AlertThreshold, type AlertType, type AssembledContext, type AttributionRule, type AuditEvent, AutoHardenEngine, type BillingConfig, type BillingEvent, type BillingEventType, type BillingStats, type BudgetAlert, type BudgetConfig, type BudgetLevel, type BudgetNode, type CacheConfig, type CacheEntry, type CacheLayer, type CacheStrategy, type CapabilityFlags, type CapitalizationResult, type Channel, type ChecklistItem, type ChecklistItemStatus, type CircuitBreakerState, type CircuitState, type ClockDriftReport, type CockpitMetric, type CockpitTimeWindow, type ComparableInput, type ComparableResult, type ComparisonNode, type CompiledExpression, type ConsistencyMismatch, type ConsistencyResult, type ConstraintCheckResult, type ConstraintConfig, type ConstraintDecision, type ConstraintLevel, type ConstraintMode, type ConstraintState, type ConstraintTrigger, ContextAccelerator, type ContextAcceleratorConfig, type ContextFragment, type ContextPriority, type ContributionDimension, type ContributionEvent, type ContributionScore, ContributionSettlementEngine, type CostAlert, type CostAuditEvent, type CostCategory$1 as CostCategory, type CostEntry, type CostEstimate, type CostEstimateRequest, type CostGateEnhancedConfig, CostGateEnhancedEngine, type CostRecord, type CostReport, type CostSummary, type DCFInput, type DCFResult, DEFAULT_CA_CONFIG, DEFAULT_GE_CONFIG, DEFAULT_HARD_RULES, DEFAULT_RULES, DEFAULT_SCORING_WEIGHTS, DEFAULT_TSA_CONFIG, type DataPoint, type DecisionFeedback, type DegradationLevel, type DegradeState, type DriftAlert, type DriftAnalyzerConfig, type DriftConfig, type DriftIndex, type DriftPattern, type DriftResult, type DriftWindow, type EligibilityResult, type EngineConfig, type EngineTier, type EngineTierLimits, type EntityType, type EstimateAccuracy, type EvalContext, type EvalRequest, type EvalResult, type EventOrderValidation, type EvictionPolicy, EvolutionChannelEngine, type EvolutionConfig, type EvolutionEvent, type ExecContext, type ExprTreePolicyRule, type ExpressionNode, type FailureBudget, type FailureCategory, type FailureRecord, type FailureSeverity, type FeasibilityCheck, type FeatureSwitchDef, type FeatureSwitchState, FeatureSwitchesManager, type FeatureSwitchesOptions, type CostCategory as FinOpsCostCategory, type FreezeType, type FunctionNode, type PolicyVersion as GovPolicyVersion, type GovernanceDecision, GovernanceEnhancer, type GovernanceEnhancerConfig, type GovernanceRule, type HardRule, type HardenConfig, type HardenEvent, type HardenLevel, type HardenMeasure, type HardenMeasureType, type HardenState, type HealthScore, type HttpContext, type KillSwitchState, type LiteralNode, type LogicalNode, type MarketSize, type McpContext, type MetricPoint, type ModelCandidate, type ModelPricing, type ModelTier, type MonitoringMetrics, type MultiLevelBudgetConfig, MultiLevelBudgetEngine, type NetworkEffectInput, type NetworkEffectResult, type NotNode, OverrideDriftAnalyzer, type OverrideEvent, type PenaltyCheck, PolicyEngine, type PolicyRule, type PolicySnapshot, type PolicyVersion$1 as PolicyVersion, type PrefetchRule, type PricingEvalRequest, type PricingEvalResult, type PricingRule, PricingRulesEngine, type ProtectiveAction, type RankResult, type RankableItem, type RankingConfig, type RankingSnapshot, type RealityConstraint, type ReasonCode, type RecalcEngineConfig, type RecalcGranularity, type RecalcHandler, type RecalcTask, type RecalcTaskStatus, type RecalcTriggerType, RecalculationEngine, type ReleasePhase, type ReleaseVersion, type RiskLevel, type RoutingDecision, type RoutingRequest, type RuleCondition, type RuleEvalResult, SOVR_FEATURE_SWITCHES, type ScoreConfigVersion, type ScoringResult, type ScoringWeights, SelfConstraintEngine, SemanticDriftDetectorEngine, type SemanticFingerprint, type SensitivityResult, type SettlementContext, type SqlContext, type SystemState, TIME_WINDOWS, type ThresholdConfig, type TighteningThresholds, type TimeConsistencyConfig, TimeSeriesAggregator, type TimeSeriesAggregatorConfig, type TimestampRecord, type ToolPricing, TrendAlertEngine, type TrendMetric, TwoPhaseRouter, type TwoPhaseRouterConfig, type UnitEconomics, ValuationModel, type ValuationModelConfig, type VariableNode, type Verdict, type WindowType, compileFromJSON, compileRuleSet, createAutoHardenEngine, createCostGateEnhanced, createEvolutionChannel, createMultiLevelBudget, createRecalculationEngine, createSemanticDriftDetector, PolicyEngine as default, estimateCost, evaluateRules, getAccuracyStats, getModelPricingTable, getToolPricingTable, recordActualCost, registerFunction, updateModelPricing, updateToolPricing };
package/dist/index.js CHANGED
@@ -4615,8 +4615,11 @@ var RISK_SCORES = {
4615
4615
  high: 70,
4616
4616
  critical: 95
4617
4617
  };
4618
- var ENGINE_VERSION = "3.4.0";
4618
+ var ENGINE_VERSION = "4.0.0";
4619
4619
  var ENGINE_VERSION_CHECK_URL = "https://api.sovr.inc/api/sovr/v1/version/check";
4620
+ var DEFAULT_METERING_ENDPOINT = "https://sovr-ai-mkzgqqeh.manus.space/api/v1/metering/batch";
4621
+ var LOGIN_VALIDATE_URL = "https://sovr-ai-mkzgqqeh.manus.space/api/keys/validate";
4622
+ var IRREVERSIBLE_ACTION_REGEX = /^(DELETE|DROP|TRUNCATE|ALTER|UPDATE|INSERT|CREATE|GRANT|REVOKE|COPY|shell_exec|file_write|db_delete|db_update|db_execute|payment|deploy|publish)$/i;
4620
4623
  var ENGINE_TIER_LIMITS = {
4621
4624
  free: { evaluationsPerMonth: 50, irreversibleAllowsPerMonth: 0 },
4622
4625
  personal: { evaluationsPerMonth: 5e3, irreversibleAllowsPerMonth: 500 },
@@ -4633,6 +4636,28 @@ var PolicyEngine = class {
4633
4636
  _usage = { evaluations: 0, irreversibleAllows: 0, monthKey: "" };
4634
4637
  _apiKey;
4635
4638
  _versionChecked = false;
4639
+ // v4.0.0: BillingReporter
4640
+ _billingEnabled;
4641
+ _billingEndpoint;
4642
+ _billingBuffer = [];
4643
+ _billingFlushTimer = null;
4644
+ _billingFlushInterval;
4645
+ _billingBufferMax;
4646
+ _billingStats = {
4647
+ eventsReported: 0,
4648
+ eventsDropped: 0,
4649
+ bufferSize: 0,
4650
+ byType: {
4651
+ "gate.check": 0,
4652
+ "gate.block": 0,
4653
+ "irreversible.allowed": 0,
4654
+ "trust_bundle.issued": 0,
4655
+ "trust_bundle.exported": 0,
4656
+ "replay.requested": 0,
4657
+ "auditor.session": 0
4658
+ }
4659
+ };
4660
+ _loginValidated = false;
4636
4661
  constructor(config) {
4637
4662
  this._apiKey = config.apiKey || process.env.SOVR_API_KEY || "";
4638
4663
  if (!this._apiKey) {
@@ -4664,7 +4689,19 @@ var PolicyEngine = class {
4664
4689
  this._tier = config.tier ?? "free";
4665
4690
  const now = /* @__PURE__ */ new Date();
4666
4691
  this._usage.monthKey = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}`;
4692
+ const billing = config.billing ?? {};
4693
+ this._billingEnabled = billing.enabled !== false;
4694
+ this._billingEndpoint = billing.meteringEndpoint ?? DEFAULT_METERING_ENDPOINT;
4695
+ this._billingFlushInterval = billing.flushIntervalMs ?? 1e4;
4696
+ this._billingBufferMax = billing.bufferMax ?? 500;
4667
4697
  this._asyncVersionCheck();
4698
+ this._asyncLoginValidation();
4699
+ if (this._billingEnabled) {
4700
+ this._billingFlushTimer = setInterval(() => {
4701
+ this._flushBillingBuffer().catch(() => {
4702
+ });
4703
+ }, this._billingFlushInterval);
4704
+ }
4668
4705
  }
4669
4706
  /** v3.1.0: Async version check — blocks evaluate() on first call if deprecated */
4670
4707
  async _asyncVersionCheck() {
@@ -4707,6 +4744,137 @@ var PolicyEngine = class {
4707
4744
  }
4708
4745
  }
4709
4746
  }
4747
+ // ============================================================================
4748
+ // v4.0.0: Mandatory Login Validation (Remote API Key → User Identity)
4749
+ // ============================================================================
4750
+ /**
4751
+ * Async login validation — verifies API Key is bound to a registered user.
4752
+ * Runs once at startup. On failure: logs warning but allows operation (fail-open).
4753
+ * On success: sets tier from server response.
4754
+ */
4755
+ async _asyncLoginValidation() {
4756
+ if (this._loginValidated) return;
4757
+ try {
4758
+ const res = await globalThis.fetch(LOGIN_VALIDATE_URL, {
4759
+ method: "GET",
4760
+ headers: {
4761
+ "Authorization": `Bearer ${this._apiKey}`,
4762
+ "X-SOVR-Source": "engine",
4763
+ "X-SOVR-Version": ENGINE_VERSION
4764
+ },
4765
+ signal: AbortSignal.timeout(8e3)
4766
+ });
4767
+ if (res.ok) {
4768
+ const data = await res.json();
4769
+ this._loginValidated = true;
4770
+ if (data.tier) {
4771
+ this._tier = data.tier;
4772
+ }
4773
+ if (data.valid === false) {
4774
+ console.error(
4775
+ "\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n\u2551 SOVR LOGIN VALIDATION FAILED \u2551\n\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563\n\u2551 Your API key is not bound to a registered user. \u2551\n\u2551 Please login at: https://sovr.inc/login \u2551\n\u2551 Then get a valid key: https://sovr.inc/dashboard/api-keys \u2551\n\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\n"
4776
+ );
4777
+ }
4778
+ } else if (res.status === 401 || res.status === 403) {
4779
+ console.error(
4780
+ `[SOVR ENGINE] Login validation failed (HTTP ${res.status}). API key may be invalid or expired.`
4781
+ );
4782
+ }
4783
+ } catch {
4784
+ }
4785
+ }
4786
+ /** Get login validation status */
4787
+ get loginValidated() {
4788
+ return this._loginValidated;
4789
+ }
4790
+ // ============================================================================
4791
+ // v4.0.0: BillingReporter — 7 event types, batch flush, quota check
4792
+ // ============================================================================
4793
+ /**
4794
+ * Record a billing event into the buffer.
4795
+ * Fire-and-forget — never blocks the main request flow.
4796
+ */
4797
+ recordBillingEvent(event_type, action, resource, verdict, metadata) {
4798
+ if (!this._billingEnabled) return;
4799
+ this._billingBuffer.push({
4800
+ event_type,
4801
+ action,
4802
+ resource,
4803
+ verdict,
4804
+ api_key: this._apiKey,
4805
+ timestamp: Date.now(),
4806
+ metadata
4807
+ });
4808
+ this._billingStats.byType[event_type] = (this._billingStats.byType[event_type] || 0) + 1;
4809
+ if (this._billingBuffer.length >= this._billingBufferMax) {
4810
+ this._flushBillingBuffer().catch(() => {
4811
+ });
4812
+ }
4813
+ }
4814
+ /**
4815
+ * Flush billing buffer to the metering endpoint.
4816
+ * Batch POST — fire-and-forget with re-queue on failure.
4817
+ */
4818
+ async _flushBillingBuffer() {
4819
+ if (this._billingBuffer.length === 0) return;
4820
+ const batch = this._billingBuffer.splice(0, this._billingBufferMax);
4821
+ try {
4822
+ const response = await globalThis.fetch(this._billingEndpoint, {
4823
+ method: "POST",
4824
+ headers: {
4825
+ "Content-Type": "application/json",
4826
+ "Authorization": `Bearer ${this._apiKey}`,
4827
+ "X-SOVR-Source": "engine",
4828
+ "X-SOVR-Version": ENGINE_VERSION
4829
+ },
4830
+ body: JSON.stringify({ events: batch }),
4831
+ signal: AbortSignal.timeout(5e3)
4832
+ });
4833
+ if (response.ok) {
4834
+ this._billingStats.eventsReported += batch.length;
4835
+ } else {
4836
+ throw new Error(`HTTP ${response.status}`);
4837
+ }
4838
+ } catch {
4839
+ if (this._billingBuffer.length < this._billingBufferMax * 2) {
4840
+ this._billingBuffer.unshift(...batch);
4841
+ } else {
4842
+ this._billingStats.eventsDropped += batch.length;
4843
+ }
4844
+ }
4845
+ }
4846
+ /**
4847
+ * Classify an evaluate() call into the appropriate billing event type.
4848
+ * Key pricing principle: "放行的不可逆动作" is the highest-price tax base.
4849
+ */
4850
+ _classifyBillingEvent(action, verdict) {
4851
+ if (verdict === "deny" || verdict === "block") {
4852
+ return "gate.block";
4853
+ }
4854
+ if ((verdict === "allow" || verdict === "escalate") && IRREVERSIBLE_ACTION_REGEX.test(action)) {
4855
+ return "irreversible.allowed";
4856
+ }
4857
+ return "gate.check";
4858
+ }
4859
+ /** Get billing statistics */
4860
+ get billingStats() {
4861
+ return {
4862
+ ...this._billingStats,
4863
+ bufferSize: this._billingBuffer.length
4864
+ };
4865
+ }
4866
+ /**
4867
+ * Flush remaining billing events and stop the timer.
4868
+ * Call this before process exit for clean shutdown.
4869
+ */
4870
+ async shutdown() {
4871
+ if (this._billingFlushTimer) {
4872
+ clearInterval(this._billingFlushTimer);
4873
+ this._billingFlushTimer = null;
4874
+ }
4875
+ await this._flushBillingBuffer().catch(() => {
4876
+ });
4877
+ }
4710
4878
  /** Set the current tier (e.g., after API key verification) */
4711
4879
  setTier(tier) {
4712
4880
  this._tier = tier;
@@ -4818,6 +4986,14 @@ var PolicyEngine = class {
4818
4986
  Promise.resolve(this.onAudit(event)).catch(() => {
4819
4987
  });
4820
4988
  }
4989
+ const billingType = this._classifyBillingEvent(request.action, verdict);
4990
+ this.recordBillingEvent(billingType, request.action, request.resource, verdict, {
4991
+ risk_score: riskScore,
4992
+ risk_level: riskLevel,
4993
+ decision_id: decisionId,
4994
+ channel: request.channel,
4995
+ matched_rules: matchedRules.length
4996
+ });
4821
4997
  if (this._tier === "free") {
4822
4998
  return {
4823
4999
  ...result,
package/dist/index.mjs CHANGED
@@ -4545,8 +4545,11 @@ var RISK_SCORES = {
4545
4545
  high: 70,
4546
4546
  critical: 95
4547
4547
  };
4548
- var ENGINE_VERSION = "3.4.0";
4548
+ var ENGINE_VERSION = "4.0.0";
4549
4549
  var ENGINE_VERSION_CHECK_URL = "https://api.sovr.inc/api/sovr/v1/version/check";
4550
+ var DEFAULT_METERING_ENDPOINT = "https://sovr-ai-mkzgqqeh.manus.space/api/v1/metering/batch";
4551
+ var LOGIN_VALIDATE_URL = "https://sovr-ai-mkzgqqeh.manus.space/api/keys/validate";
4552
+ var IRREVERSIBLE_ACTION_REGEX = /^(DELETE|DROP|TRUNCATE|ALTER|UPDATE|INSERT|CREATE|GRANT|REVOKE|COPY|shell_exec|file_write|db_delete|db_update|db_execute|payment|deploy|publish)$/i;
4550
4553
  var ENGINE_TIER_LIMITS = {
4551
4554
  free: { evaluationsPerMonth: 50, irreversibleAllowsPerMonth: 0 },
4552
4555
  personal: { evaluationsPerMonth: 5e3, irreversibleAllowsPerMonth: 500 },
@@ -4563,6 +4566,28 @@ var PolicyEngine = class {
4563
4566
  _usage = { evaluations: 0, irreversibleAllows: 0, monthKey: "" };
4564
4567
  _apiKey;
4565
4568
  _versionChecked = false;
4569
+ // v4.0.0: BillingReporter
4570
+ _billingEnabled;
4571
+ _billingEndpoint;
4572
+ _billingBuffer = [];
4573
+ _billingFlushTimer = null;
4574
+ _billingFlushInterval;
4575
+ _billingBufferMax;
4576
+ _billingStats = {
4577
+ eventsReported: 0,
4578
+ eventsDropped: 0,
4579
+ bufferSize: 0,
4580
+ byType: {
4581
+ "gate.check": 0,
4582
+ "gate.block": 0,
4583
+ "irreversible.allowed": 0,
4584
+ "trust_bundle.issued": 0,
4585
+ "trust_bundle.exported": 0,
4586
+ "replay.requested": 0,
4587
+ "auditor.session": 0
4588
+ }
4589
+ };
4590
+ _loginValidated = false;
4566
4591
  constructor(config) {
4567
4592
  this._apiKey = config.apiKey || process.env.SOVR_API_KEY || "";
4568
4593
  if (!this._apiKey) {
@@ -4594,7 +4619,19 @@ var PolicyEngine = class {
4594
4619
  this._tier = config.tier ?? "free";
4595
4620
  const now = /* @__PURE__ */ new Date();
4596
4621
  this._usage.monthKey = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}`;
4622
+ const billing = config.billing ?? {};
4623
+ this._billingEnabled = billing.enabled !== false;
4624
+ this._billingEndpoint = billing.meteringEndpoint ?? DEFAULT_METERING_ENDPOINT;
4625
+ this._billingFlushInterval = billing.flushIntervalMs ?? 1e4;
4626
+ this._billingBufferMax = billing.bufferMax ?? 500;
4597
4627
  this._asyncVersionCheck();
4628
+ this._asyncLoginValidation();
4629
+ if (this._billingEnabled) {
4630
+ this._billingFlushTimer = setInterval(() => {
4631
+ this._flushBillingBuffer().catch(() => {
4632
+ });
4633
+ }, this._billingFlushInterval);
4634
+ }
4598
4635
  }
4599
4636
  /** v3.1.0: Async version check — blocks evaluate() on first call if deprecated */
4600
4637
  async _asyncVersionCheck() {
@@ -4637,6 +4674,137 @@ var PolicyEngine = class {
4637
4674
  }
4638
4675
  }
4639
4676
  }
4677
+ // ============================================================================
4678
+ // v4.0.0: Mandatory Login Validation (Remote API Key → User Identity)
4679
+ // ============================================================================
4680
+ /**
4681
+ * Async login validation — verifies API Key is bound to a registered user.
4682
+ * Runs once at startup. On failure: logs warning but allows operation (fail-open).
4683
+ * On success: sets tier from server response.
4684
+ */
4685
+ async _asyncLoginValidation() {
4686
+ if (this._loginValidated) return;
4687
+ try {
4688
+ const res = await globalThis.fetch(LOGIN_VALIDATE_URL, {
4689
+ method: "GET",
4690
+ headers: {
4691
+ "Authorization": `Bearer ${this._apiKey}`,
4692
+ "X-SOVR-Source": "engine",
4693
+ "X-SOVR-Version": ENGINE_VERSION
4694
+ },
4695
+ signal: AbortSignal.timeout(8e3)
4696
+ });
4697
+ if (res.ok) {
4698
+ const data = await res.json();
4699
+ this._loginValidated = true;
4700
+ if (data.tier) {
4701
+ this._tier = data.tier;
4702
+ }
4703
+ if (data.valid === false) {
4704
+ console.error(
4705
+ "\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n\u2551 SOVR LOGIN VALIDATION FAILED \u2551\n\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563\n\u2551 Your API key is not bound to a registered user. \u2551\n\u2551 Please login at: https://sovr.inc/login \u2551\n\u2551 Then get a valid key: https://sovr.inc/dashboard/api-keys \u2551\n\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\n"
4706
+ );
4707
+ }
4708
+ } else if (res.status === 401 || res.status === 403) {
4709
+ console.error(
4710
+ `[SOVR ENGINE] Login validation failed (HTTP ${res.status}). API key may be invalid or expired.`
4711
+ );
4712
+ }
4713
+ } catch {
4714
+ }
4715
+ }
4716
+ /** Get login validation status */
4717
+ get loginValidated() {
4718
+ return this._loginValidated;
4719
+ }
4720
+ // ============================================================================
4721
+ // v4.0.0: BillingReporter — 7 event types, batch flush, quota check
4722
+ // ============================================================================
4723
+ /**
4724
+ * Record a billing event into the buffer.
4725
+ * Fire-and-forget — never blocks the main request flow.
4726
+ */
4727
+ recordBillingEvent(event_type, action, resource, verdict, metadata) {
4728
+ if (!this._billingEnabled) return;
4729
+ this._billingBuffer.push({
4730
+ event_type,
4731
+ action,
4732
+ resource,
4733
+ verdict,
4734
+ api_key: this._apiKey,
4735
+ timestamp: Date.now(),
4736
+ metadata
4737
+ });
4738
+ this._billingStats.byType[event_type] = (this._billingStats.byType[event_type] || 0) + 1;
4739
+ if (this._billingBuffer.length >= this._billingBufferMax) {
4740
+ this._flushBillingBuffer().catch(() => {
4741
+ });
4742
+ }
4743
+ }
4744
+ /**
4745
+ * Flush billing buffer to the metering endpoint.
4746
+ * Batch POST — fire-and-forget with re-queue on failure.
4747
+ */
4748
+ async _flushBillingBuffer() {
4749
+ if (this._billingBuffer.length === 0) return;
4750
+ const batch = this._billingBuffer.splice(0, this._billingBufferMax);
4751
+ try {
4752
+ const response = await globalThis.fetch(this._billingEndpoint, {
4753
+ method: "POST",
4754
+ headers: {
4755
+ "Content-Type": "application/json",
4756
+ "Authorization": `Bearer ${this._apiKey}`,
4757
+ "X-SOVR-Source": "engine",
4758
+ "X-SOVR-Version": ENGINE_VERSION
4759
+ },
4760
+ body: JSON.stringify({ events: batch }),
4761
+ signal: AbortSignal.timeout(5e3)
4762
+ });
4763
+ if (response.ok) {
4764
+ this._billingStats.eventsReported += batch.length;
4765
+ } else {
4766
+ throw new Error(`HTTP ${response.status}`);
4767
+ }
4768
+ } catch {
4769
+ if (this._billingBuffer.length < this._billingBufferMax * 2) {
4770
+ this._billingBuffer.unshift(...batch);
4771
+ } else {
4772
+ this._billingStats.eventsDropped += batch.length;
4773
+ }
4774
+ }
4775
+ }
4776
+ /**
4777
+ * Classify an evaluate() call into the appropriate billing event type.
4778
+ * Key pricing principle: "放行的不可逆动作" is the highest-price tax base.
4779
+ */
4780
+ _classifyBillingEvent(action, verdict) {
4781
+ if (verdict === "deny" || verdict === "block") {
4782
+ return "gate.block";
4783
+ }
4784
+ if ((verdict === "allow" || verdict === "escalate") && IRREVERSIBLE_ACTION_REGEX.test(action)) {
4785
+ return "irreversible.allowed";
4786
+ }
4787
+ return "gate.check";
4788
+ }
4789
+ /** Get billing statistics */
4790
+ get billingStats() {
4791
+ return {
4792
+ ...this._billingStats,
4793
+ bufferSize: this._billingBuffer.length
4794
+ };
4795
+ }
4796
+ /**
4797
+ * Flush remaining billing events and stop the timer.
4798
+ * Call this before process exit for clean shutdown.
4799
+ */
4800
+ async shutdown() {
4801
+ if (this._billingFlushTimer) {
4802
+ clearInterval(this._billingFlushTimer);
4803
+ this._billingFlushTimer = null;
4804
+ }
4805
+ await this._flushBillingBuffer().catch(() => {
4806
+ });
4807
+ }
4640
4808
  /** Set the current tier (e.g., after API key verification) */
4641
4809
  setTier(tier) {
4642
4810
  this._tier = tier;
@@ -4748,6 +4916,14 @@ var PolicyEngine = class {
4748
4916
  Promise.resolve(this.onAudit(event)).catch(() => {
4749
4917
  });
4750
4918
  }
4919
+ const billingType = this._classifyBillingEvent(request.action, verdict);
4920
+ this.recordBillingEvent(billingType, request.action, request.resource, verdict, {
4921
+ risk_score: riskScore,
4922
+ risk_level: riskLevel,
4923
+ decision_id: decisionId,
4924
+ channel: request.channel,
4925
+ matched_rules: matchedRules.length
4926
+ });
4751
4927
  if (this._tier === "free") {
4752
4928
  return {
4753
4929
  ...result,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sovr/engine",
3
- "version": "3.7.0",
3
+ "version": "4.0.0",
4
4
  "description": "Unified Policy Engine for SOVR — the single decision plane for all proxy channels",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",