@probelabs/visor 0.1.130 → 0.1.131

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 (134) hide show
  1. package/README.md +7 -0
  2. package/defaults/visor.yaml +5 -2
  3. package/dist/ai-review-service.d.ts +2 -0
  4. package/dist/ai-review-service.d.ts.map +1 -1
  5. package/dist/cli-main.d.ts.map +1 -1
  6. package/dist/cli.d.ts.map +1 -1
  7. package/dist/config/cli-handler.d.ts +5 -0
  8. package/dist/config/cli-handler.d.ts.map +1 -0
  9. package/dist/config/config-reloader.d.ts +24 -0
  10. package/dist/config/config-reloader.d.ts.map +1 -0
  11. package/dist/config/config-snapshot-store.d.ts +21 -0
  12. package/dist/config/config-snapshot-store.d.ts.map +1 -0
  13. package/dist/config/config-watcher.d.ts +19 -0
  14. package/dist/config/config-watcher.d.ts.map +1 -0
  15. package/dist/config/types.d.ts +16 -0
  16. package/dist/config/types.d.ts.map +1 -0
  17. package/dist/defaults/visor.yaml +5 -2
  18. package/dist/docs/ai-configuration.md +139 -0
  19. package/dist/docs/ai-custom-tools.md +30 -0
  20. package/dist/docs/capacity-planning.md +359 -0
  21. package/dist/docs/commands.md +35 -0
  22. package/dist/docs/database-operations.md +487 -0
  23. package/dist/docs/index.md +6 -1
  24. package/dist/docs/licensing.md +372 -0
  25. package/dist/docs/production-deployment.md +583 -0
  26. package/dist/examples/ai-with-bash.yaml +17 -0
  27. package/dist/generated/config-schema.d.ts +4 -0
  28. package/dist/generated/config-schema.d.ts.map +1 -1
  29. package/dist/index.js +9945 -10907
  30. package/dist/liquid-extensions.d.ts +7 -0
  31. package/dist/liquid-extensions.d.ts.map +1 -1
  32. package/dist/output/traces/{run-2026-02-11T16-20-59-999Z.ndjson → run-2026-02-15T19-14-20-379Z.ndjson} +84 -84
  33. package/dist/{traces/run-2026-02-11T16-21-47-711Z.ndjson → output/traces/run-2026-02-15T19-15-09-410Z.ndjson} +1019 -1019
  34. package/dist/providers/ai-check-provider.d.ts +5 -0
  35. package/dist/providers/ai-check-provider.d.ts.map +1 -1
  36. package/dist/providers/command-check-provider.d.ts.map +1 -1
  37. package/dist/providers/workflow-check-provider.d.ts.map +1 -1
  38. package/dist/scheduler/schedule-tool.d.ts.map +1 -1
  39. package/dist/sdk/{check-provider-registry-PANIXYRB.mjs → check-provider-registry-AAPPJ4CP.mjs} +7 -7
  40. package/dist/sdk/{check-provider-registry-M3Y6JMTW.mjs → check-provider-registry-S7BMQ2FC.mjs} +7 -7
  41. package/dist/sdk/check-provider-registry-ZOLEYDKM.mjs +28 -0
  42. package/dist/sdk/{chunk-VMLORODQ.mjs → chunk-2GCSK3PD.mjs} +4 -4
  43. package/dist/sdk/{chunk-EUUAQBTW.mjs → chunk-6ZZ4DPAA.mjs} +240 -48
  44. package/dist/sdk/chunk-6ZZ4DPAA.mjs.map +1 -0
  45. package/dist/sdk/{chunk-HOKQOO3G.mjs → chunk-EBTD2D4L.mjs} +2 -2
  46. package/dist/sdk/chunk-LDFUW34H.mjs +39912 -0
  47. package/dist/sdk/chunk-LDFUW34H.mjs.map +1 -0
  48. package/dist/sdk/{chunk-UCNT3PDT.mjs → chunk-LQ5B4T6L.mjs} +5 -1
  49. package/dist/sdk/chunk-LQ5B4T6L.mjs.map +1 -0
  50. package/dist/sdk/{chunk-S6CD7GFM.mjs → chunk-MQ57AB4U.mjs} +211 -35
  51. package/dist/sdk/chunk-MQ57AB4U.mjs.map +1 -0
  52. package/dist/sdk/chunk-N4I6ZDCJ.mjs +436 -0
  53. package/dist/sdk/chunk-N4I6ZDCJ.mjs.map +1 -0
  54. package/dist/sdk/chunk-OMFPM576.mjs +739 -0
  55. package/dist/sdk/chunk-OMFPM576.mjs.map +1 -0
  56. package/dist/sdk/chunk-RI77TA6V.mjs +436 -0
  57. package/dist/sdk/chunk-RI77TA6V.mjs.map +1 -0
  58. package/dist/sdk/chunk-VO4N6TEL.mjs +1502 -0
  59. package/dist/sdk/chunk-VO4N6TEL.mjs.map +1 -0
  60. package/dist/sdk/{chunk-V2IV3ILA.mjs → chunk-XJQKTK6V.mjs} +31 -5
  61. package/dist/sdk/chunk-XJQKTK6V.mjs.map +1 -0
  62. package/dist/sdk/{config-OGOS4ZU4.mjs → config-4EG7IQIU.mjs} +2 -2
  63. package/dist/sdk/{failure-condition-evaluator-HC3M5377.mjs → failure-condition-evaluator-GLHZZF47.mjs} +3 -3
  64. package/dist/sdk/failure-condition-evaluator-KN55WXRO.mjs +17 -0
  65. package/dist/sdk/{github-frontend-E2KJSC3Y.mjs → github-frontend-F4TE2JY7.mjs} +3 -3
  66. package/dist/sdk/github-frontend-HCOKL53D.mjs +1356 -0
  67. package/dist/sdk/github-frontend-HCOKL53D.mjs.map +1 -0
  68. package/dist/sdk/{host-EE6EJ2FM.mjs → host-SAT6RHDX.mjs} +2 -2
  69. package/dist/sdk/host-VA3ET7N6.mjs +63 -0
  70. package/dist/sdk/host-VA3ET7N6.mjs.map +1 -0
  71. package/dist/sdk/{liquid-extensions-E4EUOCES.mjs → liquid-extensions-YDIIH33Q.mjs} +2 -2
  72. package/dist/sdk/{routing-OZQWAGAI.mjs → routing-KFYQGOYU.mjs} +5 -5
  73. package/dist/sdk/routing-OXQKETSA.mjs +25 -0
  74. package/dist/sdk/{schedule-tool-handler-IEB2VS7O.mjs → schedule-tool-handler-G353DHS6.mjs} +7 -7
  75. package/dist/sdk/{schedule-tool-handler-B7TMSG6A.mjs → schedule-tool-handler-OQF57URO.mjs} +7 -7
  76. package/dist/sdk/schedule-tool-handler-PJVKWSYX.mjs +38 -0
  77. package/dist/sdk/schedule-tool-handler-PJVKWSYX.mjs.map +1 -0
  78. package/dist/sdk/sdk.d.mts +15 -0
  79. package/dist/sdk/sdk.d.ts +15 -0
  80. package/dist/sdk/sdk.js +621 -183
  81. package/dist/sdk/sdk.js.map +1 -1
  82. package/dist/sdk/sdk.mjs +6 -6
  83. package/dist/sdk/{trace-helpers-PP3YHTAM.mjs → trace-helpers-LOPBHYYX.mjs} +4 -2
  84. package/dist/sdk/trace-helpers-LOPBHYYX.mjs.map +1 -0
  85. package/dist/sdk/trace-helpers-R2ETIEC2.mjs +25 -0
  86. package/dist/sdk/trace-helpers-R2ETIEC2.mjs.map +1 -0
  87. package/dist/sdk/{workflow-check-provider-2ET3SFZH.mjs → workflow-check-provider-57KAR4Y4.mjs} +7 -7
  88. package/dist/sdk/workflow-check-provider-57KAR4Y4.mjs.map +1 -0
  89. package/dist/sdk/{workflow-check-provider-HB4XTD4Z.mjs → workflow-check-provider-LRWD52WN.mjs} +7 -7
  90. package/dist/sdk/workflow-check-provider-LRWD52WN.mjs.map +1 -0
  91. package/dist/sdk/workflow-check-provider-N2DRFQDB.mjs +28 -0
  92. package/dist/sdk/workflow-check-provider-N2DRFQDB.mjs.map +1 -0
  93. package/dist/slack/socket-runner.d.ts.map +1 -1
  94. package/dist/state-machine/context/build-engine-context.d.ts.map +1 -1
  95. package/dist/state-machine/runner.d.ts.map +1 -1
  96. package/dist/state-machine/states/completed.d.ts.map +1 -1
  97. package/dist/telemetry/trace-helpers.d.ts +5 -0
  98. package/dist/telemetry/trace-helpers.d.ts.map +1 -1
  99. package/dist/test-runner/evaluators.d.ts.map +1 -1
  100. package/dist/test-runner/index.d.ts +7 -0
  101. package/dist/test-runner/index.d.ts.map +1 -1
  102. package/dist/test-runner/validator.d.ts.map +1 -1
  103. package/dist/traces/{run-2026-02-11T16-20-59-999Z.ndjson → run-2026-02-15T19-14-20-379Z.ndjson} +84 -84
  104. package/dist/{output/traces/run-2026-02-11T16-21-47-711Z.ndjson → traces/run-2026-02-15T19-15-09-410Z.ndjson} +1019 -1019
  105. package/dist/tui/chat-runner.d.ts.map +1 -1
  106. package/dist/types/cli.d.ts +2 -0
  107. package/dist/types/cli.d.ts.map +1 -1
  108. package/dist/types/config.d.ts +15 -0
  109. package/dist/types/config.d.ts.map +1 -1
  110. package/dist/types/engine.d.ts +2 -0
  111. package/dist/types/engine.d.ts.map +1 -1
  112. package/package.json +3 -3
  113. package/defaults/.visor.yaml +0 -420
  114. package/dist/sdk/chunk-EUUAQBTW.mjs.map +0 -1
  115. package/dist/sdk/chunk-S6CD7GFM.mjs.map +0 -1
  116. package/dist/sdk/chunk-UCNT3PDT.mjs.map +0 -1
  117. package/dist/sdk/chunk-V2IV3ILA.mjs.map +0 -1
  118. package/dist/sdk/chunk-YJRBN3XS.mjs +0 -217
  119. package/dist/sdk/chunk-YJRBN3XS.mjs.map +0 -1
  120. /package/dist/sdk/{check-provider-registry-M3Y6JMTW.mjs.map → check-provider-registry-AAPPJ4CP.mjs.map} +0 -0
  121. /package/dist/sdk/{check-provider-registry-PANIXYRB.mjs.map → check-provider-registry-S7BMQ2FC.mjs.map} +0 -0
  122. /package/dist/sdk/{config-OGOS4ZU4.mjs.map → check-provider-registry-ZOLEYDKM.mjs.map} +0 -0
  123. /package/dist/sdk/{chunk-VMLORODQ.mjs.map → chunk-2GCSK3PD.mjs.map} +0 -0
  124. /package/dist/sdk/{chunk-HOKQOO3G.mjs.map → chunk-EBTD2D4L.mjs.map} +0 -0
  125. /package/dist/sdk/{failure-condition-evaluator-HC3M5377.mjs.map → config-4EG7IQIU.mjs.map} +0 -0
  126. /package/dist/sdk/{liquid-extensions-E4EUOCES.mjs.map → failure-condition-evaluator-GLHZZF47.mjs.map} +0 -0
  127. /package/dist/sdk/{routing-OZQWAGAI.mjs.map → failure-condition-evaluator-KN55WXRO.mjs.map} +0 -0
  128. /package/dist/sdk/{github-frontend-E2KJSC3Y.mjs.map → github-frontend-F4TE2JY7.mjs.map} +0 -0
  129. /package/dist/sdk/{host-EE6EJ2FM.mjs.map → host-SAT6RHDX.mjs.map} +0 -0
  130. /package/dist/sdk/{schedule-tool-handler-B7TMSG6A.mjs.map → liquid-extensions-YDIIH33Q.mjs.map} +0 -0
  131. /package/dist/sdk/{schedule-tool-handler-IEB2VS7O.mjs.map → routing-KFYQGOYU.mjs.map} +0 -0
  132. /package/dist/sdk/{trace-helpers-PP3YHTAM.mjs.map → routing-OXQKETSA.mjs.map} +0 -0
  133. /package/dist/sdk/{workflow-check-provider-2ET3SFZH.mjs.map → schedule-tool-handler-G353DHS6.mjs.map} +0 -0
  134. /package/dist/sdk/{workflow-check-provider-HB4XTD4Z.mjs.map → schedule-tool-handler-OQF57URO.mjs.map} +0 -0
