@derwinjs/db 0.7.0 → 0.8.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.
Files changed (41) hide show
  1. package/dist/budget-gate.d.ts +43 -0
  2. package/dist/budget-gate.d.ts.map +1 -0
  3. package/dist/budget-gate.js +110 -0
  4. package/dist/budget-gate.js.map +1 -0
  5. package/dist/classification-override-store.d.ts +24 -0
  6. package/dist/classification-override-store.d.ts.map +1 -0
  7. package/dist/classification-override-store.js +131 -0
  8. package/dist/classification-override-store.js.map +1 -0
  9. package/dist/freeze-window-evaluator.d.ts +62 -0
  10. package/dist/freeze-window-evaluator.d.ts.map +1 -0
  11. package/dist/freeze-window-evaluator.js +236 -0
  12. package/dist/freeze-window-evaluator.js.map +1 -0
  13. package/dist/index.d.ts +6 -0
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +6 -0
  16. package/dist/index.js.map +1 -1
  17. package/dist/kill-switch-evaluator.d.ts +68 -0
  18. package/dist/kill-switch-evaluator.d.ts.map +1 -0
  19. package/dist/kill-switch-evaluator.js +389 -0
  20. package/dist/kill-switch-evaluator.js.map +1 -0
  21. package/dist/path-tier-resolver.d.ts +47 -0
  22. package/dist/path-tier-resolver.d.ts.map +1 -0
  23. package/dist/path-tier-resolver.js +177 -0
  24. package/dist/path-tier-resolver.js.map +1 -0
  25. package/dist/trust-threshold-config-store.d.ts +20 -0
  26. package/dist/trust-threshold-config-store.d.ts.map +1 -0
  27. package/dist/trust-threshold-config-store.js +88 -0
  28. package/dist/trust-threshold-config-store.js.map +1 -0
  29. package/package.json +3 -3
  30. package/prisma/migrations/20260507120000_sprint8_policy_governance/migration.sql +58 -0
  31. package/prisma/migrations/20260507120100_sprint8_phase2_thresholds_and_freeze/migration.sql +33 -0
  32. package/prisma/migrations/20260507120200_sprint8_phase3_budget_cap/migration.sql +21 -0
  33. package/prisma/migrations/20260507120300_sprint8_phase4_kill_switches/migration.sql +74 -0
  34. package/prisma/schema.prisma +183 -11
  35. package/prisma-client/edge.js +96 -19
  36. package/prisma-client/index-browser.js +93 -16
  37. package/prisma-client/index.d.ts +10997 -3426
  38. package/prisma-client/index.js +96 -19
  39. package/prisma-client/package.json +1 -1
  40. package/prisma-client/schema.prisma +183 -11
  41. package/prisma-client/wasm.js +93 -16
