@copilotkit/license-verifier
Advanced tools
+47
| # @copilotkit/license-verifier | ||
| Public runtime package for offline CopilotKit license verification. | ||
| ## Public API | ||
| The package exports one root entry point: | ||
| <!-- prettier-ignore --> | ||
| ```ts | ||
| import { | ||
| LICENSED_FEATURES, | ||
| addRuntimeKeyAttestation, | ||
| clearRuntimeKeys, | ||
| createLicenseChecker, | ||
| getFeatureDisplayName, | ||
| getFeatureLimit, | ||
| getMasterPublicKey, | ||
| getPublicKey, | ||
| isComponentFeature, | ||
| isFeatureEnabled, | ||
| isRuntimeFeature, | ||
| verifyKeyAttestation, | ||
| verifyLicense, | ||
| type KeyAttestationData, | ||
| type LicenseChecker, | ||
| type LicenseFeatures, | ||
| type LicenseOwner, | ||
| type LicensePayload, | ||
| type LicenseStatus, | ||
| type LicenseTier, | ||
| } from "@copilotkit/license-verifier"; | ||
| ``` | ||
| `verifyLicense(token)` parses the signed payload, verifies the Ed25519 signature, checks expiration, and returns a `LicenseStatus`. Signed payloads may contain extra feature keys so older verifiers can still parse newer tokens structurally; helper reads still deny those unknown keys by default. | ||
| Feature reads are catalog-gated. `isFeatureEnabled(license, feature)` returns `true` only when `feature` is a known boolean feature in `LICENSED_FEATURES` and the signed payload value is exactly `true`. `getFeatureLimit(license, feature)` returns a number only when `feature` is a known numeric feature and the signed payload value is a non-negative integer. Unknown feature keys and value-kind mismatches deny by default. | ||
| `LICENSED_FEATURES` is re-exported from the internal `@cpki/license-catalog` | ||
| projection used at build time. The verifier should not define a separate | ||
| feature catalog. | ||
| `createLicenseChecker(token?)` verifies once, caches the signed payload, and re-evaluates expiration on each `getStatus()` call. `checkFeature(feature)` uses the same catalog-gated boolean feature behavior as `isFeatureEnabled`. | ||
| ## Online Key Attestation | ||
| The package does not export a network client for online verification. Hosts that fetch signing keys from an online endpoint should validate that response outside this package, then call `addRuntimeKeyAttestation({ keyId, publicKey, attestationSig })`. The attestation signature must be over `keyId:publicKey` and signed by the master key baked into the package. |
+69
-91
| //#region src/types.d.ts | ||
| interface LicenseOwner { | ||
| /** Canonical organization identifier embedded in the signed payload. */ | ||
| org_id: string; | ||
@@ -8,20 +9,8 @@ org_name: string; | ||
| interface LicenseFeatures { | ||
| headless_ui?: boolean; | ||
| dev_console?: boolean; | ||
| chat?: boolean; | ||
| sidebar?: boolean; | ||
| popup?: boolean; | ||
| suggestions?: boolean; | ||
| agents?: boolean; | ||
| voice?: boolean; | ||
| frontend_tools?: boolean; | ||
| human_in_the_loop?: boolean; | ||
| mcp_integration?: boolean; | ||
| custom_activity_renderers?: boolean; | ||
| guardrails?: boolean; | ||
| max_agents?: number; | ||
| max_tools?: number; | ||
| "threads.retention_hours"?: number; | ||
| "threads.max_count"?: number; | ||
| "sdk.angular"?: boolean; | ||
| [key: string]: boolean | number | undefined; | ||
| } | ||
| type LicenseTier = "developer" | "pro" | "enterprise"; | ||
| type LicenseTier = "free" | "developer" | "pro" | "enterprise"; | ||
| interface LicensePayload { | ||
@@ -41,2 +30,8 @@ version: number; | ||
| tier: LicenseTier; | ||
| catalog_version?: string; | ||
| plan_code?: LicenseTier; | ||
| entitlement_source?: "enterprise_override" | "clerk_subscription" | "clerk_free_default"; | ||
| issuer?: string | null; | ||
| supersedes_license_id?: string | null; | ||
| replacement_reason?: string | null; | ||
| seat_limit: number; | ||
@@ -49,21 +44,5 @@ features: LicenseFeatures; | ||
| license: LicensePayload | null; | ||
| error: "invalid_signature" | "expired" | "unknown_key" | "parse_error" | null; | ||
| error: "invalid_signature" | "expired" | "unknown_key" | "parse_error" | "key_mismatch" | null; | ||
| graceRemaining?: number; | ||
| warningSeverity: "none" | "info" | "warning" | "critical"; | ||
| } | ||
| type LicenseMode = "online" | "offline"; | ||
| interface OnlineVerifyResponse { | ||
| valid: boolean; | ||
| revoked?: boolean; | ||
| refreshed_token?: string; | ||
| message?: string; | ||
| } | ||
| interface KeyDeliveryResponse { | ||
| keys: Array<{ | ||
| key_id: string; | ||
| public_key: string; | ||
| attestation: string; | ||
| status: string; | ||
| }>; | ||
| master_key_id?: string; | ||
| } //#endregion | ||
@@ -80,3 +59,4 @@ //#region src/verify.d.ts | ||
| * Check whether a specific feature is enabled in the license. | ||
| * Returns false if the license is null or the feature is not present (deny by default). | ||
| * Returns false if the license is null, the feature is unknown, the feature is | ||
| * missing, or the catalog says the feature is not boolean-valued. | ||
| */ | ||
@@ -86,3 +66,4 @@ declare function isFeatureEnabled(license: LicensePayload | null, feature: string): boolean; | ||
| * Get a numeric feature limit from the license. | ||
| * Returns null if the license is null, the feature is missing, or the value is not a number. | ||
| * Returns null if the license is null, the feature is unknown, the feature is | ||
| * missing, or the catalog says the feature is not number-valued. | ||
| */ | ||
@@ -100,13 +81,15 @@ declare function getFeatureLimit(license: LicensePayload | null, feature: string): number | null; | ||
| declare function getMasterPublicKey(): string | null; | ||
| declare const LICENSE_PUBLIC_KEYS: Record<string, string>; | ||
| /** | ||
| * Get a public key by key ID. | ||
| * Checks runtime keys first (network-delivered), then bundled keys. | ||
| * Baked keys take precedence because runtime attestations must not override | ||
| * key IDs compiled into this package. | ||
| */ | ||
| declare function getPublicKey(keyId: string): string | null; | ||
| /** | ||
| * Add a runtime key fetched from the network. | ||
| * Only call this after verifying the key's attestation. | ||
| * Add a runtime key only after validating its master-key attestation. | ||
| * | ||
| * @param attestation - New key material plus a master-key signature. | ||
| * @returns True when the runtime key was accepted. | ||
| */ | ||
| declare function addRuntimeKey(keyId: string, publicKey: string): void; | ||
| declare function addRuntimeKeyAttestation(attestation: KeyAttestationData): boolean; | ||
| /** Remove all runtime keys from the in-memory registry. */ | ||
@@ -126,55 +109,57 @@ declare function clearRuntimeKeys(): void; | ||
| //#endregion | ||
| //#region src/feature-registry.d.ts | ||
| //#region ../../libs/license-catalog/src/index.d.ts | ||
| //# sourceMappingURL=keystore.d.ts.map | ||
| declare const FEATURE_IDS: readonly ["threads.retention_hours", "threads.max_count", "sdk.angular", "deployment.helm_chart"]; | ||
| type FeatureId = (typeof FEATURE_IDS)[number]; | ||
| /** | ||
| * Entitlement claim value embedded in license snapshots. | ||
| * | ||
| * Numeric limits use `0` for unlimited. | ||
| */ | ||
| type FeatureValueKind = "boolean" | "number"; | ||
| interface FeatureDefinition { | ||
| displayName: string; | ||
| component?: boolean; | ||
| runtime?: boolean; | ||
| /** Stable feature id embedded in license feature snapshots. */ | ||
| readonly id: FeatureId; | ||
| /** Human-readable feature name for admin/runtime UI. */ | ||
| readonly displayName: string; | ||
| /** Expected JSON value type for this feature claim. */ | ||
| readonly valueKind: FeatureValueKind; | ||
| /** Whether the feature controls client component availability. */ | ||
| readonly component: boolean; | ||
| /** Whether the feature controls runtime/server behavior. */ | ||
| readonly runtime: boolean; | ||
| } | ||
| declare const LICENSED_FEATURES: Record<string, FeatureDefinition>; | ||
| declare function getFeatureDisplayName(feature: string): string; | ||
| declare function isComponentFeature(feature: string): boolean; | ||
| declare function isRuntimeFeature(feature: string): boolean; | ||
| //#endregion | ||
| //#region src/online-verifier.d.ts | ||
| interface OnlineVerifierOptions { | ||
| baseUrl?: string; | ||
| timeoutMs?: number; | ||
| } | ||
| declare const LICENSED_FEATURES: Readonly<Record<FeatureId, FeatureDefinition>>; | ||
| /** | ||
| * Create an online verifier. | ||
| * STUB: Always returns null until ops-api endpoints exist (Phase 6/7). | ||
| * Resolve a feature's display name from the shared catalog. | ||
| * | ||
| * @param feature - Candidate feature key. | ||
| * @returns Catalog display name, or the original key when unknown. | ||
| */ | ||
| declare function createOnlineVerifier(_options?: OnlineVerifierOptions): { | ||
| verifyOnline: (_token?: string) => Promise<OnlineVerifyResponse | null>; | ||
| fetchKeys: () => Promise<KeyDeliveryResponse["keys"] | null>; | ||
| }; | ||
| //#endregion | ||
| //#region src/context.d.ts | ||
| declare function getFeatureDisplayName(feature: string): string; | ||
| /** | ||
| * License context value exposed to child components. | ||
| * React providers create their own React Context using this shape. | ||
| * Return true when the feature controls client component availability. | ||
| * | ||
| * @param feature - Candidate feature key. | ||
| * @returns Whether the feature is component-scoped. | ||
| */ | ||
| interface LicenseContextValue { | ||
| /** The resolved license status after verification. Null if no token provided. */ | ||
| status: LicenseStatus | null; | ||
| /** Convenience: the license payload if valid, null otherwise. */ | ||
| license: LicensePayload | null; | ||
| /** Whether a specific feature is licensed. Returns true if no licensing is active (no token). */ | ||
| checkFeature: (feature: string) => boolean; | ||
| /** Get a numeric feature limit. Returns null if not applicable. */ | ||
| getLimit: (feature: string) => number | null; | ||
| } | ||
| declare function isComponentFeature(feature: string): boolean; | ||
| /** | ||
| * Create a license context value from a verification result. | ||
| * When no token is provided (status is null), all features return true (unlicensed = unrestricted, with branding). | ||
| * Return true when the feature controls runtime/server behavior. | ||
| * | ||
| * @param feature - Candidate feature key. | ||
| * @returns Whether the feature is runtime-scoped. | ||
| */ | ||
| declare function createLicenseContextValue(status: LicenseStatus | null): LicenseContextValue; | ||
| declare function isRuntimeFeature(feature: string): boolean; | ||
| //#endregion | ||
| //#region src/license-check.d.ts | ||
| //# sourceMappingURL=context.d.ts.map | ||
| /** | ||
| * Resolve a feature definition by id. | ||
| * | ||
| * @param feature - Candidate feature key. | ||
| * @returns Feature definition, or null when unknown. | ||
| */ | ||
| /** | ||
| * Runtime-agnostic license checker that caches verification results | ||
@@ -186,3 +171,3 @@ * and re-evaluates expiration on each access for long-lived processes. | ||
| getStatus(): LicenseStatus; | ||
| /** Check whether a specific feature is enabled. Returns true when no token (soft enforcement). */ | ||
| /** Check whether a specific feature is enabled by a valid, non-expired license. */ | ||
| checkFeature(feature: string): boolean; | ||
@@ -195,13 +180,6 @@ } | ||
| * When no token is provided, falls back to `COPILOTKIT_LICENSE_TOKEN` env var. | ||
| * Missing/invalid tokens result in soft enforcement (features allowed, warnings emitted). | ||
| * Missing/invalid tokens never enable features; product surfaces own warnings | ||
| * and enforcement decisions outside this package. | ||
| */ | ||
| declare function createLicenseChecker(licenseToken?: string): LicenseChecker; | ||
| /** | ||
| * Generate a license warning HTTP header based on the checker's current status. | ||
| * Returns null when no warning is needed. | ||
| */ | ||
| declare function getLicenseWarningHeader(checker?: LicenseChecker): { | ||
| key: string; | ||
| value: string; | ||
| } | null; | ||
@@ -211,3 +189,3 @@ //#endregion | ||
| export { KeyAttestationData, KeyDeliveryResponse, LICENSED_FEATURES, LICENSE_PUBLIC_KEYS, LicenseChecker, LicenseContextValue, LicenseFeatures, LicenseMode, LicenseOwner, LicensePayload, LicenseStatus, LicenseTier, OnlineVerifyResponse, addRuntimeKey, clearRuntimeKeys, createLicenseChecker, createLicenseContextValue, createOnlineVerifier, getFeatureDisplayName, getFeatureLimit, getLicenseWarningHeader, getMasterPublicKey, getPublicKey, isComponentFeature, isFeatureEnabled, isRuntimeFeature, verifyKeyAttestation, verifyLicense }; | ||
| export { KeyAttestationData, LICENSED_FEATURES, LicenseChecker, LicenseFeatures, LicenseOwner, LicensePayload, LicenseStatus, LicenseTier, addRuntimeKeyAttestation, clearRuntimeKeys, createLicenseChecker, getFeatureDisplayName, getFeatureLimit, getMasterPublicKey, getPublicKey, isComponentFeature, isFeatureEnabled, isRuntimeFeature, verifyKeyAttestation, verifyLicense }; | ||
| //# sourceMappingURL=index.d.mts.map |
+69
-91
| //#region src/types.d.ts | ||
| interface LicenseOwner { | ||
| /** Canonical organization identifier embedded in the signed payload. */ | ||
| org_id: string; | ||
@@ -8,20 +9,8 @@ org_name: string; | ||
| interface LicenseFeatures { | ||
| headless_ui?: boolean; | ||
| dev_console?: boolean; | ||
| chat?: boolean; | ||
| sidebar?: boolean; | ||
| popup?: boolean; | ||
| suggestions?: boolean; | ||
| agents?: boolean; | ||
| voice?: boolean; | ||
| frontend_tools?: boolean; | ||
| human_in_the_loop?: boolean; | ||
| mcp_integration?: boolean; | ||
| custom_activity_renderers?: boolean; | ||
| guardrails?: boolean; | ||
| max_agents?: number; | ||
| max_tools?: number; | ||
| "threads.retention_hours"?: number; | ||
| "threads.max_count"?: number; | ||
| "sdk.angular"?: boolean; | ||
| [key: string]: boolean | number | undefined; | ||
| } | ||
| type LicenseTier = "developer" | "pro" | "enterprise"; | ||
| type LicenseTier = "free" | "developer" | "pro" | "enterprise"; | ||
| interface LicensePayload { | ||
@@ -41,2 +30,8 @@ version: number; | ||
| tier: LicenseTier; | ||
| catalog_version?: string; | ||
| plan_code?: LicenseTier; | ||
| entitlement_source?: "enterprise_override" | "clerk_subscription" | "clerk_free_default"; | ||
| issuer?: string | null; | ||
| supersedes_license_id?: string | null; | ||
| replacement_reason?: string | null; | ||
| seat_limit: number; | ||
@@ -49,21 +44,5 @@ features: LicenseFeatures; | ||
| license: LicensePayload | null; | ||
| error: "invalid_signature" | "expired" | "unknown_key" | "parse_error" | null; | ||
| error: "invalid_signature" | "expired" | "unknown_key" | "parse_error" | "key_mismatch" | null; | ||
| graceRemaining?: number; | ||
| warningSeverity: "none" | "info" | "warning" | "critical"; | ||
| } | ||
| type LicenseMode = "online" | "offline"; | ||
| interface OnlineVerifyResponse { | ||
| valid: boolean; | ||
| revoked?: boolean; | ||
| refreshed_token?: string; | ||
| message?: string; | ||
| } | ||
| interface KeyDeliveryResponse { | ||
| keys: Array<{ | ||
| key_id: string; | ||
| public_key: string; | ||
| attestation: string; | ||
| status: string; | ||
| }>; | ||
| master_key_id?: string; | ||
| } //#endregion | ||
@@ -80,3 +59,4 @@ //#region src/verify.d.ts | ||
| * Check whether a specific feature is enabled in the license. | ||
| * Returns false if the license is null or the feature is not present (deny by default). | ||
| * Returns false if the license is null, the feature is unknown, the feature is | ||
| * missing, or the catalog says the feature is not boolean-valued. | ||
| */ | ||
@@ -86,3 +66,4 @@ declare function isFeatureEnabled(license: LicensePayload | null, feature: string): boolean; | ||
| * Get a numeric feature limit from the license. | ||
| * Returns null if the license is null, the feature is missing, or the value is not a number. | ||
| * Returns null if the license is null, the feature is unknown, the feature is | ||
| * missing, or the catalog says the feature is not number-valued. | ||
| */ | ||
@@ -100,13 +81,15 @@ declare function getFeatureLimit(license: LicensePayload | null, feature: string): number | null; | ||
| declare function getMasterPublicKey(): string | null; | ||
| declare const LICENSE_PUBLIC_KEYS: Record<string, string>; | ||
| /** | ||
| * Get a public key by key ID. | ||
| * Checks runtime keys first (network-delivered), then bundled keys. | ||
| * Baked keys take precedence because runtime attestations must not override | ||
| * key IDs compiled into this package. | ||
| */ | ||
| declare function getPublicKey(keyId: string): string | null; | ||
| /** | ||
| * Add a runtime key fetched from the network. | ||
| * Only call this after verifying the key's attestation. | ||
| * Add a runtime key only after validating its master-key attestation. | ||
| * | ||
| * @param attestation - New key material plus a master-key signature. | ||
| * @returns True when the runtime key was accepted. | ||
| */ | ||
| declare function addRuntimeKey(keyId: string, publicKey: string): void; | ||
| declare function addRuntimeKeyAttestation(attestation: KeyAttestationData): boolean; | ||
| /** Remove all runtime keys from the in-memory registry. */ | ||
@@ -126,55 +109,57 @@ declare function clearRuntimeKeys(): void; | ||
| //#endregion | ||
| //#region src/feature-registry.d.ts | ||
| //#region ../../libs/license-catalog/src/index.d.ts | ||
| //# sourceMappingURL=keystore.d.ts.map | ||
| declare const FEATURE_IDS: readonly ["threads.retention_hours", "threads.max_count", "sdk.angular", "deployment.helm_chart"]; | ||
| type FeatureId = (typeof FEATURE_IDS)[number]; | ||
| /** | ||
| * Entitlement claim value embedded in license snapshots. | ||
| * | ||
| * Numeric limits use `0` for unlimited. | ||
| */ | ||
| type FeatureValueKind = "boolean" | "number"; | ||
| interface FeatureDefinition { | ||
| displayName: string; | ||
| component?: boolean; | ||
| runtime?: boolean; | ||
| /** Stable feature id embedded in license feature snapshots. */ | ||
| readonly id: FeatureId; | ||
| /** Human-readable feature name for admin/runtime UI. */ | ||
| readonly displayName: string; | ||
| /** Expected JSON value type for this feature claim. */ | ||
| readonly valueKind: FeatureValueKind; | ||
| /** Whether the feature controls client component availability. */ | ||
| readonly component: boolean; | ||
| /** Whether the feature controls runtime/server behavior. */ | ||
| readonly runtime: boolean; | ||
| } | ||
| declare const LICENSED_FEATURES: Record<string, FeatureDefinition>; | ||
| declare function getFeatureDisplayName(feature: string): string; | ||
| declare function isComponentFeature(feature: string): boolean; | ||
| declare function isRuntimeFeature(feature: string): boolean; | ||
| //#endregion | ||
| //#region src/online-verifier.d.ts | ||
| interface OnlineVerifierOptions { | ||
| baseUrl?: string; | ||
| timeoutMs?: number; | ||
| } | ||
| declare const LICENSED_FEATURES: Readonly<Record<FeatureId, FeatureDefinition>>; | ||
| /** | ||
| * Create an online verifier. | ||
| * STUB: Always returns null until ops-api endpoints exist (Phase 6/7). | ||
| * Resolve a feature's display name from the shared catalog. | ||
| * | ||
| * @param feature - Candidate feature key. | ||
| * @returns Catalog display name, or the original key when unknown. | ||
| */ | ||
| declare function createOnlineVerifier(_options?: OnlineVerifierOptions): { | ||
| verifyOnline: (_token?: string) => Promise<OnlineVerifyResponse | null>; | ||
| fetchKeys: () => Promise<KeyDeliveryResponse["keys"] | null>; | ||
| }; | ||
| //#endregion | ||
| //#region src/context.d.ts | ||
| declare function getFeatureDisplayName(feature: string): string; | ||
| /** | ||
| * License context value exposed to child components. | ||
| * React providers create their own React Context using this shape. | ||
| * Return true when the feature controls client component availability. | ||
| * | ||
| * @param feature - Candidate feature key. | ||
| * @returns Whether the feature is component-scoped. | ||
| */ | ||
| interface LicenseContextValue { | ||
| /** The resolved license status after verification. Null if no token provided. */ | ||
| status: LicenseStatus | null; | ||
| /** Convenience: the license payload if valid, null otherwise. */ | ||
| license: LicensePayload | null; | ||
| /** Whether a specific feature is licensed. Returns true if no licensing is active (no token). */ | ||
| checkFeature: (feature: string) => boolean; | ||
| /** Get a numeric feature limit. Returns null if not applicable. */ | ||
| getLimit: (feature: string) => number | null; | ||
| } | ||
| declare function isComponentFeature(feature: string): boolean; | ||
| /** | ||
| * Create a license context value from a verification result. | ||
| * When no token is provided (status is null), all features return true (unlicensed = unrestricted, with branding). | ||
| * Return true when the feature controls runtime/server behavior. | ||
| * | ||
| * @param feature - Candidate feature key. | ||
| * @returns Whether the feature is runtime-scoped. | ||
| */ | ||
| declare function createLicenseContextValue(status: LicenseStatus | null): LicenseContextValue; | ||
| declare function isRuntimeFeature(feature: string): boolean; | ||
| //#endregion | ||
| //#region src/license-check.d.ts | ||
| //# sourceMappingURL=context.d.ts.map | ||
| /** | ||
| * Resolve a feature definition by id. | ||
| * | ||
| * @param feature - Candidate feature key. | ||
| * @returns Feature definition, or null when unknown. | ||
| */ | ||
| /** | ||
| * Runtime-agnostic license checker that caches verification results | ||
@@ -186,3 +171,3 @@ * and re-evaluates expiration on each access for long-lived processes. | ||
| getStatus(): LicenseStatus; | ||
| /** Check whether a specific feature is enabled. Returns true when no token (soft enforcement). */ | ||
| /** Check whether a specific feature is enabled by a valid, non-expired license. */ | ||
| checkFeature(feature: string): boolean; | ||
@@ -195,13 +180,6 @@ } | ||
| * When no token is provided, falls back to `COPILOTKIT_LICENSE_TOKEN` env var. | ||
| * Missing/invalid tokens result in soft enforcement (features allowed, warnings emitted). | ||
| * Missing/invalid tokens never enable features; product surfaces own warnings | ||
| * and enforcement decisions outside this package. | ||
| */ | ||
| declare function createLicenseChecker(licenseToken?: string): LicenseChecker; | ||
| /** | ||
| * Generate a license warning HTTP header based on the checker's current status. | ||
| * Returns null when no warning is needed. | ||
| */ | ||
| declare function getLicenseWarningHeader(checker?: LicenseChecker): { | ||
| key: string; | ||
| value: string; | ||
| } | null; | ||
@@ -211,3 +189,3 @@ //#endregion | ||
| export { KeyAttestationData, KeyDeliveryResponse, LICENSED_FEATURES, LICENSE_PUBLIC_KEYS, LicenseChecker, LicenseContextValue, LicenseFeatures, LicenseMode, LicenseOwner, LicensePayload, LicenseStatus, LicenseTier, OnlineVerifyResponse, addRuntimeKey, clearRuntimeKeys, createLicenseChecker, createLicenseContextValue, createOnlineVerifier, getFeatureDisplayName, getFeatureLimit, getLicenseWarningHeader, getMasterPublicKey, getPublicKey, isComponentFeature, isFeatureEnabled, isRuntimeFeature, verifyKeyAttestation, verifyLicense }; | ||
| export { KeyAttestationData, LICENSED_FEATURES, LicenseChecker, LicenseFeatures, LicenseOwner, LicensePayload, LicenseStatus, LicenseTier, addRuntimeKeyAttestation, clearRuntimeKeys, createLicenseChecker, getFeatureDisplayName, getFeatureLimit, getMasterPublicKey, getPublicKey, isComponentFeature, isFeatureEnabled, isRuntimeFeature, verifyKeyAttestation, verifyLicense }; | ||
| //# sourceMappingURL=index.d.ts.map |
+1
-1
| { | ||
| "name": "@copilotkit/license-verifier", | ||
| "version": "0.2.0", | ||
| "version": "0.3.0", | ||
| "description": "CopilotKit license verification", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
| {"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/verify.ts","../src/keystore.ts","../src/feature-registry.ts","../src/online-verifier.ts","../src/context.ts","../src/license-check.ts"],"sourcesContent":null,"mappings":"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"} |
| {"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/verify.ts","../src/keystore.ts","../src/feature-registry.ts","../src/online-verifier.ts","../src/context.ts","../src/license-check.ts"],"sourcesContent":null,"mappings":"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"} |
| {"version":3,"file":"index.mjs","names":["key: string","parsed: unknown","LICENSE_PUBLIC_KEYS: Record<string, string>","runtimeKeys: Record<string, string>","keyId: string","publicKey: string","attestation: KeyAttestationData","data: string","token: string","license: LicensePayload | null","feature: string","LICENSED_FEATURES: Record<string, FeatureDefinition>","feature: string","_options?: OnlineVerifierOptions","_token?: string","status: LicenseStatus | null","feature: string","licenseToken?: string","initialStatus: LicenseStatus","cachedPayload: LicensePayload | null","signatureValid: boolean","feature: string","checker?: LicenseChecker"],"sources":["../src/shared.ts","../src/keystore.ts","../src/verify.ts","../src/feature-registry.ts","../src/online-verifier.ts","../src/context.ts","../src/license-check.ts"],"sourcesContent":["/** Number of days after license expiration before hard enforcement kicks in. */\nexport const GRACE_PERIOD_DAYS = 7;\n\n/**\n * Split a base64 key string into 64-char PEM lines.\n * Throws if the key is empty or not valid base64 content.\n */\nexport function splitBase64(key: string): string[] {\n const lines = key.match(/.{1,64}/g);\n if (!lines) {\n throw new Error(\"Invalid key material: empty or malformed base64 string\");\n }\n return lines;\n}\n","import * as crypto from \"crypto\";\nimport { splitBase64 } from \"./shared\";\n\n/**\n * Parse the baked-in license keys JSON.\n * At build time, tsdown `env` replaces process.env.BAKED_LICENSE_KEYS_JSON with a string literal.\n * At runtime (tests / unbaked), the env var is not set so this returns {}.\n */\nfunction parseBakedLicenseKeys(): Record<string, string> {\n try {\n const json = process.env.BAKED_LICENSE_KEYS_JSON;\n if (!json) return {};\n const parsed: unknown = JSON.parse(json);\n if (typeof parsed === \"object\" && parsed !== null && !Array.isArray(parsed)) {\n return parsed as Record<string, string>;\n }\n return {};\n } catch {\n return {};\n }\n}\n\n/**\n * Master public key — root of trust.\n * Baked in at build time via tsdown `env` (replaces process.env.BAKED_MASTER_PUBLIC_KEY).\n * Not overridable at runtime — this is the root of the trust chain.\n */\nexport function getMasterPublicKey(): string | null {\n const baked = process.env.BAKED_MASTER_PUBLIC_KEY;\n return baked || null;\n}\n\n// License-signing keys — bundled at build time, augmented at runtime via /v1/keys.\nexport const LICENSE_PUBLIC_KEYS: Record<string, string> = parseBakedLicenseKeys();\n\n// Runtime keys fetched from licensing.copilotkit.ai/v1/keys\nconst runtimeKeys: Record<string, string> = {};\n\n/**\n * Get a public key by key ID.\n * Checks runtime keys first (network-delivered), then bundled keys.\n */\nexport function getPublicKey(keyId: string): string | null {\n return runtimeKeys[keyId] ?? LICENSE_PUBLIC_KEYS[keyId] ?? null;\n}\n\n/**\n * Add a runtime key fetched from the network.\n * Only call this after verifying the key's attestation.\n */\nexport function addRuntimeKey(keyId: string, publicKey: string): void {\n runtimeKeys[keyId] = publicKey;\n}\n\n/** Remove all runtime keys from the in-memory registry. */\nexport function clearRuntimeKeys(): void {\n for (const key of Object.keys(runtimeKeys)) {\n delete runtimeKeys[key];\n }\n}\n\nexport interface KeyAttestationData {\n keyId: string;\n publicKey: string;\n attestationSig: string;\n}\n\n/**\n * Verify a key attestation against the master public key.\n * The attestation is a signature of `keyId:publicKey` by the master key.\n */\nexport function verifyKeyAttestation(attestation: KeyAttestationData): boolean {\n try {\n const masterKey = getMasterPublicKey();\n if (!masterKey) {\n return false;\n }\n\n const message = `${attestation.keyId}:${attestation.publicKey}`;\n const signature = Buffer.from(attestation.attestationSig, \"base64\");\n\n const pemKey =\n \"-----BEGIN PUBLIC KEY-----\\n\" +\n splitBase64(masterKey).join(\"\\n\") +\n \"\\n-----END PUBLIC KEY-----\";\n const publicKey = crypto.createPublicKey(pemKey);\n\n return crypto.verify(null, Buffer.from(message), publicKey, signature);\n } catch {\n return false;\n }\n}\n","import * as crypto from \"crypto\";\nimport type { LicensePayload, LicenseStatus } from \"./types\";\nimport { getPublicKey } from \"./keystore\";\nimport { splitBase64, GRACE_PERIOD_DAYS } from \"./shared\";\n\n/**\n * Decode a base64url-encoded string to a Buffer.\n */\nfunction base64UrlDecode(data: string): Buffer {\n let padded = data.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const padding = (4 - (padded.length % 4)) % 4;\n padded += \"=\".repeat(padding);\n return Buffer.from(padded, \"base64\");\n}\n\n/**\n * Parse a 3-part license token: header.payload.signature\n * Header format: { alg: \"EdDSA\", typ: \"LIC\", kid: \"<key_id>\" }\n */\nfunction parseToken(token: string): {\n header: { alg: string; typ: string; kid: string };\n payload: LicensePayload;\n signature: Buffer;\n signingInput: string;\n} | null {\n if (!token || typeof token !== \"string\") return null;\n const parts = token.split(\".\");\n if (parts.length !== 3) return null;\n\n try {\n const [headerPart, payloadPart, signaturePart] = parts as [string, string, string];\n const header = JSON.parse(base64UrlDecode(headerPart).toString(\"utf-8\"));\n const payload = JSON.parse(base64UrlDecode(payloadPart).toString(\"utf-8\"));\n const signature = base64UrlDecode(signaturePart);\n\n if (header.alg !== \"EdDSA\" || header.typ !== \"LIC\") return null;\n\n return { header, payload, signature, signingInput: `${headerPart}.${payloadPart}` };\n } catch {\n return null;\n }\n}\n\n/**\n * Verify a license token offline using Ed25519 signature.\n * This is a pure function — no caching. Callers should cache the result.\n */\nexport function verifyLicense(token: string): LicenseStatus {\n const parsed = parseToken(token);\n if (!parsed) {\n return { valid: false, license: null, error: \"parse_error\", warningSeverity: \"critical\" };\n }\n\n const publicKeyBase64 = getPublicKey(parsed.header.kid);\n if (!publicKeyBase64) {\n return {\n valid: false,\n license: parsed.payload,\n error: \"unknown_key\",\n warningSeverity: \"critical\",\n };\n }\n\n try {\n const pemKey =\n \"-----BEGIN PUBLIC KEY-----\\n\" +\n splitBase64(publicKeyBase64).join(\"\\n\") +\n \"\\n-----END PUBLIC KEY-----\";\n const publicKey = crypto.createPublicKey(pemKey);\n const isValid = crypto.verify(null, Buffer.from(parsed.signingInput), publicKey, parsed.signature);\n\n if (!isValid) {\n return {\n valid: false,\n license: parsed.payload,\n error: \"invalid_signature\",\n warningSeverity: \"critical\",\n };\n }\n } catch {\n return {\n valid: false,\n license: parsed.payload,\n error: \"invalid_signature\",\n warningSeverity: \"critical\",\n };\n }\n\n // Check expiration\n const expiresAt = new Date(parsed.payload.expires_at);\n const now = new Date();\n if (expiresAt < now) {\n const daysSinceExpiry = Math.floor((now.getTime() - expiresAt.getTime()) / (24 * 60 * 60 * 1000));\n const graceRemaining = GRACE_PERIOD_DAYS - daysSinceExpiry;\n\n if (graceRemaining <= 0) {\n return {\n valid: false,\n license: parsed.payload,\n error: \"expired\",\n warningSeverity: \"critical\",\n };\n }\n\n return {\n valid: true,\n license: parsed.payload,\n error: null,\n graceRemaining,\n warningSeverity: \"warning\",\n };\n }\n\n return { valid: true, license: parsed.payload, error: null, warningSeverity: \"none\" };\n}\n\n/**\n * Check whether a specific feature is enabled in the license.\n * Returns false if the license is null or the feature is not present (deny by default).\n */\nexport function isFeatureEnabled(license: LicensePayload | null, feature: string): boolean {\n if (!license) return false;\n return license.features[feature] === true;\n}\n\n/**\n * Get a numeric feature limit from the license.\n * Returns null if the license is null, the feature is missing, or the value is not a number.\n */\nexport function getFeatureLimit(license: LicensePayload | null, feature: string): number | null {\n if (!license) return null;\n const value = license.features[feature];\n return typeof value === \"number\" ? value : null;\n}\n","interface FeatureDefinition {\n displayName: string;\n component?: boolean;\n runtime?: boolean;\n}\n\nexport const LICENSED_FEATURES: Record<string, FeatureDefinition> = {\n chat: { displayName: \"Chat\", component: true },\n sidebar: { displayName: \"Sidebar\", component: true },\n popup: { displayName: \"Popup\", component: true },\n suggestions: { displayName: \"Suggestions\", component: true },\n agents: { displayName: \"Agents\", runtime: true },\n voice: { displayName: \"Voice\", component: true, runtime: true },\n frontend_tools: { displayName: \"Frontend Tools\", component: true },\n human_in_the_loop: { displayName: \"Human-in-the-Loop\", component: true },\n mcp_integration: { displayName: \"MCP Integration\", runtime: true },\n custom_activity_renderers: { displayName: \"Activity Renderers\", component: true },\n headless_ui: { displayName: \"Headless UI\", component: true },\n dev_console: { displayName: \"Dev Console\", component: true },\n guardrails: { displayName: \"Guardrails\", runtime: true },\n};\n\nexport function getFeatureDisplayName(feature: string): string {\n return LICENSED_FEATURES[feature]?.displayName ?? feature;\n}\n\nexport function isComponentFeature(feature: string): boolean {\n return LICENSED_FEATURES[feature]?.component === true;\n}\n\nexport function isRuntimeFeature(feature: string): boolean {\n return LICENSED_FEATURES[feature]?.runtime === true;\n}\n","import type { OnlineVerifyResponse, KeyDeliveryResponse } from \"./types\";\n\ninterface OnlineVerifierOptions {\n baseUrl?: string;\n timeoutMs?: number;\n}\n\n/**\n * Create an online verifier.\n * STUB: Always returns null until ops-api endpoints exist (Phase 6/7).\n */\n// eslint-disable-next-line @typescript-eslint/no-unused-vars -- stub params reserved for Phase 7 implementation\nexport function createOnlineVerifier(_options?: OnlineVerifierOptions) {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- stub params reserved for Phase 7 implementation\n async function verifyOnline(_token?: string): Promise<OnlineVerifyResponse | null> {\n // TODO: Implement in Phase 7 when ops-api /v1/verify exists\n return null;\n }\n\n async function fetchKeys(): Promise<KeyDeliveryResponse[\"keys\"] | null> {\n // TODO: Implement in Phase 7 when ops-api /v1/keys exists\n return null;\n }\n\n return { verifyOnline, fetchKeys };\n}\n","import type { LicenseStatus, LicensePayload } from \"./types\";\n\n/**\n * License context value exposed to child components.\n * React providers create their own React Context using this shape.\n */\nexport interface LicenseContextValue {\n /** The resolved license status after verification. Null if no token provided. */\n status: LicenseStatus | null;\n /** Convenience: the license payload if valid, null otherwise. */\n license: LicensePayload | null;\n /** Whether a specific feature is licensed. Returns true if no licensing is active (no token). */\n checkFeature: (feature: string) => boolean;\n /** Get a numeric feature limit. Returns null if not applicable. */\n getLimit: (feature: string) => number | null;\n}\n\n/**\n * Create a license context value from a verification result.\n * When no token is provided (status is null), all features return true (unlicensed = unrestricted, with branding).\n */\nexport function createLicenseContextValue(\n status: LicenseStatus | null,\n): LicenseContextValue {\n const license = status?.valid ? status.license : null;\n\n return {\n status,\n license,\n checkFeature(feature: string): boolean {\n if (!status) return true; // No licensing active — features work but show branding\n if (!status.valid) return true; // Invalid license — features work but show warnings\n if (!status.license) return true;\n return status.license.features[feature] === true;\n },\n getLimit(feature: string): number | null {\n if (!license) return null;\n const val = license.features[feature];\n return typeof val === \"number\" ? val : null;\n },\n };\n}\n","import { verifyLicense, isFeatureEnabled } from \"./verify\";\nimport type { LicenseStatus, LicensePayload } from \"./types\";\nimport { GRACE_PERIOD_DAYS } from \"./shared\";\n\n/**\n * Runtime-agnostic license checker that caches verification results\n * and re-evaluates expiration on each access for long-lived processes.\n */\nexport interface LicenseChecker {\n /** Get the current license status, re-evaluating expiration. */\n getStatus(): LicenseStatus;\n /** Check whether a specific feature is enabled. Returns true when no token (soft enforcement). */\n checkFeature(feature: string): boolean;\n}\n\n/**\n * Create a license checker that verifies the token once at construction\n * and re-evaluates expiration on each `getStatus()` call.\n *\n * When no token is provided, falls back to `COPILOTKIT_LICENSE_TOKEN` env var.\n * Missing/invalid tokens result in soft enforcement (features allowed, warnings emitted).\n */\nexport function createLicenseChecker(licenseToken?: string): LicenseChecker {\n const token = licenseToken ?? process.env.COPILOTKIT_LICENSE_TOKEN;\n\n let initialStatus: LicenseStatus;\n if (token) {\n initialStatus = verifyLicense(token);\n if (!initialStatus.valid) {\n console.warn(\n \"\\n\" +\n \"**********************************************************\\n\" +\n \"* *\\n\" +\n `* [CopilotKit] License error: ${(initialStatus.error ?? \"unknown\").padEnd(25)}*\\n` +\n \"* Visit copilotkit.ai/pricing for a valid license. *\\n\" +\n \"* *\\n\" +\n \"**********************************************************\\n\",\n );\n }\n } else {\n console.warn(\n \"\\n\" +\n \"**********************************************************\\n\" +\n \"* *\\n\" +\n \"* [CopilotKit] No license token configured. *\\n\" +\n \"* Visit copilotkit.ai/pricing to get a license. *\\n\" +\n \"* *\\n\" +\n \"**********************************************************\\n\",\n );\n initialStatus = { valid: false, license: null, error: null, warningSeverity: \"info\" };\n }\n\n const cachedPayload: LicensePayload | null = initialStatus.license;\n const signatureValid: boolean = initialStatus.license !== null && initialStatus.error === null;\n\n function getStatus(): LicenseStatus {\n if (!cachedPayload || !signatureValid) return initialStatus;\n\n const expiresAt = new Date(cachedPayload.expires_at);\n const now = new Date();\n\n if (expiresAt >= now) {\n return { valid: true, license: cachedPayload, error: null, warningSeverity: \"none\" };\n }\n\n const daysSinceExpiry = Math.floor((now.getTime() - expiresAt.getTime()) / (24 * 60 * 60 * 1000));\n const graceRemaining = GRACE_PERIOD_DAYS - daysSinceExpiry;\n\n if (graceRemaining > 0) {\n return { valid: true, license: cachedPayload, error: null, graceRemaining, warningSeverity: \"warning\" };\n }\n\n return { valid: false, license: cachedPayload, error: \"expired\", warningSeverity: \"critical\" };\n }\n\n function checkFeature(feature: string): boolean {\n const status = getStatus();\n if (!status.license) return true;\n return isFeatureEnabled(status.license, feature);\n }\n\n return { getStatus, checkFeature };\n}\n\n/**\n * Generate a license warning HTTP header based on the checker's current status.\n * Returns null when no warning is needed.\n */\nexport function getLicenseWarningHeader(\n checker?: LicenseChecker,\n): { key: string; value: string } | null {\n if (!checker) return null;\n const status = checker.getStatus();\n if (status.warningSeverity === \"critical\") {\n console.warn(\"[CopilotKit] License expired. Visit copilotkit.ai/pricing\");\n return { key: \"X-CopilotKit-License-Warning\", value: status.error ?? \"expired\" };\n }\n if (status.warningSeverity === \"warning\") {\n console.warn(`[CopilotKit] License expires in ${status.graceRemaining} days. Please renew.`);\n return { key: \"X-CopilotKit-License-Warning\", value: \"expiring\" };\n }\n return null;\n}\n"],"mappings":"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"} |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Obfuscated code
Supply chain riskObfuscated files are intentionally packed to hide their behavior. This could be a sign of malware.
Found 2 instances
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Obfuscated code
Supply chain riskObfuscated files are intentionally packed to hide their behavior. This could be a sign of malware.
Found 2 instances
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
No README
QualityPackage does not have a README. This may indicate a failed publish or a low quality package.
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
639128
613.62%0
-100%48
Infinity%0
-100%6
-25%174
-10.77%