@@ -0,0 +1,372 @@
1
+ # Enterprise Licensing
2
+
3
+ > **Enterprise Edition feature.** Contact **hello@probelabs.com** for licensing.
4
+
5
+ This guide covers obtaining, installing, managing, and troubleshooting Visor Enterprise Edition licenses.
6
+
7
+ ---
8
+
9
+ ## Table of Contents
10
+
11
+ - [Overview](#overview)
12
+ - [Licensed Features](#licensed-features)
13
+ - [Obtaining a License](#obtaining-a-license)
14
+ - [Installing the License](#installing-the-license)
15
+ - [License Lookup Order](#license-lookup-order)
16
+ - [License Format](#license-format)
17
+ - [Grace Period](#grace-period)
18
+ - [Verifying Your License](#verifying-your-license)
19
+ - [Renewal](#renewal)
20
+ - [Rotation and Revocation](#rotation-and-revocation)
21
+ - [CI/CD Integration](#cicd-integration)
22
+ - [Air-Gapped Environments](#air-gapped-environments)
23
+ - [FAQ](#faq)
24
+ - [Troubleshooting](#troubleshooting)
25
+
26
+ ---
27
+
28
+ ## Overview
29
+
30
+ Visor Enterprise Edition (EE) is a superset of the open-source version. All OSS functionality works identically without a license. Enterprise features are inert and silently disabled unless a valid license is present.
31
+
32
+ When a license is loaded:
33
+ 1. Visor validates the cryptographic signature (EdDSA / Ed25519).
34
+ 2. Checks the expiration date (with a 72-hour grace period).
35
+ 3. Reads the `features` claim to determine which EE capabilities are active.
36
+ 4. Caches the result for 5 minutes to avoid repeated validation.
37
+
38
+ ---
39
+
40
+ ## Licensed Features
41
+
42
+ | Feature String | Capability | Documentation |
43
+ |---------------|------------|---------------|
44
+ | `policy` | OPA policy engine (check gating, tool access, capability control) | [Enterprise Policy Engine](./enterprise-policy.md) |
45
+ | `scheduler-sql` | PostgreSQL, MySQL, and MSSQL scheduler backends | [Scheduler Storage](./scheduler-storage.md) |
46
+
47
+ Features not listed in the license JWT are disabled. The OSS SQLite scheduler and all other OSS features work without a license.
48
+
49
+ ---
50
+
51
+ ## Obtaining a License
52
+
53
+ ### Trial License
54
+
55
+ Contact **hello@probelabs.com** with:
56
+ - Your organization name
57
+ - Expected number of Visor instances
58
+ - Which features you want to evaluate (`policy`, `scheduler-sql`, or both)
59
+
60
+ Trial licenses are typically issued for 30 days with all features enabled.
61
+
62
+ ### Production License
63
+
64
+ Production licenses are issued per-organization and include:
65
+ - Organization name (`org` claim)
66
+ - Licensed features list
67
+ - Expiration date
68
+ - Unique subject identifier
69
+
70
+ Contact **hello@probelabs.com** or your account representative for production licensing.
71
+
72
+ ---
73
+
74
+ ## Installing the License
75
+
76
+ ### Option 1: Environment Variable (recommended for CI/CD and containers)
77
+
78
+ ```bash
79
+ export VISOR_LICENSE="eyJhbGciOiJFZERTQSIs..."
80
+ ```
81
+
82
+ The value is the raw JWT string (no file path, no prefix).
83
+
84
+ ### Option 2: Environment Variable Pointing to File
85
+
86
+ ```bash
87
+ export VISOR_LICENSE_FILE="/etc/visor/license.jwt"
88
+ ```
89
+
90
+ The file should contain only the raw JWT string.
91
+
92
+ ### Option 3: Project-Level File
93
+
94
+ Place a file named `.visor-license` in your project root (alongside `.visor.yaml`):
95
+
96
+ ```bash
97
+ echo "eyJhbGciOiJFZERTQSIs..." > .visor-license
98
+ ```
99
+
100
+ ### Option 4: User-Level File
101
+
102
+ Place the license in your home config directory:
103
+
104
+ ```bash
105
+ mkdir -p ~/.config/visor
106
+ echo "eyJhbGciOiJFZERTQSIs..." > ~/.config/visor/.visor-license
107
+ ```
108
+
109
+ ---
110
+
111
+ ## License Lookup Order
112
+
113
+ Visor checks for a license in this order, using the first one found:
114
+
115
+ 1. `VISOR_LICENSE` environment variable (raw JWT)
116
+ 2. `VISOR_LICENSE_FILE` environment variable (file path)
117
+ 3. `.visor-license` in the current working directory
118
+ 4. `~/.config/visor/.visor-license` in the user's home directory
119
+
120
+ ---
121
+
122
+ ## License Format
123
+
124
+ Licenses are Ed25519-signed JWTs (EdDSA algorithm) with the following payload:
125
+
126
+ ```json
127
+ {
128
+ "org": "Acme Corp",
129
+ "features": ["policy", "scheduler-sql"],
130
+ "exp": 1740000000,
131
+ "iat": 1708464000,
132
+ "sub": "org-acme-prod"
133
+ }
134
+ ```
135
+
136
+ | Claim | Type | Description |
137
+ |-------|------|-------------|
138
+ | `org` | string | Organization name |
139
+ | `features` | string[] | Licensed feature strings |
140
+ | `exp` | number | Expiration timestamp (Unix seconds) |
141
+ | `iat` | number | Issue timestamp (Unix seconds) |
142
+ | `sub` | string | Subject identifier (unique per license) |
143
+
144
+ The signature is verified against Visor's embedded public key. Licenses cannot be forged or modified.
145
+
146
+ ---
147
+
148
+ ## Grace Period
149
+
150
+ When a license expires, Visor provides a **72-hour grace period**:
151
+
152
+ | State | Behavior |
153
+ |-------|----------|
154
+ | **Valid** | All licensed features work normally |
155
+ | **Expired < 72 hours** | Features continue working; warning logged at startup |
156
+ | **Expired > 72 hours** | Enterprise features silently disable; OSS features unaffected |
157
+
158
+ During the grace period, Visor logs:
159
+
160
+ ```
161
+ [warn] Visor EE license expired. Grace period active (expires in Xh). Please renew.
162
+ ```
163
+
164
+ ---
165
+
166
+ ## Verifying Your License
167
+
168
+ ### Check at Startup
169
+
170
+ Run Visor with `--debug` to see license validation output:
171
+
172
+ ```bash
173
+ visor --debug --config .visor.yaml --check all 2>&1 | grep -i license
174
+ ```
175
+
176
+ With a valid license:
177
+ ```
178
+ [debug] [License] Valid license for "Acme Corp" (features: policy, scheduler-sql, expires: 2026-06-01)
179
+ ```
180
+
181
+ Without a license:
182
+ ```
183
+ [debug] [License] No license found. Enterprise features disabled.
184
+ ```
185
+
186
+ ### Check Feature Availability
187
+
188
+ If a feature is used without a license, Visor logs a debug message and falls back to OSS behavior:
189
+
190
+ ```
191
+ [debug] [Policy] Policy engine disabled (no license or feature not licensed)
192
+ ```
193
+
194
+ ---
195
+
196
+ ## Renewal
197
+
198
+ ### Before Expiration
199
+
200
+ 1. Contact **hello@probelabs.com** or your account representative.
201
+ 2. Provide your current `sub` claim (from your existing license) for continuity.
202
+ 3. Receive a new JWT with an updated `exp` claim.
203
+ 4. Replace the old license using any of the [installation methods](#installing-the-license).
204
+ 5. Visor picks up the new license within 5 minutes (cache TTL) or on next restart.
205
+
206
+ ### After Expiration (within grace period)
207
+
208
+ Same process as above. Enterprise features continue working during the 72-hour grace period.
209
+
210
+ ### After Grace Period
211
+
212
+ Enterprise features are disabled but **no data is lost**. Once a new license is installed:
213
+ - Policy engine re-enables immediately.
214
+ - SQL scheduler backends reconnect automatically.
215
+ - All previously stored schedules and policies remain intact.
216
+
217
+ ---
218
+
219
+ ## Rotation and Revocation
220
+
221
+ ### Rotating a License
222
+
223
+ To rotate to a new license (e.g., changing features or extending expiration):
224
+
225
+ 1. Obtain the new license JWT.
226
+ 2. Replace the old license (env var, file, or config file).
227
+ 3. Restart Visor or wait up to 5 minutes for cache refresh.
228
+
229
+ Both old and new licenses can coexist briefly during rotation. Visor uses whichever it finds first in the lookup order.
230
+
231
+ ### Revoking a License
232
+
233
+ To immediately revoke enterprise features:
234
+
235
+ ```bash
236
+ # Remove from environment
237
+ unset VISOR_LICENSE
238
+ unset VISOR_LICENSE_FILE
239
+
240
+ # Remove from filesystem
241
+ rm .visor-license
242
+ rm ~/.config/visor/.visor-license
243
+ ```
244
+
245
+ Restart Visor. Enterprise features will be silently disabled.
246
+
247
+ ---
248
+
249
+ ## CI/CD Integration
250
+
251
+ ### GitHub Actions
252
+
253
+ ```yaml
254
+ - name: Run Visor
255
+ env:
256
+ VISOR_LICENSE: ${{ secrets.VISOR_LICENSE }}
257
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
258
+ run: visor --config .visor.yaml --check all
259
+ ```
260
+
261
+ ### GitLab CI
262
+
263
+ ```yaml
264
+ visor:
265
+ image: node:20
266
+ variables:
267
+ VISOR_LICENSE: $VISOR_LICENSE
268
+ script:
269
+ - npm install -g @probelabs/visor@ee
270
+ - visor --config .visor.yaml --check all
271
+ ```
272
+
273
+ ### Jenkins
274
+
275
+ ```groovy
276
+ pipeline {
277
+ environment {
278
+ VISOR_LICENSE = credentials('visor-license')
279
+ }
280
+ stages {
281
+ stage('Review') {
282
+ steps {
283
+ sh 'visor --config .visor.yaml --check all'
284
+ }
285
+ }
286
+ }
287
+ }
288
+ ```
289
+
290
+ ### Kubernetes Secret
291
+
292
+ ```yaml
293
+ apiVersion: v1
294
+ kind: Secret
295
+ metadata:
296
+ name: visor-license
297
+ type: Opaque
298
+ stringData:
299
+ VISOR_LICENSE: "eyJhbGciOiJFZERTQSIs..."
300
+ ```
301
+
302
+ Reference in deployment:
303
+
304
+ ```yaml
305
+ envFrom:
306
+ - secretRef:
307
+ name: visor-license
308
+ ```
309
+
310
+ ---
311
+
312
+ ## Air-Gapped Environments
313
+
314
+ Visor licenses are validated entirely offline. No network calls are made during license validation. This makes Visor EE fully compatible with air-gapped and restricted network environments.
315
+
316
+ Requirements:
317
+ - The license JWT must be available via one of the [lookup methods](#license-lookup-order).
318
+ - The EE npm package (`@probelabs/visor@ee`) must be installed from a local registry or tarball.
319
+ - For OPA policies, pre-compile `.rego` to `.wasm` externally and reference the `.wasm` file directly.
320
+
321
+ ---
322
+
323
+ ## FAQ
324
+
325
+ **Q: What happens if I remove the license?**
326
+ A: Enterprise features silently disable. OSS features continue working. No data is lost. Schedules stored in PostgreSQL remain accessible once a license is restored.
327
+
328
+ **Q: Can I use the same license on multiple machines?**
329
+ A: Yes. Licenses are not node-locked. They are valid for the licensed organization across any number of instances.
330
+
331
+ **Q: Does Visor phone home?**
332
+ A: No. License validation is entirely offline using cryptographic signature verification. No telemetry or usage data is sent to Probelabs for licensing purposes.
333
+
334
+ **Q: What happens during a deploy if the license secret isn't set?**
335
+ A: Visor starts normally with OSS-only features. Enterprise features are disabled until the license is available.
336
+
337
+ **Q: Can I downgrade from EE to OSS?**
338
+ A: Yes. Replace `@probelabs/visor@ee` with `@probelabs/visor`. Remove the license. If you were using PostgreSQL, switch the scheduler config back to `driver: sqlite` and Visor will use the local SQLite database.
339
+
340
+ ---
341
+
342
+ ## Troubleshooting
343
+
344
+ ### "No license found"
345
+
346
+ - Check the [lookup order](#license-lookup-order) and verify the license is accessible.
347
+ - For containers: ensure the env var or file mount is correctly configured.
348
+ - Run `visor --debug` to see which paths Visor checks.
349
+
350
+ ### "License signature invalid"
351
+
352
+ - Ensure the JWT is not truncated or modified.
353
+ - Verify you're using a license issued by Probelabs (not a self-signed token).
354
+ - Check for trailing whitespace or newlines in the license string.
355
+
356
+ ### "License expired"
357
+
358
+ - Check the `exp` claim: `echo "YOUR_JWT" | cut -d. -f2 | base64 -d 2>/dev/null | jq .exp`
359
+ - Contact **hello@probelabs.com** for renewal.
360
+ - The 72-hour grace period provides time to obtain a new license.
361
+
362
+ ### "Feature not licensed"
363
+
364
+ - Check your license's `features` claim matches the feature you're using.
365
+ - `policy` is required for OPA policy engine.
366
+ - `scheduler-sql` is required for PostgreSQL/MySQL/MSSQL backends.
367
+
368
+ ### License Not Picked Up After Update
369
+
370
+ - Visor caches license validation for 5 minutes. Wait or restart.
371
+ - If using `VISOR_LICENSE_FILE`, verify the file path hasn't changed.
372
+ - Check file permissions (must be readable by the Visor process).