@@ -1,5 +1,5 @@
1
1
  {
2
- "name": "prisma-client-066e8161e24d11a80c9958a72d4d5ce33cf4b1ec59b2112c45a8e8419025acf5",
2
+ "name": "prisma-client-80d22168424dade7c0d713042f02aefb7e5dd12207a0e4feb91cb2584021f57a",
3
3
  "main": "index.js",
4
4
  "types": "index.d.ts",
5
5
  "browser": "index-browser.js",
@@ -77,6 +77,17 @@ model Project {
77
77
  dailyDispatchLimit Int @default(50)
78
78
  testCommand String? // shell command for Verify-Pre, default 'pnpm test'
79
79
 
80
+ // Sprint 8 Phase 3 (QAP-084) — per-project monthly auto-fix budget cap +
81
+ // soft-warn percentage. The legacy `monthlyBudgetCents` field above predates
82
+ // the budget-gate work and is kept for back-compat with policy-derived caps;
83
+ // the gate added here reads `monthlyBudgetUsd` (Float USD) for explicit
84
+ // operator-facing budgets and uses `null` to mean NO_CAP. Soft-warn fires
85
+ // at `utilization >= budgetSoftWarnPct` (default 0.8 = 80%); HARD_STOP fires
86
+ // at `utilization >= 1.0` and refuses new auto-fix dispatches. See SDK
87
+ // BudgetGate contract in @derwinjs/sdk for full semantics.
88
+ monthlyBudgetUsd Float? // null = no cap
89
+ budgetSoftWarnPct Float @default(0.8) // soft warn at 80% by default
90
+
80
91
  // GitHub integration (QAP-019C / Group D-1, 2026-05-04).
81
92
  //
82
93
  // `repoFullName` is the canonical "<owner>/<repo>" identifier (e.g.,
@@ -96,18 +107,47 @@ model Project {
96
107
  webhookSecret String?
97
108
  authorModel String? // override Author LLM model (Sprint 3b — claude-sonnet-4-6 default in adapter)
98
109
 
110
+ // Default risk tier when no PathTierRule matches (QAP-080, Sprint 8). Used
111
+ // by PathTierResolver.resolveTier() as the fallback. LOW chosen as the
112
+ // safe-by-default starting point — operators bump it via the policy editor
113
+ // (Sprint 9 / QAP-088) once the project has trust history.
114
+ defaultTier RiskTier @default(LOW)
115
+
116
+ // Per-tier minimum trustPercent for auto-fix dispatch (QAP-082, Sprint 8
117
+ // Phase 2). JSON shape: { low: number, medium: number, high: number } —
118
+ // matches the SDK's TrustThresholdConfig. Null → use DEFAULT_TRUST_THRESHOLDS
119
+ // ({ low: 60, medium: 80, high: 95 }). NEVER tier always blocks dispatch
120
+ // and is not represented in the JSON.
121
+ trustThresholds Json?
122
+
123
+ // Per-project kill-switch threshold overrides (QAP-085..087, Sprint 8
124
+ // Phase 4). JSON shape: {
125
+ // successRateDropPct?: number, // QAP-085 — < ratio trips
126
+ // successRateMinSample?: number, // QAP-085 — min total attempts
127
+ // consecutiveFailureN?: number, // QAP-086 — N in a row trips
128
+ // consecutiveFailureWindowHours?: number, // QAP-086 — window
129
+ // regressionCascadeN?: number, // QAP-087 — platform-wide N
130
+ // regressionCascadeWindowHours?: number, // QAP-087 — window
131
+ // }.
132
+ // Null → use DEFAULT_THRESHOLDS in createPrismaKillSwitchEvaluator.
133
+ killSwitchConfig Json?
134
+
99
135
  // Relations
100
- profile ProjectProfile?
101
- runs QARun[]
102
- tickets QATicket[]
103
- fixAttempts QAFixAttempt[]
104
- auditArtifacts AuditArtifact[]
105
- policies Policy[]
106
- trustScores ClassificationTrust[]
107
- modeLog ProjectModeLog[]
108
- patterns QAPattern[]
109
- reverts QARevert[]
110
- uniformities QAUniformity[]
136
+ profile ProjectProfile?
137
+ runs QARun[]
138
+ tickets QATicket[]
139
+ fixAttempts QAFixAttempt[]
140
+ auditArtifacts AuditArtifact[]
141
+ policies Policy[]
142
+ trustScores ClassificationTrust[]
143
+ modeLog ProjectModeLog[]
144
+ patterns QAPattern[]
145
+ reverts QARevert[]
146
+ uniformities QAUniformity[]
147
+ pathTierRules PathTierRule[]
148
+ classificationOverrides ClassificationOverride[]
149
+ freezeWindows FreezeWindow[]
150
+ killSwitches KillSwitchState[]
111
151
 
112
152
  @@map("projects")
113
153
  @@schema("derwin")
@@ -633,6 +673,138 @@ enum PolicyType {
633
673
  @@schema("derwin")
634
674
  }
635
675
 
676
+ // ─── Sprint 8 (QAP-080..081) — explicit policy tables ────────────────────
677
+ //
678
+ // `Policy.pathRules` and `Policy.classificationOverrides` were JSON columns
679
+ // historically. Sprint 8 promotes them to first-class tables so the
680
+ // operator-facing policy editor (Sprint 9 / QAP-088) can render, reorder,
681
+ // and audit them as discrete rows. The legacy JSON fields stay on Policy
682
+ // to preserve back-compat with QAP-013's createPrismaFixPolicy until
683
+ // Sprint 9 migrates the read path; new writes go to these tables.
684
+
685
+ model PathTierRule {
686
+ id String @id @default(cuid())
687
+ projectId String
688
+ pattern String // glob: '*' = single segment, '**' = cross-segment
689
+ tier RiskTier
690
+ // Lower number = higher precedence. Assigned in-order by setRules.
691
+ priority Int
692
+ reason String?
693
+ createdAt DateTime @default(now())
694
+ updatedAt DateTime @updatedAt
695
+
696
+ project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
697
+
698
+ @@index([projectId, priority])
699
+ @@map("path_tier_rules")
700
+ @@schema("derwin")
701
+ }
702
+
703
+ model ClassificationOverride {
704
+ id String @id @default(cuid())
705
+ projectId String
706
+ classification String // free-form QATicket.classification value (e.g. 'SELECTOR')
707
+ // Surface filter — null means "applies to ALL surfaces" (wildcard).
708
+ surface String?
709
+ overrideMode OverrideMode
710
+ // Non-null ONLY when overrideMode === DOWNGRADE_TIER. Validated at write.
711
+ downgradeTier RiskTier?
712
+ reason String @db.Text
713
+ createdBy String
714
+ createdAt DateTime @default(now())
715
+
716
+ project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
717
+
718
+ @@index([projectId, classification, surface])
719
+ @@map("classification_overrides")
720
+ @@schema("derwin")
721
+ }
722
+
723
+ enum OverrideMode {
724
+ BLOCK_AUTO_FIX
725
+ FORCE_ESCALATION
726
+ DOWNGRADE_TIER
727
+
728
+ @@schema("derwin")
729
+ }
730
+
731
+ // ─── Sprint 8 Phase 2 (QAP-083) — Freeze windows ─────────────────────────
732
+ //
733
+ // Operator-defined recurring time windows during which auto-fix dispatch
734
+ // is partially or fully blocked. Cron-driven (5-field, no seconds): the
735
+ // dispatcher computes the most recent firing time at-or-before `now` and
736
+ // considers the window active if `(now - lastFire) < durationMinutes * 60s`.
737
+ // See FreezeWindowEvaluator contract in @derwinjs/sdk for full semantics.
738
+
739
+ model FreezeWindow {
740
+ id String @id @default(cuid())
741
+ projectId String
742
+ cronExpression String
743
+ durationMinutes Int
744
+ label String
745
+ blocksDispatch Boolean @default(true)
746
+ enabled Boolean @default(true)
747
+ createdAt DateTime @default(now())
748
+
749
+ project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
750
+
751
+ @@index([projectId, enabled])
752
+ @@map("freeze_windows")
753
+ @@schema("derwin")
754
+ }
755
+
756
+ // ─── Sprint 8 Phase 4 (QAP-085..087) — Kill switches ─────────────────────
757
+ //
758
+ // Three independent triggers that halt auto-fix activity when recent
759
+ // telemetry indicates the platform is misbehaving:
760
+ // - SUCCESS_RATE_DROP (QAP-085) → scope CLASSIFICATION (per-(class,surface))
761
+ // - CONSECUTIVE_FAILURE (QAP-086) → scope PROJECT
762
+ // - REGRESSION_CASCADE (QAP-087) → scope PLATFORM (projectId IS NULL)
763
+ //
764
+ // History-preserving — a new trip creates a new row rather than mutating
765
+ // an old one — so the audit trail shows every trip across time. The
766
+ // `engaged` flag flips to false on operator unblock; subsequent re-trips
767
+ // of the same tuple insert another row.
768
+
769
+ model KillSwitchState {
770
+ id String @id @default(cuid())
771
+ projectId String?
772
+ classification String?
773
+ surface String?
774
+ type KillSwitchType
775
+ scope KillSwitchScope
776
+ engaged Boolean @default(true)
777
+ engagedAt DateTime @default(now())
778
+ unblockedAt DateTime?
779
+ unblockedBy String?
780
+ reason String @db.Text
781
+ triggerMetrics Json
782
+ createdAt DateTime @default(now())
783
+
784
+ project Project? @relation(fields: [projectId], references: [id], onDelete: Cascade)
785
+
786
+ @@index([projectId, engaged])
787
+ @@index([type, scope, engaged])
788
+ @@map("kill_switch_states")
789
+ @@schema("derwin")
790
+ }
791
+
792
+ enum KillSwitchType {
793
+ SUCCESS_RATE_DROP
794
+ CONSECUTIVE_FAILURE
795
+ REGRESSION_CASCADE
796
+
797
+ @@schema("derwin")
798
+ }
799
+
800
+ enum KillSwitchScope {
801
+ CLASSIFICATION
802
+ PROJECT
803
+ PLATFORM
804
+
805
+ @@schema("derwin")
806
+ }
807
+
636
808
  model ProjectModeLog {
637
809
  id String @id @default(cuid())
638
810
  projectId String
@@ -135,9 +135,14 @@ exports.Prisma.ProjectScalarFieldEnum = {
135
135
  monthlyBudgetCents: 'monthlyBudgetCents',
136
136
  dailyDispatchLimit: 'dailyDispatchLimit',
137
137
  testCommand: 'testCommand',
138
+ monthlyBudgetUsd: 'monthlyBudgetUsd',
139
+ budgetSoftWarnPct: 'budgetSoftWarnPct',
138
140
  repoFullName: 'repoFullName',
139
141
  webhookSecret: 'webhookSecret',
140
- authorModel: 'authorModel'
142
+ authorModel: 'authorModel',
143
+ defaultTier: 'defaultTier',
144
+ trustThresholds: 'trustThresholds',
145
+ killSwitchConfig: 'killSwitchConfig'
141
146
  };
142
147
 
143
148
  exports.Prisma.ProjectProfileScalarFieldEnum = {
@@ -323,6 +328,56 @@ exports.Prisma.PolicyScalarFieldEnum = {
323
328
  updatedBy: 'updatedBy'
324
329
  };
325
330
 
331
+ exports.Prisma.PathTierRuleScalarFieldEnum = {
332
+ id: 'id',
333
+ projectId: 'projectId',
334
+ pattern: 'pattern',
335
+ tier: 'tier',
336
+ priority: 'priority',
337
+ reason: 'reason',
338
+ createdAt: 'createdAt',
339
+ updatedAt: 'updatedAt'
340
+ };
341
+
342
+ exports.Prisma.ClassificationOverrideScalarFieldEnum = {
343
+ id: 'id',
344
+ projectId: 'projectId',
345
+ classification: 'classification',
346
+ surface: 'surface',
347
+ overrideMode: 'overrideMode',
348
+ downgradeTier: 'downgradeTier',
349
+ reason: 'reason',
350
+ createdBy: 'createdBy',
351
+ createdAt: 'createdAt'
352
+ };
353
+
354
+ exports.Prisma.FreezeWindowScalarFieldEnum = {
355
+ id: 'id',
356
+ projectId: 'projectId',
357
+ cronExpression: 'cronExpression',
358
+ durationMinutes: 'durationMinutes',
359
+ label: 'label',
360
+ blocksDispatch: 'blocksDispatch',
361
+ enabled: 'enabled',
362
+ createdAt: 'createdAt'
363
+ };
364
+
365
+ exports.Prisma.KillSwitchStateScalarFieldEnum = {
366
+ id: 'id',
367
+ projectId: 'projectId',
368
+ classification: 'classification',
369
+ surface: 'surface',
370
+ type: 'type',
371
+ scope: 'scope',
372
+ engaged: 'engaged',
373
+ engagedAt: 'engagedAt',
374
+ unblockedAt: 'unblockedAt',
375
+ unblockedBy: 'unblockedBy',
376
+ reason: 'reason',
377
+ triggerMetrics: 'triggerMetrics',
378
+ createdAt: 'createdAt'
379
+ };
380
+
326
381
  exports.Prisma.ProjectModeLogScalarFieldEnum = {
327
382
  id: 'id',
328
383
  projectId: 'projectId',
@@ -400,12 +455,12 @@ exports.Prisma.SortOrder = {
400
455
  desc: 'desc'
401
456
  };
402
457
 
403
- exports.Prisma.JsonNullValueInput = {
458
+ exports.Prisma.NullableJsonNullValueInput = {
459
+ DbNull: Prisma.DbNull,
404
460
  JsonNull: Prisma.JsonNull
405
461
  };
406
462
 
407
- exports.Prisma.NullableJsonNullValueInput = {
408
- DbNull: Prisma.DbNull,
463
+ exports.Prisma.JsonNullValueInput = {
409
464
  JsonNull: Prisma.JsonNull
410
465
  };
411
466
 
@@ -414,16 +469,16 @@ exports.Prisma.QueryMode = {
414
469
  insensitive: 'insensitive'
415
470
  };
416
471
 
417
- exports.Prisma.NullsOrder = {
418
- first: 'first',
419
- last: 'last'
420
- };
421
-
422
472
  exports.Prisma.JsonNullValueFilter = {
423
473
  DbNull: Prisma.DbNull,
424
474
  JsonNull: Prisma.JsonNull,
425
475
  AnyNull: Prisma.AnyNull
426
476
  };
477
+
478
+ exports.Prisma.NullsOrder = {
479
+ first: 'first',
480
+ last: 'last'
481
+ };
427
482
  exports.ProjectType = exports.$Enums.ProjectType = {
428
483
  SAAS: 'SAAS',
429
484
  ECOMMERCE: 'ECOMMERCE',
@@ -441,6 +496,13 @@ exports.ProjectMode = exports.$Enums.ProjectMode = {
441
496
  AUTO: 'AUTO'
442
497
  };
443
498
 
499
+ exports.RiskTier = exports.$Enums.RiskTier = {
500
+ LOW: 'LOW',
501
+ MEDIUM: 'MEDIUM',
502
+ HIGH: 'HIGH',
503
+ NEVER: 'NEVER'
504
+ };
505
+
444
506
  exports.RunTrigger = exports.$Enums.RunTrigger = {
445
507
  CRON: 'CRON',
446
508
  OPERATOR_ON_DEMAND: 'OPERATOR_ON_DEMAND',
@@ -474,13 +536,6 @@ exports.Severity = exports.$Enums.Severity = {
474
536
  LOW: 'LOW'
475
537
  };
476
538
 
477
- exports.RiskTier = exports.$Enums.RiskTier = {
478
- LOW: 'LOW',
479
- MEDIUM: 'MEDIUM',
480
- HIGH: 'HIGH',
481
- NEVER: 'NEVER'
482
- };
483
-
484
539
  exports.TicketStatus = exports.$Enums.TicketStatus = {
485
540
  OPEN: 'OPEN',
486
541
  INVESTIGATING: 'INVESTIGATING',
@@ -543,6 +598,24 @@ exports.PolicyType = exports.$Enums.PolicyType = {
543
598
  ESCALATION: 'ESCALATION'
544
599
  };
545
600
 
601
+ exports.OverrideMode = exports.$Enums.OverrideMode = {
602
+ BLOCK_AUTO_FIX: 'BLOCK_AUTO_FIX',
603
+ FORCE_ESCALATION: 'FORCE_ESCALATION',
604
+ DOWNGRADE_TIER: 'DOWNGRADE_TIER'
605
+ };
606
+
607
+ exports.KillSwitchType = exports.$Enums.KillSwitchType = {
608
+ SUCCESS_RATE_DROP: 'SUCCESS_RATE_DROP',
609
+ CONSECUTIVE_FAILURE: 'CONSECUTIVE_FAILURE',
610
+ REGRESSION_CASCADE: 'REGRESSION_CASCADE'
611
+ };
612
+
613
+ exports.KillSwitchScope = exports.$Enums.KillSwitchScope = {
614
+ CLASSIFICATION: 'CLASSIFICATION',
615
+ PROJECT: 'PROJECT',
616
+ PLATFORM: 'PLATFORM'
617
+ };
618
+
546
619
  exports.QAFailureClass = exports.$Enums.QAFailureClass = {
547
620
  SELECTOR: 'SELECTOR',
548
621
  TIMING: 'TIMING',
@@ -577,6 +650,10 @@ exports.Prisma.ModelName = {
577
650
  RAGCorpus: 'RAGCorpus',
578
651
  AuditArtifact: 'AuditArtifact',
579
652
  Policy: 'Policy',
653
+ PathTierRule: 'PathTierRule',
654
+ ClassificationOverride: 'ClassificationOverride',
655
+ FreezeWindow: 'FreezeWindow',
656
+ KillSwitchState: 'KillSwitchState',
580
657
  ProjectModeLog: 'ProjectModeLog',
581
658
  SpendLedger: 'SpendLedger',
582
659
  QAPattern: 'QAPattern',