@voltro/plugin-licensing 0.81.0 → 0.83.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.
@@ -4551,7 +4551,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
4551
4551
  SOFTWARE.
4552
4552
  ```
4553
4553
 
4554
- ## undici@8.10.0
4554
+ ## undici@8.11.2
4555
4555
 
4556
4556
  License: MIT
4557
4557
 
package/dist/index.d.ts CHANGED
@@ -38,10 +38,10 @@ export declare interface LicenseClaims {
38
38
 
39
39
  export declare const LicenseService: Tag<LicenseServiceShape, LicenseServiceShape>;
40
40
 
41
- /** The service handlers can `yield*` to read the current license directly (for
42
- * feature checks beyond billing's metered entitlements). */
43
41
  export declare interface LicenseServiceShape {
44
42
  readonly snapshot: () => LicenseSnapshot | undefined;
43
+ /** Where the installation stands with its license — see {@link LicenseStatus}. */
44
+ readonly status: () => LicenseStatus;
45
45
  readonly limitFor: (tenantId: string | null | undefined, key: string) => number | undefined;
46
46
  readonly hasFeature: (feature: string) => boolean;
47
47
  readonly allowsPlugin: (plugin: string) => boolean;
@@ -62,8 +62,43 @@ export declare interface LicenseSnapshot {
62
62
  /** Whether a plugin is licensed for production use (name without the
63
63
  * `@voltro/plugin-` prefix, e.g. `'storage'`). The "installed ≠ billable" gate. */
64
64
  readonly allowsPlugin: (plugin: string) => boolean;
65
+ /** `active` until `exp`, `grace` while an expired license is still honored,
66
+ * `expired` after — when `limitFor` and the rest go dark. */
67
+ readonly state: () => 'active' | 'grace' | 'expired';
65
68
  }
66
69
 
70
+ /** The service handlers can `yield*` to read the current license directly (for
71
+ * feature checks beyond billing's metered entitlements). */
72
+ /**
73
+ * Where the installation stands with its license, for an operator's screen:
74
+ * `none` — no license configured; `active` / `grace` / `expired` — the
75
+ * installed one, by its expiry and the grace period; `rejected` — the license
76
+ * offered did not verify (a last good one, if any, still reports its own
77
+ * state in `installed`).
78
+ */
79
+ export declare type LicenseStatus = {
80
+ readonly state: 'none';
81
+ } | {
82
+ readonly state: 'active' | 'grace' | 'expired';
83
+ readonly edition: string;
84
+ /** Unix seconds; 0 for a license that does not expire. */
85
+ readonly expiresAt: number;
86
+ /** The tenant a tenant-scoped license applies to. */
87
+ readonly tenant?: string;
88
+ } | {
89
+ readonly state: 'rejected';
90
+ readonly reason: LicenseVerifyError['reason'];
91
+ readonly message: string;
92
+ readonly installed?: {
93
+ readonly state: 'active' | 'grace' | 'expired';
94
+ readonly edition: string;
95
+ readonly expiresAt: number;
96
+ };
97
+ };
98
+
99
+ /** The current {@link LicenseStatus}, read from the in-memory snapshot and the last refusal. */
100
+ export declare const licenseStatus: () => LicenseStatus;
101
+
67
102
  export declare class LicenseVerifyError extends LicenseVerifyError_base<{
68
103
  /** `expired` — past `exp`; `invalid` — bad signature; `key` — unusable public
69
104
  * key; `malformed` — verified but the payload isn't a license. */
package/dist/index.js CHANGED
@@ -56,6 +56,7 @@ var c = class extends e.TaggedError("LicenseVerifyError") {}, l = (e) => typeof
56
56
  let n = new Set(e.features), r = new Set(e.plugins), i = t.graceSeconds ?? 0, a = t.now ?? (() => Date.now() / 1e3), o = () => e.exp <= 0 || a() <= e.exp + i;
57
57
  return {
58
58
  claims: e,
59
+ state: () => e.exp <= 0 || a() <= e.exp ? "active" : o() ? "grace" : "expired",
59
60
  limitFor: (t, n) => {
60
61
  if (!o() || e.tenant !== void 0 && e.tenant !== t) return;
61
62
  let r = e.entitlements[n];
@@ -66,10 +67,29 @@ var c = class extends e.TaggedError("LicenseVerifyError") {}, l = (e) => typeof
66
67
  };
67
68
  }, h, g = (e) => {
68
69
  h = e;
69
- }, _ = () => h, v = (e, n) => t.sync(() => {
70
+ }, _ = () => h, v, y = (e) => {
71
+ v = e;
72
+ }, b = () => v, x = (e, n) => t.sync(() => {
70
73
  let t = _()?.limitFor(e, n);
71
74
  return t === void 0 ? null : t;
72
- }), y = a([{
75
+ }), S = () => {
76
+ let e = _(), t = e === void 0 ? void 0 : {
77
+ state: e.state(),
78
+ edition: e.claims.edition,
79
+ expiresAt: e.claims.exp,
80
+ ...e.claims.tenant === void 0 ? {} : { tenant: e.claims.tenant }
81
+ }, n = b();
82
+ return n === void 0 ? t ?? { state: "none" } : {
83
+ state: "rejected",
84
+ reason: n.reason,
85
+ message: n.message,
86
+ ...t === void 0 ? {} : { installed: {
87
+ state: t.state,
88
+ edition: t.edition,
89
+ expiresAt: t.expiresAt
90
+ } }
91
+ };
92
+ }, C = a([{
73
93
  name: "VOLTRO_LICENSE_PUBLIC_KEY",
74
94
  required: !1,
75
95
  secret: !1,
@@ -79,23 +99,27 @@ var c = class extends e.TaggedError("LicenseVerifyError") {}, l = (e) => typeof
79
99
  required: !1,
80
100
  secret: !1,
81
101
  description: "The signed EdDSA license token, verified offline at boot."
82
- }]), { Tag: b, Live: x } = r("@voltro/plugin-licensing/LicenseService", {
102
+ }]), { Tag: w, Live: T } = r("@voltro/plugin-licensing/LicenseService", {
83
103
  snapshot: () => _(),
104
+ status: () => S(),
84
105
  limitFor: (e, t) => _()?.limitFor(e, t),
85
106
  hasFeature: (e) => _()?.hasFeature(e) ?? !1,
86
107
  allowsPlugin: (e) => _()?.allowsPlugin(e) ?? !1,
87
108
  edition: () => _()?.claims.edition
88
- }), S = class extends e.TaggedError("PluginNotLicensed") {}, C = (e) => _()?.allowsPlugin(e) ?? !1, w = (e) => C(e) ? t.void : t.fail(new S({ plugin: e })), T = (e = {}) => {
89
- let r = y.read("VOLTRO_LICENSE_PUBLIC_KEY", e.publicKey), a = y.read("VOLTRO_LICENSE_KEY", e.licenseKey), o = e.graceSeconds ?? 0, s = e.refreshMs ?? 9e5, c, l = (e, n) => p(e, n).pipe(t.match({
109
+ }), E = class extends e.TaggedError("PluginNotLicensed") {}, D = (e) => _()?.allowsPlugin(e) ?? !1, O = (e) => D(e) ? t.void : t.fail(new E({ plugin: e })), k = (e = {}) => {
110
+ let r = C.read("VOLTRO_LICENSE_PUBLIC_KEY", e.publicKey), a = C.read("VOLTRO_LICENSE_KEY", e.licenseKey), o = e.graceSeconds ?? 0, s = e.refreshMs ?? 9e5, c, l = (e, n) => p(e, n).pipe(t.match({
90
111
  onSuccess: (e) => {
91
- g(m(e, { graceSeconds: o })), c?.info("license active", {
112
+ g(m(e, { graceSeconds: o })), y(void 0), c?.info("license active", {
92
113
  edition: e.edition,
93
114
  entitlements: Object.keys(e.entitlements).length,
94
115
  exp: e.exp
95
116
  });
96
117
  },
97
118
  onFailure: (e) => {
98
- c?.warn("license verification failed — entitlements fall back to static plan", {
119
+ y({
120
+ reason: e.reason,
121
+ message: e.message
122
+ }), c?.warn("license verification failed — entitlements fall back to static plan", {
99
123
  reason: e.reason,
100
124
  message: e.message
101
125
  });
@@ -107,8 +131,8 @@ var c = class extends e.TaggedError("LicenseVerifyError") {}, l = (e) => typeof
107
131
  instance: e.name
108
132
  }),
109
133
  description: "Offline-verified EdDSA license keys + entitlement snapshots; feeds @voltro/plugin-billing via entitlementResolver.",
110
- declaredEnv: y.declared,
111
- services: x,
134
+ declaredEnv: C.declared,
135
+ services: T,
112
136
  onActivate: (e) => t.gen(function* () {
113
137
  if (c = e.logger, r === void 0 || a === void 0) {
114
138
  e.logger.debug("licensing: no license configured — static plan entitlements apply");
@@ -131,8 +155,10 @@ var c = class extends e.TaggedError("LicenseVerifyError") {}, l = (e) => typeof
131
155
  }
132
156
  });
133
157
  },
134
- onDeactivate: () => t.sync(() => g(void 0))
158
+ onDeactivate: () => t.sync(() => {
159
+ g(void 0), y(void 0);
160
+ })
135
161
  });
136
162
  };
137
163
  //#endregion
138
- export { b as LicenseService, c as LicenseVerifyError, S as PluginNotLicensed, v as entitlementResolver, C as licenseAllowsPlugin, T as licensingPlugin, w as requireLicensedPlugin, p as verifyLicense };
164
+ export { w as LicenseService, c as LicenseVerifyError, E as PluginNotLicensed, x as entitlementResolver, D as licenseAllowsPlugin, S as licenseStatus, k as licensingPlugin, O as requireLicensedPlugin, p as verifyLicense };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voltro/plugin-licensing",
3
- "version": "0.81.0",
3
+ "version": "0.83.0",
4
4
  "description": "Offline-verified license keys + cloud-issued entitlement snapshots for @voltro apps",
5
5
  "keywords": [
6
6
  "voltro",
@@ -38,10 +38,10 @@
38
38
  "node": ">=24.0.0"
39
39
  },
40
40
  "dependencies": {
41
- "@voltro/database": "0.81.0",
42
- "@voltro/env": "0.81.0",
43
- "@voltro/logger": "0.81.0",
44
- "@voltro/protocol": "0.81.0",
41
+ "@voltro/database": "0.83.0",
42
+ "@voltro/env": "0.83.0",
43
+ "@voltro/logger": "0.83.0",
44
+ "@voltro/protocol": "0.83.0",
45
45
  "jose": "^6.2.12"
46
46
  },
47
47
  "peerDependencies": {