shieldcortex 2.17.0 → 2.18.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 (95) hide show
  1. package/README.md +305 -505
  2. package/dashboard/.next/standalone/dashboard/.next/BUILD_ID +1 -1
  3. package/dashboard/.next/standalone/dashboard/.next/build-manifest.json +2 -2
  4. package/dashboard/.next/standalone/dashboard/.next/prerender-manifest.json +3 -3
  5. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.html +2 -2
  6. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.rsc +1 -1
  7. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  8. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  9. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  10. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  11. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  12. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.html +1 -1
  13. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.rsc +1 -1
  14. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  15. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  16. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  17. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  18. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  19. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  20. package/dashboard/.next/standalone/dashboard/.next/server/app/index.html +1 -1
  21. package/dashboard/.next/standalone/dashboard/.next/server/app/index.rsc +2 -2
  22. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  23. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_full.segment.rsc +2 -2
  24. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_head.segment.rsc +1 -1
  25. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_index.segment.rsc +1 -1
  26. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  27. package/dashboard/.next/standalone/dashboard/.next/server/app/page_client-reference-manifest.js +1 -1
  28. package/dashboard/.next/standalone/dashboard/.next/server/chunks/ssr/dashboard_25b1b286._.js +1 -1
  29. package/dashboard/.next/standalone/dashboard/.next/server/pages/404.html +1 -1
  30. package/dashboard/.next/standalone/dashboard/.next/server/pages/500.html +2 -2
  31. package/dashboard/.next/standalone/dashboard/.next/server/server-reference-manifest.js +1 -1
  32. package/dashboard/.next/standalone/dashboard/.next/server/server-reference-manifest.json +1 -1
  33. package/dashboard/.next/standalone/dashboard/.next/static/chunks/{61a3c89b08347bc2.js → 8a1c0cc0ae709e3d.js} +1 -1
  34. package/dist/defence/iron-dome/index.d.ts.map +1 -1
  35. package/dist/defence/iron-dome/index.js +5 -0
  36. package/dist/defence/iron-dome/index.js.map +1 -1
  37. package/dist/defence/pipeline.d.ts.map +1 -1
  38. package/dist/defence/pipeline.js +9 -6
  39. package/dist/defence/pipeline.js.map +1 -1
  40. package/dist/index.d.ts +3 -0
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +9 -0
  43. package/dist/index.js.map +1 -1
  44. package/dist/lib.d.ts +2 -0
  45. package/dist/lib.d.ts.map +1 -1
  46. package/dist/lib.js +2 -0
  47. package/dist/lib.js.map +1 -1
  48. package/dist/license/cli.d.ts +9 -0
  49. package/dist/license/cli.d.ts.map +1 -0
  50. package/dist/license/cli.js +141 -0
  51. package/dist/license/cli.js.map +1 -0
  52. package/dist/license/gate.d.ts +38 -0
  53. package/dist/license/gate.d.ts.map +1 -0
  54. package/dist/license/gate.js +84 -0
  55. package/dist/license/gate.js.map +1 -0
  56. package/dist/license/index.d.ts +12 -0
  57. package/dist/license/index.d.ts.map +1 -0
  58. package/dist/license/index.js +12 -0
  59. package/dist/license/index.js.map +1 -0
  60. package/dist/license/keys.d.ts +50 -0
  61. package/dist/license/keys.d.ts.map +1 -0
  62. package/dist/license/keys.js +30 -0
  63. package/dist/license/keys.js.map +1 -0
  64. package/dist/license/store.d.ts +45 -0
  65. package/dist/license/store.d.ts.map +1 -0
  66. package/dist/license/store.js +148 -0
  67. package/dist/license/store.js.map +1 -0
  68. package/dist/license/validate.d.ts +24 -0
  69. package/dist/license/validate.d.ts.map +1 -0
  70. package/dist/license/validate.js +86 -0
  71. package/dist/license/validate.js.map +1 -0
  72. package/dist/license/verify.d.ts +18 -0
  73. package/dist/license/verify.d.ts.map +1 -0
  74. package/dist/license/verify.js +126 -0
  75. package/dist/license/verify.js.map +1 -0
  76. package/dist/memory/store.d.ts.map +1 -1
  77. package/dist/memory/store.js +18 -16
  78. package/dist/memory/store.js.map +1 -1
  79. package/dist/setup/status.d.ts.map +1 -1
  80. package/dist/setup/status.js +34 -0
  81. package/dist/setup/status.js.map +1 -1
  82. package/dist/setup/uninstall.d.ts.map +1 -1
  83. package/dist/setup/uninstall.js +6 -1
  84. package/dist/setup/uninstall.js.map +1 -1
  85. package/dist/tools/context.d.ts.map +1 -1
  86. package/dist/tools/context.js +2 -0
  87. package/dist/tools/context.js.map +1 -1
  88. package/dist/worker/brain-worker.d.ts.map +1 -1
  89. package/dist/worker/brain-worker.js +25 -18
  90. package/dist/worker/brain-worker.js.map +1 -1
  91. package/package.json +1 -1
  92. package/plugins/openclaw/README.md +3 -1
  93. /package/dashboard/.next/standalone/dashboard/.next/static/{rafRHTrrEzsWtJlg9d1Sf → h890EBq1H-89xzeQf-gx5}/_buildManifest.js +0 -0
  94. /package/dashboard/.next/standalone/dashboard/.next/static/{rafRHTrrEzsWtJlg9d1Sf → h890EBq1H-89xzeQf-gx5}/_clientMiddlewareManifest.json +0 -0
  95. /package/dashboard/.next/standalone/dashboard/.next/static/{rafRHTrrEzsWtJlg9d1Sf → h890EBq1H-89xzeQf-gx5}/_ssgManifest.js +0 -0
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Feature gating — the central guard for Pro/Team features.
3
+ *
4
+ * Usage:
5
+ * requireFeature('custom_injection_patterns'); // throws FeatureGatedError if not Pro+
6
+ * isFeatureEnabled('cloud_sync'); // returns boolean (soft check)
7
+ */
8
+ import { getLicenseTier } from './store.js';
9
+ import { TIER_RANK } from './keys.js';
10
+ const FEATURE_TIERS = {
11
+ custom_injection_patterns: 'pro',
12
+ custom_iron_dome_policies: 'pro',
13
+ custom_firewall_rules: 'pro',
14
+ audit_export: 'pro',
15
+ skill_scanner_deep: 'pro',
16
+ cloud_sync: 'team',
17
+ team_management: 'team',
18
+ shared_patterns: 'team',
19
+ };
20
+ const FEATURE_DESCRIPTIONS = {
21
+ custom_injection_patterns: 'Define up to 50 custom regex patterns for detecting domain-specific threats.',
22
+ custom_iron_dome_policies: 'Create custom Iron Dome policies with tailored action gates and trust levels.',
23
+ custom_firewall_rules: 'Add custom firewall rules to block or allow specific content patterns.',
24
+ audit_export: 'Export your full audit trail as JSON or CSV for compliance reporting.',
25
+ skill_scanner_deep: 'Deep skill scanning with multi-file analysis and semantic intent detection.',
26
+ cloud_sync: 'Sync audit data across devices for centralised team visibility.',
27
+ team_management: 'Manage team members, invites, and shared security policies.',
28
+ shared_patterns: 'Share custom injection patterns and policies across your team.',
29
+ };
30
+ // ── Error class ──────────────────────────────────────────
31
+ export class FeatureGatedError extends Error {
32
+ feature;
33
+ requiredTier;
34
+ constructor(feature, requiredTier) {
35
+ const tierLabel = requiredTier.charAt(0).toUpperCase() + requiredTier.slice(1);
36
+ const desc = FEATURE_DESCRIPTIONS[feature];
37
+ super(`This feature requires a ${tierLabel} licence.\n\n` +
38
+ `${desc}\n\n` +
39
+ ` Upgrade: https://shieldcortex.ai/pricing\n` +
40
+ ` Activate: shieldcortex license activate <key>`);
41
+ this.feature = feature;
42
+ this.requiredTier = requiredTier;
43
+ this.name = 'FeatureGatedError';
44
+ }
45
+ }
46
+ // ── Guards ────────────────────────────────────────────────
47
+ /**
48
+ * Check if a feature is enabled under the current licence tier.
49
+ * Use for soft checks (e.g. hiding UI elements, silent returns).
50
+ */
51
+ export function isFeatureEnabled(feature) {
52
+ const requiredTier = FEATURE_TIERS[feature];
53
+ const currentTier = getLicenseTier();
54
+ return TIER_RANK[currentTier] >= TIER_RANK[requiredTier];
55
+ }
56
+ /**
57
+ * Require a feature — throws FeatureGatedError if the current licence
58
+ * doesn't include it. Use at the entry point of gated features.
59
+ */
60
+ export function requireFeature(feature) {
61
+ if (!isFeatureEnabled(feature)) {
62
+ throw new FeatureGatedError(feature, FEATURE_TIERS[feature]);
63
+ }
64
+ }
65
+ /**
66
+ * Get the minimum tier required for a feature.
67
+ */
68
+ export function getRequiredTier(feature) {
69
+ return FEATURE_TIERS[feature];
70
+ }
71
+ /**
72
+ * List all features with their required tier and current availability.
73
+ */
74
+ export function listFeatures() {
75
+ const currentTier = getLicenseTier();
76
+ const currentRank = TIER_RANK[currentTier];
77
+ return Object.keys(FEATURE_TIERS).map((feature) => ({
78
+ feature,
79
+ requiredTier: FEATURE_TIERS[feature],
80
+ enabled: currentRank >= TIER_RANK[FEATURE_TIERS[feature]],
81
+ description: FEATURE_DESCRIPTIONS[feature],
82
+ }));
83
+ }
84
+ //# sourceMappingURL=gate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate.js","sourceRoot":"","sources":["../../src/license/gate.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAoB,MAAM,WAAW,CAAC;AAcxD,MAAM,aAAa,GAAsC;IACvD,yBAAyB,EAAE,KAAK;IAChC,yBAAyB,EAAE,KAAK;IAChC,qBAAqB,EAAE,KAAK;IAC5B,YAAY,EAAE,KAAK;IACnB,kBAAkB,EAAE,KAAK;IACzB,UAAU,EAAE,MAAM;IAClB,eAAe,EAAE,MAAM;IACvB,eAAe,EAAE,MAAM;CACxB,CAAC;AAEF,MAAM,oBAAoB,GAAiC;IACzD,yBAAyB,EAAE,8EAA8E;IACzG,yBAAyB,EAAE,+EAA+E;IAC1G,qBAAqB,EAAE,wEAAwE;IAC/F,YAAY,EAAE,uEAAuE;IACrF,kBAAkB,EAAE,6EAA6E;IACjG,UAAU,EAAE,iEAAiE;IAC7E,eAAe,EAAE,6DAA6D;IAC9E,eAAe,EAAE,gEAAgE;CAClF,CAAC;AAEF,4DAA4D;AAE5D,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IAEjC;IACA;IAFT,YACS,OAAqB,EACrB,YAAyB;QAEhC,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC/E,MAAM,IAAI,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAC3C,KAAK,CACH,2BAA2B,SAAS,eAAe;YACnD,GAAG,IAAI,MAAM;YACb,+CAA+C;YAC/C,iDAAiD,CAClD,CAAC;QAVK,YAAO,GAAP,OAAO,CAAc;QACrB,iBAAY,GAAZ,YAAY,CAAa;QAUhC,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF;AAED,6DAA6D;AAE7D;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAqB;IACpD,MAAM,YAAY,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IAC5C,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,OAAO,SAAS,CAAC,WAAW,CAAC,IAAI,SAAS,CAAC,YAAY,CAAC,CAAC;AAC3D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,OAAqB;IAClD,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,iBAAiB,CAAC,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,OAAqB;IACnD,OAAO,aAAa,CAAC,OAAO,CAAC,CAAC;AAChC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY;IAM1B,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,MAAM,WAAW,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC;IAE3C,OAAQ,MAAM,CAAC,IAAI,CAAC,aAAa,CAAoB,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACtE,OAAO;QACP,YAAY,EAAE,aAAa,CAAC,OAAO,CAAC;QACpC,OAAO,EAAE,WAAW,IAAI,SAAS,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QACzD,WAAW,EAAE,oBAAoB,CAAC,OAAO,CAAC;KAC3C,CAAC,CAAC,CAAC;AACN,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * License module — re-exports for public API and internal use.
3
+ */
4
+ export { getLicense, getLicenseTier, getLicenseFile, clearLicenseCache } from './store.js';
5
+ export { verifyLicenseKey, parseLicensePayload } from './verify.js';
6
+ export { isFeatureEnabled, requireFeature, getRequiredTier, listFeatures, FeatureGatedError, } from './gate.js';
7
+ export { scheduleOnlineValidation } from './validate.js';
8
+ export type { LicenseTier, LicenseInfo, LicensePayload, LicenseFile } from './keys.js';
9
+ export type { GatedFeature } from './gate.js';
10
+ export { TIER_RANK, KEY_PREFIXES, EXPIRY_GRACE_DAYS } from './keys.js';
11
+ export { handleLicenseCommand } from './cli.js';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/license/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC3F,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,YAAY,EACZ,iBAAiB,GAClB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAGzD,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACvF,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAGvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * License module — re-exports for public API and internal use.
3
+ */
4
+ // ── Public API (exported from lib.ts) ────────────────────
5
+ export { getLicense, getLicenseTier, getLicenseFile, clearLicenseCache } from './store.js';
6
+ export { verifyLicenseKey, parseLicensePayload } from './verify.js';
7
+ export { isFeatureEnabled, requireFeature, getRequiredTier, listFeatures, FeatureGatedError, } from './gate.js';
8
+ export { scheduleOnlineValidation } from './validate.js';
9
+ export { TIER_RANK, KEY_PREFIXES, EXPIRY_GRACE_DAYS } from './keys.js';
10
+ // ── CLI (imported lazily from src/index.ts) ──────────────
11
+ export { handleLicenseCommand } from './cli.js';
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/license/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,4DAA4D;AAC5D,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC3F,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,YAAY,EACZ,iBAAiB,GAClB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAKzD,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAEvE,4DAA4D;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * License key types, constants, and the Ed25519 public key used to verify licence keys offline.
3
+ *
4
+ * The private key lives ONLY in the SaaS API (Fly.io secrets).
5
+ * This public key can verify signatures but cannot create them.
6
+ */
7
+ /**
8
+ * Ed25519 public key in DER (SPKI) hex format.
9
+ * Generated once; the matching private key is stored in Fly.io as LICENSE_SIGNING_KEY.
10
+ */
11
+ export declare const LICENSE_PUBLIC_KEY_HEX = "302a300506032b657003210053e006dc81bf14eda2b2481868f7bbad49b614b3dafe24f950202c4f712f955d";
12
+ export type LicenseTier = 'free' | 'pro' | 'team' | 'enterprise';
13
+ /** The signed payload embedded inside a license key. */
14
+ export interface LicensePayload {
15
+ tier: Exclude<LicenseTier, 'free'>;
16
+ teamId: number;
17
+ email: string;
18
+ /** Expiry — Unix seconds */
19
+ exp: number;
20
+ /** Issued-at — Unix seconds */
21
+ iat: number;
22
+ /** Stripe subscription ID — used for online revocation checks */
23
+ sid: string;
24
+ }
25
+ /** The result of verifying a license key. */
26
+ export interface LicenseInfo {
27
+ valid: boolean;
28
+ tier: LicenseTier;
29
+ email: string | null;
30
+ expiresAt: Date | null;
31
+ daysUntilExpiry: number | null;
32
+ teamId: number | null;
33
+ subscriptionId: string | null;
34
+ }
35
+ /** Stored in ~/.shieldcortex/license.json */
36
+ export interface LicenseFile {
37
+ key: string;
38
+ activatedAt: string;
39
+ lastValidatedAt: string | null;
40
+ validationStatus: 'valid' | 'expired' | 'revoked' | 'unvalidated';
41
+ }
42
+ /** Key prefix convention: sc_{tier}_ */
43
+ export declare const KEY_PREFIXES: Record<Exclude<LicenseTier, 'free'>, string>;
44
+ /** Tier rank for comparison (higher = more permissive) */
45
+ export declare const TIER_RANK: Record<LicenseTier, number>;
46
+ /** Grace period after expiry (days) — covers Stripe dunning retries */
47
+ export declare const EXPIRY_GRACE_DAYS = 7;
48
+ /** How often to run online validation (ms) */
49
+ export declare const ONLINE_VALIDATION_INTERVAL_MS: number;
50
+ //# sourceMappingURL=keys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../../src/license/keys.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,eAAO,MAAM,sBAAsB,6FACyD,CAAC;AAI7F,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,YAAY,CAAC;AAEjE,wDAAwD;AACxD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,4BAA4B;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,+BAA+B;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,iEAAiE;IACjE,GAAG,EAAE,MAAM,CAAC;CACb;AAED,6CAA6C;AAC7C,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,6CAA6C;AAC7C,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,gBAAgB,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,aAAa,CAAC;CACnE;AAID,wCAAwC;AACxC,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,MAAM,CAIrE,CAAC;AAEF,0DAA0D;AAC1D,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAKjD,CAAC;AAEF,uEAAuE;AACvE,eAAO,MAAM,iBAAiB,IAAI,CAAC;AAEnC,8CAA8C;AAC9C,eAAO,MAAM,6BAA6B,QAAsB,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * License key types, constants, and the Ed25519 public key used to verify licence keys offline.
3
+ *
4
+ * The private key lives ONLY in the SaaS API (Fly.io secrets).
5
+ * This public key can verify signatures but cannot create them.
6
+ */
7
+ /**
8
+ * Ed25519 public key in DER (SPKI) hex format.
9
+ * Generated once; the matching private key is stored in Fly.io as LICENSE_SIGNING_KEY.
10
+ */
11
+ export const LICENSE_PUBLIC_KEY_HEX = '302a300506032b657003210053e006dc81bf14eda2b2481868f7bbad49b614b3dafe24f950202c4f712f955d';
12
+ // ── Constants ────────────────────────────────────────────
13
+ /** Key prefix convention: sc_{tier}_ */
14
+ export const KEY_PREFIXES = {
15
+ pro: 'sc_pro_',
16
+ team: 'sc_team_',
17
+ enterprise: 'sc_ent_',
18
+ };
19
+ /** Tier rank for comparison (higher = more permissive) */
20
+ export const TIER_RANK = {
21
+ free: 0,
22
+ pro: 1,
23
+ team: 2,
24
+ enterprise: 3,
25
+ };
26
+ /** Grace period after expiry (days) — covers Stripe dunning retries */
27
+ export const EXPIRY_GRACE_DAYS = 7;
28
+ /** How often to run online validation (ms) */
29
+ export const ONLINE_VALIDATION_INTERVAL_MS = 24 * 60 * 60 * 1000; // 24 hours
30
+ //# sourceMappingURL=keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys.js","sourceRoot":"","sources":["../../src/license/keys.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,sBAAsB,GACjC,0FAA0F,CAAC;AAsC7F,4DAA4D;AAE5D,wCAAwC;AACxC,MAAM,CAAC,MAAM,YAAY,GAAiD;IACxE,GAAG,EAAE,SAAS;IACd,IAAI,EAAE,UAAU;IAChB,UAAU,EAAE,SAAS;CACtB,CAAC;AAEF,0DAA0D;AAC1D,MAAM,CAAC,MAAM,SAAS,GAAgC;IACpD,IAAI,EAAE,CAAC;IACP,GAAG,EAAE,CAAC;IACN,IAAI,EAAE,CAAC;IACP,UAAU,EAAE,CAAC;CACd,CAAC;AAEF,uEAAuE;AACvE,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC;AAEnC,8CAA8C;AAC9C,MAAM,CAAC,MAAM,6BAA6B,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * License file I/O — reads/writes ~/.shieldcortex/license.json
3
+ *
4
+ * The Ed25519 signature on the key itself provides integrity for the tier
5
+ * and expiry. The validationStatus field is advisory — a tampered value
6
+ * only persists until the next online validation (≤24h). HMAC is not
7
+ * needed here because the hard security boundary is the signed key, not
8
+ * the JSON file.
9
+ *
10
+ * License is cached in memory after first read.
11
+ */
12
+ import type { LicenseTier, LicenseInfo, LicenseFile } from './keys.js';
13
+ /** Clear the in-memory cache (useful for testing or after activation). */
14
+ export declare function clearLicenseCache(): void;
15
+ /**
16
+ * Read and verify the stored license.
17
+ * Returns a LicenseInfo with tier='free' if no license exists or verification fails.
18
+ */
19
+ export declare function getLicense(): LicenseInfo;
20
+ /**
21
+ * Quick accessor for the current licence tier.
22
+ * Returns 'free' if no valid licence exists.
23
+ */
24
+ export declare function getLicenseTier(): LicenseTier;
25
+ /**
26
+ * Read the raw license file data (for status display).
27
+ * Returns null if no license file exists.
28
+ */
29
+ export declare function getLicenseFile(): LicenseFile | null;
30
+ /**
31
+ * Activate a license key — verify it, then store in license.json.
32
+ * Returns the verified LicenseInfo.
33
+ * Throws if the key is invalid.
34
+ */
35
+ export declare function activateLicense(key: string): LicenseInfo;
36
+ /**
37
+ * Remove the license file (deactivate).
38
+ */
39
+ export declare function deactivateLicense(): void;
40
+ /**
41
+ * Update the validation status and timestamp in the license file.
42
+ * Called by the online validation module.
43
+ */
44
+ export declare function updateValidationStatus(status: LicenseFile['validationStatus']): void;
45
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/license/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AASvE,0EAA0E;AAC1E,wBAAgB,iBAAiB,IAAI,IAAI,CAExC;AAID;;;GAGG;AACH,wBAAgB,UAAU,IAAI,WAAW,CA0CxC;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAE5C;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,WAAW,GAAG,IAAI,CAOnD;AAID;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAmBxD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CASxC;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,WAAW,CAAC,kBAAkB,CAAC,GAAG,IAAI,CAepF"}
@@ -0,0 +1,148 @@
1
+ /**
2
+ * License file I/O — reads/writes ~/.shieldcortex/license.json
3
+ *
4
+ * The Ed25519 signature on the key itself provides integrity for the tier
5
+ * and expiry. The validationStatus field is advisory — a tampered value
6
+ * only persists until the next online validation (≤24h). HMAC is not
7
+ * needed here because the hard security boundary is the signed key, not
8
+ * the JSON file.
9
+ *
10
+ * License is cached in memory after first read.
11
+ */
12
+ import { readFileSync, writeFileSync, existsSync, unlinkSync, mkdirSync } from 'fs';
13
+ import { join } from 'path';
14
+ import { homedir } from 'os';
15
+ import { verifyLicenseKey } from './verify.js';
16
+ const CONFIG_DIR = join(homedir(), '.shieldcortex');
17
+ const LICENSE_FILE = join(CONFIG_DIR, 'license.json');
18
+ // ── Cache ────────────────────────────────────────────────
19
+ let cachedLicense = null;
20
+ /** Clear the in-memory cache (useful for testing or after activation). */
21
+ export function clearLicenseCache() {
22
+ cachedLicense = null;
23
+ }
24
+ // ── Read ─────────────────────────────────────────────────
25
+ /**
26
+ * Read and verify the stored license.
27
+ * Returns a LicenseInfo with tier='free' if no license exists or verification fails.
28
+ */
29
+ export function getLicense() {
30
+ if (cachedLicense)
31
+ return cachedLicense;
32
+ const FREE = {
33
+ valid: false,
34
+ tier: 'free',
35
+ email: null,
36
+ expiresAt: null,
37
+ daysUntilExpiry: null,
38
+ teamId: null,
39
+ subscriptionId: null,
40
+ };
41
+ try {
42
+ if (!existsSync(LICENSE_FILE)) {
43
+ cachedLicense = FREE;
44
+ return FREE;
45
+ }
46
+ const raw = JSON.parse(readFileSync(LICENSE_FILE, 'utf-8'));
47
+ if (!raw.key) {
48
+ cachedLicense = FREE;
49
+ return FREE;
50
+ }
51
+ // Check if previously marked as revoked or expired by online validation.
52
+ // Revoked = subscription cancelled (hard block).
53
+ // Expired = advisory; verifyLicenseKey() applies the 7-day grace period
54
+ // so we only hard-block on revoked here.
55
+ if (raw.validationStatus === 'revoked') {
56
+ cachedLicense = FREE;
57
+ return FREE;
58
+ }
59
+ // Verify the key cryptographically (checks exp + grace period)
60
+ const info = verifyLicenseKey(raw.key);
61
+ cachedLicense = info;
62
+ return info;
63
+ }
64
+ catch {
65
+ cachedLicense = FREE;
66
+ return FREE;
67
+ }
68
+ }
69
+ /**
70
+ * Quick accessor for the current licence tier.
71
+ * Returns 'free' if no valid licence exists.
72
+ */
73
+ export function getLicenseTier() {
74
+ return getLicense().tier;
75
+ }
76
+ /**
77
+ * Read the raw license file data (for status display).
78
+ * Returns null if no license file exists.
79
+ */
80
+ export function getLicenseFile() {
81
+ try {
82
+ if (!existsSync(LICENSE_FILE))
83
+ return null;
84
+ return JSON.parse(readFileSync(LICENSE_FILE, 'utf-8'));
85
+ }
86
+ catch {
87
+ return null;
88
+ }
89
+ }
90
+ // ── Write ────────────────────────────────────────────────
91
+ /**
92
+ * Activate a license key — verify it, then store in license.json.
93
+ * Returns the verified LicenseInfo.
94
+ * Throws if the key is invalid.
95
+ */
96
+ export function activateLicense(key) {
97
+ const info = verifyLicenseKey(key);
98
+ if (!info.valid) {
99
+ throw new Error('Invalid or expired licence key. Check the key and try again.');
100
+ }
101
+ const file = {
102
+ key,
103
+ activatedAt: new Date().toISOString(),
104
+ lastValidatedAt: null,
105
+ validationStatus: 'unvalidated',
106
+ };
107
+ mkdirSync(CONFIG_DIR, { recursive: true });
108
+ writeFileSync(LICENSE_FILE, JSON.stringify(file, null, 2) + '\n', { mode: 0o600 });
109
+ // Invalidate cache
110
+ cachedLicense = info;
111
+ return info;
112
+ }
113
+ /**
114
+ * Remove the license file (deactivate).
115
+ */
116
+ export function deactivateLicense() {
117
+ try {
118
+ if (existsSync(LICENSE_FILE)) {
119
+ unlinkSync(LICENSE_FILE);
120
+ }
121
+ }
122
+ catch {
123
+ // Best effort
124
+ }
125
+ cachedLicense = null;
126
+ }
127
+ /**
128
+ * Update the validation status and timestamp in the license file.
129
+ * Called by the online validation module.
130
+ */
131
+ export function updateValidationStatus(status) {
132
+ try {
133
+ if (!existsSync(LICENSE_FILE))
134
+ return;
135
+ const raw = JSON.parse(readFileSync(LICENSE_FILE, 'utf-8'));
136
+ raw.validationStatus = status;
137
+ raw.lastValidatedAt = new Date().toISOString();
138
+ writeFileSync(LICENSE_FILE, JSON.stringify(raw, null, 2) + '\n', { mode: 0o600 });
139
+ // If revoked or expired, invalidate cache so next getLicense() re-verifies
140
+ if (status === 'revoked' || status === 'expired') {
141
+ cachedLicense = null;
142
+ }
143
+ }
144
+ catch {
145
+ // Best effort
146
+ }
147
+ }
148
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/license/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Periodic online licence validation — catches revocations.
3
+ *
4
+ * Fire-and-forget, never blocks. Same pattern as syncToCloud() in cloud/sync.ts.
5
+ * If offline, the licence stays valid until its exp date.
6
+ */
7
+ type ValidationStatus = 'valid' | 'revoked' | 'expired';
8
+ /**
9
+ * Run online validation if enough time has passed since the last check.
10
+ * Non-blocking — errors are silently ignored.
11
+ */
12
+ export declare function scheduleOnlineValidation(): void;
13
+ /**
14
+ * Validate the stored licence key against the SaaS API.
15
+ * Called periodically (every 24h) and once on activation.
16
+ */
17
+ export declare function validateOnline(): Promise<void>;
18
+ /**
19
+ * Run a one-time validation immediately (used during activation).
20
+ * Returns the validation status, or 'unvalidated' if the check fails.
21
+ */
22
+ export declare function validateOnceNow(): Promise<ValidationStatus | 'unvalidated'>;
23
+ export {};
24
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/license/validate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,KAAK,gBAAgB,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;AAIxD;;;GAGG;AACH,wBAAgB,wBAAwB,IAAI,IAAI,CAO/C;AAmCD;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAYpD;AAED;;;GAGG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,gBAAgB,GAAG,aAAa,CAAC,CAajF"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Periodic online licence validation — catches revocations.
3
+ *
4
+ * Fire-and-forget, never blocks. Same pattern as syncToCloud() in cloud/sync.ts.
5
+ * If offline, the licence stays valid until its exp date.
6
+ */
7
+ import { getLicenseFile, updateValidationStatus } from './store.js';
8
+ import { parseLicensePayload } from './verify.js';
9
+ import { ONLINE_VALIDATION_INTERVAL_MS } from './keys.js';
10
+ import { getCloudConfig } from '../cloud/config.js';
11
+ let lastValidationAttempt = 0;
12
+ /**
13
+ * Run online validation if enough time has passed since the last check.
14
+ * Non-blocking — errors are silently ignored.
15
+ */
16
+ export function scheduleOnlineValidation() {
17
+ const now = Date.now();
18
+ if (now - lastValidationAttempt < ONLINE_VALIDATION_INTERVAL_MS)
19
+ return;
20
+ lastValidationAttempt = now;
21
+ // Fire-and-forget
22
+ validateOnline().catch(() => { });
23
+ }
24
+ // ── Shared HTTP helper ──────────────────────────────────
25
+ /**
26
+ * Fetch the validation status from the SaaS API.
27
+ * Returns null on network error, timeout, or server error.
28
+ */
29
+ async function fetchValidationStatus(sid) {
30
+ const config = getCloudConfig();
31
+ const baseUrl = config.cloudBaseUrl || 'https://api.shieldcortex.ai';
32
+ const controller = new AbortController();
33
+ const timeout = setTimeout(() => controller.abort(), 10_000);
34
+ try {
35
+ const res = await fetch(`${baseUrl}/v1/license/validate?sid=${encodeURIComponent(sid)}`, { signal: controller.signal });
36
+ if (!res.ok)
37
+ return null;
38
+ const data = await res.json();
39
+ if (data.status === 'unknown')
40
+ return null; // Subscription not found — treat as network error
41
+ return data.status === 'active' ? 'valid' : data.status;
42
+ }
43
+ catch {
44
+ return null;
45
+ }
46
+ finally {
47
+ clearTimeout(timeout);
48
+ }
49
+ }
50
+ // ── Public API ──────────────────────────────────────────
51
+ /**
52
+ * Validate the stored licence key against the SaaS API.
53
+ * Called periodically (every 24h) and once on activation.
54
+ */
55
+ export async function validateOnline() {
56
+ const file = getLicenseFile();
57
+ if (!file?.key)
58
+ return;
59
+ const payload = parseLicensePayload(file.key);
60
+ if (!payload?.sid)
61
+ return;
62
+ const status = await fetchValidationStatus(payload.sid);
63
+ if (status) {
64
+ updateValidationStatus(status);
65
+ }
66
+ // If null (network error), leave status unchanged — licence stays valid
67
+ }
68
+ /**
69
+ * Run a one-time validation immediately (used during activation).
70
+ * Returns the validation status, or 'unvalidated' if the check fails.
71
+ */
72
+ export async function validateOnceNow() {
73
+ const file = getLicenseFile();
74
+ if (!file?.key)
75
+ return 'unvalidated';
76
+ const payload = parseLicensePayload(file.key);
77
+ if (!payload?.sid)
78
+ return 'unvalidated';
79
+ const status = await fetchValidationStatus(payload.sid);
80
+ if (status) {
81
+ updateValidationStatus(status);
82
+ return status;
83
+ }
84
+ return 'unvalidated';
85
+ }
86
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/license/validate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Offline Ed25519 licence key verification.
3
+ *
4
+ * Uses Node.js built-in crypto (available since Node 18).
5
+ * Zero external dependencies.
6
+ */
7
+ import { type LicensePayload, type LicenseInfo } from './keys.js';
8
+ /**
9
+ * Parse the payload JSON from a license key without verifying the signature.
10
+ * Returns null if parsing fails.
11
+ */
12
+ export declare function parseLicensePayload(key: string): LicensePayload | null;
13
+ /**
14
+ * Verify a license key's Ed25519 signature and check expiry.
15
+ * This is completely offline — no network calls.
16
+ */
17
+ export declare function verifyLicenseKey(key: string): LicenseInfo;
18
+ //# sourceMappingURL=verify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/license/verify.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAKL,KAAK,cAAc,EACnB,KAAK,WAAW,EACjB,MAAM,WAAW,CAAC;AA4CnB;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAiBtE;AAID;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAuDzD"}