@nxuss/lemma 1.43.0 → 1.45.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.
- package/README.md +26 -8
- package/bin/brain-ingest.js +48 -13
- package/bin/cloud.js +228 -0
- package/dist/cjs/cli/hostHooks.d.ts +44 -7
- package/dist/cjs/cli/hostHooks.d.ts.map +1 -1
- package/dist/cjs/cli/hostHooks.js +201 -11
- package/dist/cjs/cli/hostHooks.js.map +1 -1
- package/dist/cjs/cli/lemma-proxy.d.ts.map +1 -1
- package/dist/cjs/cli/lemma-proxy.js +13 -16
- package/dist/cjs/cli/lemma-proxy.js.map +1 -1
- package/dist/cjs/cloud/CloudBrainClient.d.ts +52 -0
- package/dist/cjs/cloud/CloudBrainClient.d.ts.map +1 -0
- package/dist/cjs/cloud/CloudBrainClient.js +161 -0
- package/dist/cjs/cloud/CloudBrainClient.js.map +1 -0
- package/dist/cjs/cloud/CloudConfig.d.ts +41 -0
- package/dist/cjs/cloud/CloudConfig.d.ts.map +1 -0
- package/dist/cjs/cloud/CloudConfig.js +133 -0
- package/dist/cjs/cloud/CloudConfig.js.map +1 -0
- package/dist/cjs/cloud/CloudEntitlement.d.ts +55 -0
- package/dist/cjs/cloud/CloudEntitlement.d.ts.map +1 -0
- package/dist/cjs/cloud/CloudEntitlement.js +174 -0
- package/dist/cjs/cloud/CloudEntitlement.js.map +1 -0
- package/dist/cjs/cloud/billing/stripeApi.d.ts +43 -0
- package/dist/cjs/cloud/billing/stripeApi.d.ts.map +1 -0
- package/dist/cjs/cloud/billing/stripeApi.js +116 -0
- package/dist/cjs/cloud/billing/stripeApi.js.map +1 -0
- package/dist/cjs/cloud/billing/stripeWebhook.d.ts +35 -0
- package/dist/cjs/cloud/billing/stripeWebhook.d.ts.map +1 -0
- package/dist/cjs/cloud/billing/stripeWebhook.js +190 -0
- package/dist/cjs/cloud/billing/stripeWebhook.js.map +1 -0
- package/dist/cjs/cloud/console/ConsoleStore.d.ts +111 -0
- package/dist/cjs/cloud/console/ConsoleStore.d.ts.map +1 -0
- package/dist/cjs/cloud/console/ConsoleStore.js +172 -0
- package/dist/cjs/cloud/console/ConsoleStore.js.map +1 -0
- package/dist/cjs/cloud/console/consoleRouter.d.ts +68 -0
- package/dist/cjs/cloud/console/consoleRouter.d.ts.map +1 -0
- package/dist/cjs/cloud/console/consoleRouter.js +301 -0
- package/dist/cjs/cloud/console/consoleRouter.js.map +1 -0
- package/dist/cjs/cloud/console/mailer.d.ts +22 -0
- package/dist/cjs/cloud/console/mailer.d.ts.map +1 -0
- package/dist/cjs/cloud/console/mailer.js +35 -0
- package/dist/cjs/cloud/console/mailer.js.map +1 -0
- package/dist/cjs/cloud/identity/PlanPolicy.d.ts +42 -6
- package/dist/cjs/cloud/identity/PlanPolicy.d.ts.map +1 -1
- package/dist/cjs/cloud/identity/PlanPolicy.js +102 -22
- package/dist/cjs/cloud/identity/PlanPolicy.js.map +1 -1
- package/dist/cjs/cloud/identity/RateLimiter.d.ts +21 -1
- package/dist/cjs/cloud/identity/RateLimiter.d.ts.map +1 -1
- package/dist/cjs/cloud/identity/RateLimiter.js +59 -2
- package/dist/cjs/cloud/identity/RateLimiter.js.map +1 -1
- package/dist/cjs/cloud/identity/TenantResolver.d.ts +6 -1
- package/dist/cjs/cloud/identity/TenantResolver.d.ts.map +1 -1
- package/dist/cjs/cloud/identity/TenantResolver.js +1 -1
- package/dist/cjs/cloud/identity/TenantResolver.js.map +1 -1
- package/dist/cjs/cloud/identity/authenticateV2.d.ts.map +1 -1
- package/dist/cjs/cloud/identity/authenticateV2.js +7 -4
- package/dist/cjs/cloud/identity/authenticateV2.js.map +1 -1
- package/dist/cjs/cloud/identity/identityStore.d.ts +96 -10
- package/dist/cjs/cloud/identity/identityStore.d.ts.map +1 -1
- package/dist/cjs/cloud/identity/identityStore.js +203 -4
- package/dist/cjs/cloud/identity/identityStore.js.map +1 -1
- package/dist/cjs/cloud/metering/PostgresLedgerStore.d.ts +18 -0
- package/dist/cjs/cloud/metering/PostgresLedgerStore.d.ts.map +1 -0
- package/dist/cjs/cloud/metering/PostgresLedgerStore.js +56 -0
- package/dist/cjs/cloud/metering/PostgresLedgerStore.js.map +1 -0
- package/dist/cjs/cloud/metering/UsageLedger.d.ts +74 -0
- package/dist/cjs/cloud/metering/UsageLedger.d.ts.map +1 -1
- package/dist/cjs/cloud/metering/UsageLedger.js +122 -17
- package/dist/cjs/cloud/metering/UsageLedger.js.map +1 -1
- package/dist/cjs/cloud/metering/index.d.ts +1 -0
- package/dist/cjs/cloud/metering/index.d.ts.map +1 -1
- package/dist/cjs/cloud/metering/index.js +1 -0
- package/dist/cjs/cloud/metering/index.js.map +1 -1
- package/dist/cjs/cloud/store/FileBrainStore.d.ts +6 -1
- package/dist/cjs/cloud/store/FileBrainStore.d.ts.map +1 -1
- package/dist/cjs/cloud/store/FileBrainStore.js +8 -0
- package/dist/cjs/cloud/store/FileBrainStore.js.map +1 -1
- package/dist/cjs/cloud/store/PostgresBrainStore.d.ts +11 -1
- package/dist/cjs/cloud/store/PostgresBrainStore.d.ts.map +1 -1
- package/dist/cjs/cloud/store/PostgresBrainStore.js +32 -0
- package/dist/cjs/cloud/store/PostgresBrainStore.js.map +1 -1
- package/dist/cjs/cloud/store/memorySummary.d.ts +29 -0
- package/dist/cjs/cloud/store/memorySummary.d.ts.map +1 -0
- package/dist/cjs/cloud/store/memorySummary.js +66 -0
- package/dist/cjs/cloud/store/memorySummary.js.map +1 -0
- package/dist/cjs/cloud/v2/app.d.ts.map +1 -1
- package/dist/cjs/cloud/v2/app.js +6 -0
- package/dist/cjs/cloud/v2/app.js.map +1 -1
- package/dist/cjs/cloud/v2/inputGuard.d.ts +23 -0
- package/dist/cjs/cloud/v2/inputGuard.d.ts.map +1 -0
- package/dist/cjs/cloud/v2/inputGuard.js +71 -0
- package/dist/cjs/cloud/v2/inputGuard.js.map +1 -0
- package/dist/cjs/cloud/v2/routes/admin.d.ts +24 -0
- package/dist/cjs/cloud/v2/routes/admin.d.ts.map +1 -0
- package/dist/cjs/cloud/v2/routes/admin.js +344 -0
- package/dist/cjs/cloud/v2/routes/admin.js.map +1 -0
- package/dist/cjs/cloud/v2/routes/entitlement.d.ts +13 -0
- package/dist/cjs/cloud/v2/routes/entitlement.d.ts.map +1 -0
- package/dist/cjs/cloud/v2/routes/entitlement.js +24 -0
- package/dist/cjs/cloud/v2/routes/entitlement.js.map +1 -0
- package/dist/cjs/cloud/v2/routes/index.d.ts +14 -1
- package/dist/cjs/cloud/v2/routes/index.d.ts.map +1 -1
- package/dist/cjs/cloud/v2/routes/index.js +36 -0
- package/dist/cjs/cloud/v2/routes/index.js.map +1 -1
- package/dist/cjs/cloud/v2/routes/memories.d.ts +21 -2
- package/dist/cjs/cloud/v2/routes/memories.d.ts.map +1 -1
- package/dist/cjs/cloud/v2/routes/memories.js +77 -0
- package/dist/cjs/cloud/v2/routes/memories.js.map +1 -1
- package/dist/cjs/cloud/v2/routes/recall.d.ts +1 -0
- package/dist/cjs/cloud/v2/routes/recall.d.ts.map +1 -1
- package/dist/cjs/cloud/v2/routes/recall.js +4 -0
- package/dist/cjs/cloud/v2/routes/recall.js.map +1 -1
- package/dist/cjs/cloud/v2/routes/tenant.d.ts +36 -0
- package/dist/cjs/cloud/v2/routes/tenant.d.ts.map +1 -0
- package/dist/cjs/cloud/v2/routes/tenant.js +65 -0
- package/dist/cjs/cloud/v2/routes/tenant.js.map +1 -0
- package/dist/cjs/cloud/v2/routes/usage.d.ts +1 -1
- package/dist/cjs/cloud/v2/routes/usage.d.ts.map +1 -1
- package/dist/cjs/cloud/v2/routes/verify.d.ts +1 -0
- package/dist/cjs/cloud/v2/routes/verify.d.ts.map +1 -1
- package/dist/cjs/cloud/v2/routes/verify.js +4 -0
- package/dist/cjs/cloud/v2/routes/verify.js.map +1 -1
- package/dist/cjs/cloud/v2/server.d.ts +9 -3
- package/dist/cjs/cloud/v2/server.d.ts.map +1 -1
- package/dist/cjs/cloud/v2/server.js +36 -2
- package/dist/cjs/cloud/v2/server.js.map +1 -1
- package/dist/cjs/cloud/v2/usageRecorder.d.ts +19 -0
- package/dist/cjs/cloud/v2/usageRecorder.d.ts.map +1 -0
- package/dist/cjs/cloud/v2/usageRecorder.js +42 -0
- package/dist/cjs/cloud/v2/usageRecorder.js.map +1 -0
- package/dist/cjs/contracts/api-v2.types.d.ts +92 -2
- package/dist/cjs/contracts/api-v2.types.d.ts.map +1 -1
- package/dist/cjs/contracts/store.d.ts +37 -0
- package/dist/cjs/contracts/store.d.ts.map +1 -1
- package/dist/cjs/mcp/index.js +7 -1
- package/dist/cjs/mcp/index.js.map +1 -1
- package/dist/cjs/mcp/tools/memory.d.ts.map +1 -1
- package/dist/cjs/mcp/tools/memory.js +74 -4
- package/dist/cjs/mcp/tools/memory.js.map +1 -1
- package/dist/cjs/mcp/tools/misc.d.ts.map +1 -1
- package/dist/cjs/mcp/tools/misc.js +2 -1
- package/dist/cjs/mcp/tools/misc.js.map +1 -1
- package/dist/cjs/mcp/tools/workspace.d.ts.map +1 -1
- package/dist/cjs/mcp/tools/workspace.js +4 -1
- package/dist/cjs/mcp/tools/workspace.js.map +1 -1
- package/dist/cjs/mcp/tools.d.ts +10 -0
- package/dist/cjs/mcp/tools.d.ts.map +1 -1
- package/dist/cjs/mcp/tools.js +47 -12
- package/dist/cjs/mcp/tools.js.map +1 -1
- package/dist/cjs/proxy/KeyManager.d.ts.map +1 -1
- package/dist/cjs/proxy/KeyManager.js +5 -0
- package/dist/cjs/proxy/KeyManager.js.map +1 -1
- package/dist/cjs/subconscious/CloudBrain.d.ts +77 -0
- package/dist/cjs/subconscious/CloudBrain.d.ts.map +1 -0
- package/dist/cjs/subconscious/CloudBrain.js +347 -0
- package/dist/cjs/subconscious/CloudBrain.js.map +1 -0
- package/dist/cjs/subconscious/HostRecall.d.ts.map +1 -1
- package/dist/cjs/subconscious/HostRecall.js +11 -4
- package/dist/cjs/subconscious/HostRecall.js.map +1 -1
- package/dist/cjs/subconscious/ProjectIdentity.d.ts +9 -0
- package/dist/cjs/subconscious/ProjectIdentity.d.ts.map +1 -0
- package/dist/cjs/subconscious/ProjectIdentity.js +63 -0
- package/dist/cjs/subconscious/ProjectIdentity.js.map +1 -0
- package/dist/cjs/subconscious/TeamBrain.d.ts +9 -3
- package/dist/cjs/subconscious/TeamBrain.d.ts.map +1 -1
- package/dist/cjs/subconscious/TeamBrain.js +39 -5
- package/dist/cjs/subconscious/TeamBrain.js.map +1 -1
- package/dist/cjs/utils/FixCapture.d.ts +7 -5
- package/dist/cjs/utils/FixCapture.d.ts.map +1 -1
- package/dist/cjs/utils/FixCapture.js +64 -32
- package/dist/cjs/utils/FixCapture.js.map +1 -1
- package/dist/cjs/utils/NoTerminal.d.ts +27 -0
- package/dist/cjs/utils/NoTerminal.d.ts.map +1 -0
- package/dist/cjs/utils/NoTerminal.js +37 -0
- package/dist/cjs/utils/NoTerminal.js.map +1 -0
- package/dist/cjs/utils/OpenCodeSession.d.ts +70 -0
- package/dist/cjs/utils/OpenCodeSession.d.ts.map +1 -0
- package/dist/cjs/utils/OpenCodeSession.js +154 -0
- package/dist/cjs/utils/OpenCodeSession.js.map +1 -0
- package/dist/cjs/utils/ProLicense.d.ts.map +1 -1
- package/dist/cjs/utils/ProLicense.js +11 -3
- package/dist/cjs/utils/ProLicense.js.map +1 -1
- package/dist/cjs/utils/SessionCapture.d.ts +31 -7
- package/dist/cjs/utils/SessionCapture.d.ts.map +1 -1
- package/dist/cjs/utils/SessionCapture.js +185 -32
- package/dist/cjs/utils/SessionCapture.js.map +1 -1
- package/dist/cjs/utils/StopNudge.d.ts +8 -0
- package/dist/cjs/utils/StopNudge.d.ts.map +1 -0
- package/dist/cjs/utils/StopNudge.js +93 -0
- package/dist/cjs/utils/StopNudge.js.map +1 -0
- package/dist/cjs/utils/TestAutofixInterceptor.d.ts.map +1 -1
- package/dist/cjs/utils/TestAutofixInterceptor.js +2 -0
- package/dist/cjs/utils/TestAutofixInterceptor.js.map +1 -1
- package/dist/esm/cli/hostHooks.d.ts +44 -7
- package/dist/esm/cli/hostHooks.d.ts.map +1 -1
- package/dist/esm/cli/hostHooks.js +199 -10
- package/dist/esm/cli/hostHooks.js.map +1 -1
- package/dist/esm/cli/lemma-proxy.d.ts.map +1 -1
- package/dist/esm/cli/lemma-proxy.js +14 -17
- package/dist/esm/cli/lemma-proxy.js.map +1 -1
- package/dist/esm/cloud/CloudBrainClient.d.ts +52 -0
- package/dist/esm/cloud/CloudBrainClient.d.ts.map +1 -0
- package/dist/esm/cloud/CloudBrainClient.js +153 -0
- package/dist/esm/cloud/CloudBrainClient.js.map +1 -0
- package/dist/esm/cloud/CloudConfig.d.ts +41 -0
- package/dist/esm/cloud/CloudConfig.d.ts.map +1 -0
- package/dist/esm/cloud/CloudConfig.js +118 -0
- package/dist/esm/cloud/CloudConfig.js.map +1 -0
- package/dist/esm/cloud/CloudEntitlement.d.ts +55 -0
- package/dist/esm/cloud/CloudEntitlement.d.ts.map +1 -0
- package/dist/esm/cloud/CloudEntitlement.js +159 -0
- package/dist/esm/cloud/CloudEntitlement.js.map +1 -0
- package/dist/esm/cloud/billing/stripeApi.d.ts +43 -0
- package/dist/esm/cloud/billing/stripeApi.d.ts.map +1 -0
- package/dist/esm/cloud/billing/stripeApi.js +108 -0
- package/dist/esm/cloud/billing/stripeApi.js.map +1 -0
- package/dist/esm/cloud/billing/stripeWebhook.d.ts +35 -0
- package/dist/esm/cloud/billing/stripeWebhook.d.ts.map +1 -0
- package/dist/esm/cloud/billing/stripeWebhook.js +181 -0
- package/dist/esm/cloud/billing/stripeWebhook.js.map +1 -0
- package/dist/esm/cloud/console/ConsoleStore.d.ts +111 -0
- package/dist/esm/cloud/console/ConsoleStore.d.ts.map +1 -0
- package/dist/esm/cloud/console/ConsoleStore.js +161 -0
- package/dist/esm/cloud/console/ConsoleStore.js.map +1 -0
- package/dist/esm/cloud/console/consoleRouter.d.ts +68 -0
- package/dist/esm/cloud/console/consoleRouter.d.ts.map +1 -0
- package/dist/esm/cloud/console/consoleRouter.js +290 -0
- package/dist/esm/cloud/console/consoleRouter.js.map +1 -0
- package/dist/esm/cloud/console/mailer.d.ts +22 -0
- package/dist/esm/cloud/console/mailer.d.ts.map +1 -0
- package/dist/esm/cloud/console/mailer.js +30 -0
- package/dist/esm/cloud/console/mailer.js.map +1 -0
- package/dist/esm/cloud/identity/PlanPolicy.d.ts +42 -6
- package/dist/esm/cloud/identity/PlanPolicy.d.ts.map +1 -1
- package/dist/esm/cloud/identity/PlanPolicy.js +100 -21
- package/dist/esm/cloud/identity/PlanPolicy.js.map +1 -1
- package/dist/esm/cloud/identity/RateLimiter.d.ts +21 -1
- package/dist/esm/cloud/identity/RateLimiter.d.ts.map +1 -1
- package/dist/esm/cloud/identity/RateLimiter.js +57 -2
- package/dist/esm/cloud/identity/RateLimiter.js.map +1 -1
- package/dist/esm/cloud/identity/TenantResolver.d.ts +6 -1
- package/dist/esm/cloud/identity/TenantResolver.d.ts.map +1 -1
- package/dist/esm/cloud/identity/TenantResolver.js +1 -1
- package/dist/esm/cloud/identity/TenantResolver.js.map +1 -1
- package/dist/esm/cloud/identity/authenticateV2.d.ts.map +1 -1
- package/dist/esm/cloud/identity/authenticateV2.js +7 -4
- package/dist/esm/cloud/identity/authenticateV2.js.map +1 -1
- package/dist/esm/cloud/identity/identityStore.d.ts +96 -10
- package/dist/esm/cloud/identity/identityStore.d.ts.map +1 -1
- package/dist/esm/cloud/identity/identityStore.js +199 -3
- package/dist/esm/cloud/identity/identityStore.js.map +1 -1
- package/dist/esm/cloud/metering/PostgresLedgerStore.d.ts +18 -0
- package/dist/esm/cloud/metering/PostgresLedgerStore.d.ts.map +1 -0
- package/dist/esm/cloud/metering/PostgresLedgerStore.js +52 -0
- package/dist/esm/cloud/metering/PostgresLedgerStore.js.map +1 -0
- package/dist/esm/cloud/metering/UsageLedger.d.ts +74 -0
- package/dist/esm/cloud/metering/UsageLedger.d.ts.map +1 -1
- package/dist/esm/cloud/metering/UsageLedger.js +119 -16
- package/dist/esm/cloud/metering/UsageLedger.js.map +1 -1
- package/dist/esm/cloud/metering/index.d.ts +1 -0
- package/dist/esm/cloud/metering/index.d.ts.map +1 -1
- package/dist/esm/cloud/metering/index.js +1 -0
- package/dist/esm/cloud/metering/index.js.map +1 -1
- package/dist/esm/cloud/store/FileBrainStore.d.ts +6 -1
- package/dist/esm/cloud/store/FileBrainStore.d.ts.map +1 -1
- package/dist/esm/cloud/store/FileBrainStore.js +8 -0
- package/dist/esm/cloud/store/FileBrainStore.js.map +1 -1
- package/dist/esm/cloud/store/PostgresBrainStore.d.ts +11 -1
- package/dist/esm/cloud/store/PostgresBrainStore.d.ts.map +1 -1
- package/dist/esm/cloud/store/PostgresBrainStore.js +32 -0
- package/dist/esm/cloud/store/PostgresBrainStore.js.map +1 -1
- package/dist/esm/cloud/store/memorySummary.d.ts +29 -0
- package/dist/esm/cloud/store/memorySummary.d.ts.map +1 -0
- package/dist/esm/cloud/store/memorySummary.js +60 -0
- package/dist/esm/cloud/store/memorySummary.js.map +1 -0
- package/dist/esm/cloud/v2/app.d.ts.map +1 -1
- package/dist/esm/cloud/v2/app.js +6 -0
- package/dist/esm/cloud/v2/app.js.map +1 -1
- package/dist/esm/cloud/v2/inputGuard.d.ts +23 -0
- package/dist/esm/cloud/v2/inputGuard.d.ts.map +1 -0
- package/dist/esm/cloud/v2/inputGuard.js +63 -0
- package/dist/esm/cloud/v2/inputGuard.js.map +1 -0
- package/dist/esm/cloud/v2/routes/admin.d.ts +24 -0
- package/dist/esm/cloud/v2/routes/admin.d.ts.map +1 -0
- package/dist/esm/cloud/v2/routes/admin.js +337 -0
- package/dist/esm/cloud/v2/routes/admin.js.map +1 -0
- package/dist/esm/cloud/v2/routes/entitlement.d.ts +13 -0
- package/dist/esm/cloud/v2/routes/entitlement.d.ts.map +1 -0
- package/dist/esm/cloud/v2/routes/entitlement.js +21 -0
- package/dist/esm/cloud/v2/routes/entitlement.js.map +1 -0
- package/dist/esm/cloud/v2/routes/index.d.ts +14 -1
- package/dist/esm/cloud/v2/routes/index.d.ts.map +1 -1
- package/dist/esm/cloud/v2/routes/index.js +37 -1
- package/dist/esm/cloud/v2/routes/index.js.map +1 -1
- package/dist/esm/cloud/v2/routes/memories.d.ts +21 -2
- package/dist/esm/cloud/v2/routes/memories.d.ts.map +1 -1
- package/dist/esm/cloud/v2/routes/memories.js +75 -0
- package/dist/esm/cloud/v2/routes/memories.js.map +1 -1
- package/dist/esm/cloud/v2/routes/recall.d.ts +1 -0
- package/dist/esm/cloud/v2/routes/recall.d.ts.map +1 -1
- package/dist/esm/cloud/v2/routes/recall.js +5 -1
- package/dist/esm/cloud/v2/routes/recall.js.map +1 -1
- package/dist/esm/cloud/v2/routes/tenant.d.ts +36 -0
- package/dist/esm/cloud/v2/routes/tenant.d.ts.map +1 -0
- package/dist/esm/cloud/v2/routes/tenant.js +61 -0
- package/dist/esm/cloud/v2/routes/tenant.js.map +1 -0
- package/dist/esm/cloud/v2/routes/usage.d.ts +1 -1
- package/dist/esm/cloud/v2/routes/usage.d.ts.map +1 -1
- package/dist/esm/cloud/v2/routes/verify.d.ts +1 -0
- package/dist/esm/cloud/v2/routes/verify.d.ts.map +1 -1
- package/dist/esm/cloud/v2/routes/verify.js +5 -1
- package/dist/esm/cloud/v2/routes/verify.js.map +1 -1
- package/dist/esm/cloud/v2/server.d.ts +9 -3
- package/dist/esm/cloud/v2/server.d.ts.map +1 -1
- package/dist/esm/cloud/v2/server.js +36 -3
- package/dist/esm/cloud/v2/server.js.map +1 -1
- package/dist/esm/cloud/v2/usageRecorder.d.ts +19 -0
- package/dist/esm/cloud/v2/usageRecorder.d.ts.map +1 -0
- package/dist/esm/cloud/v2/usageRecorder.js +37 -0
- package/dist/esm/cloud/v2/usageRecorder.js.map +1 -0
- package/dist/esm/contracts/api-v2.types.d.ts +92 -2
- package/dist/esm/contracts/api-v2.types.d.ts.map +1 -1
- package/dist/esm/contracts/store.d.ts +37 -0
- package/dist/esm/contracts/store.d.ts.map +1 -1
- package/dist/esm/mcp/index.js +8 -2
- package/dist/esm/mcp/index.js.map +1 -1
- package/dist/esm/mcp/tools/memory.d.ts.map +1 -1
- package/dist/esm/mcp/tools/memory.js +74 -4
- package/dist/esm/mcp/tools/memory.js.map +1 -1
- package/dist/esm/mcp/tools/misc.d.ts.map +1 -1
- package/dist/esm/mcp/tools/misc.js +2 -1
- package/dist/esm/mcp/tools/misc.js.map +1 -1
- package/dist/esm/mcp/tools/workspace.d.ts.map +1 -1
- package/dist/esm/mcp/tools/workspace.js +4 -1
- package/dist/esm/mcp/tools/workspace.js.map +1 -1
- package/dist/esm/mcp/tools.d.ts +10 -0
- package/dist/esm/mcp/tools.d.ts.map +1 -1
- package/dist/esm/mcp/tools.js +46 -12
- package/dist/esm/mcp/tools.js.map +1 -1
- package/dist/esm/proxy/KeyManager.d.ts.map +1 -1
- package/dist/esm/proxy/KeyManager.js +5 -0
- package/dist/esm/proxy/KeyManager.js.map +1 -1
- package/dist/esm/subconscious/CloudBrain.d.ts +77 -0
- package/dist/esm/subconscious/CloudBrain.d.ts.map +1 -0
- package/dist/esm/subconscious/CloudBrain.js +330 -0
- package/dist/esm/subconscious/CloudBrain.js.map +1 -0
- package/dist/esm/subconscious/HostRecall.d.ts.map +1 -1
- package/dist/esm/subconscious/HostRecall.js +11 -4
- package/dist/esm/subconscious/HostRecall.js.map +1 -1
- package/dist/esm/subconscious/ProjectIdentity.d.ts +9 -0
- package/dist/esm/subconscious/ProjectIdentity.d.ts.map +1 -0
- package/dist/esm/subconscious/ProjectIdentity.js +56 -0
- package/dist/esm/subconscious/ProjectIdentity.js.map +1 -0
- package/dist/esm/subconscious/TeamBrain.d.ts +9 -3
- package/dist/esm/subconscious/TeamBrain.d.ts.map +1 -1
- package/dist/esm/subconscious/TeamBrain.js +39 -7
- package/dist/esm/subconscious/TeamBrain.js.map +1 -1
- package/dist/esm/utils/FixCapture.d.ts +7 -5
- package/dist/esm/utils/FixCapture.d.ts.map +1 -1
- package/dist/esm/utils/FixCapture.js +64 -33
- package/dist/esm/utils/FixCapture.js.map +1 -1
- package/dist/esm/utils/NoTerminal.d.ts +27 -0
- package/dist/esm/utils/NoTerminal.d.ts.map +1 -0
- package/dist/esm/utils/NoTerminal.js +33 -0
- package/dist/esm/utils/NoTerminal.js.map +1 -0
- package/dist/esm/utils/OpenCodeSession.d.ts +70 -0
- package/dist/esm/utils/OpenCodeSession.d.ts.map +1 -0
- package/dist/esm/utils/OpenCodeSession.js +146 -0
- package/dist/esm/utils/OpenCodeSession.js.map +1 -0
- package/dist/esm/utils/ProLicense.d.ts.map +1 -1
- package/dist/esm/utils/ProLicense.js +11 -3
- package/dist/esm/utils/ProLicense.js.map +1 -1
- package/dist/esm/utils/SessionCapture.d.ts +31 -7
- package/dist/esm/utils/SessionCapture.d.ts.map +1 -1
- package/dist/esm/utils/SessionCapture.js +185 -32
- package/dist/esm/utils/SessionCapture.js.map +1 -1
- package/dist/esm/utils/StopNudge.d.ts +8 -0
- package/dist/esm/utils/StopNudge.d.ts.map +1 -0
- package/dist/esm/utils/StopNudge.js +86 -0
- package/dist/esm/utils/StopNudge.js.map +1 -0
- package/dist/esm/utils/TestAutofixInterceptor.d.ts.map +1 -1
- package/dist/esm/utils/TestAutofixInterceptor.js +2 -0
- package/dist/esm/utils/TestAutofixInterceptor.js.map +1 -1
- package/lemma-proxy.cjs +5 -0
- package/package.json +2 -1
- package/sdks/crewai/dist/ts/src/client.d.ts +5 -1
- package/sdks/crewai/dist/ts/src/client.js +8 -0
- package/sdks/crewai/dist/ts/src/types.d.ts +32 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CloudEntitlement.js","sourceRoot":"","sources":["../../../src/cloud/CloudEntitlement.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export declare const TRIAL_DAYS = 14;
|
|
2
|
+
export type Interval = 'month' | 'year';
|
|
3
|
+
export declare const SELLABLE_PLANS: readonly ["vinel", "regnum"];
|
|
4
|
+
export type SellablePlan = (typeof SELLABLE_PLANS)[number];
|
|
5
|
+
export interface StripeApiConfig {
|
|
6
|
+
secretKey: string;
|
|
7
|
+
/** Where Stripe sends the customer after paying or cancelling. */
|
|
8
|
+
successUrl: string;
|
|
9
|
+
cancelUrl: string;
|
|
10
|
+
/** Where the billing portal's "back" link goes. */
|
|
11
|
+
portalReturnUrl: string;
|
|
12
|
+
/** Test seam: defaults to the global fetch. */
|
|
13
|
+
fetchImpl?: typeof fetch;
|
|
14
|
+
}
|
|
15
|
+
export declare function stripeApiConfigFromEnv(env?: NodeJS.ProcessEnv): StripeApiConfig | null;
|
|
16
|
+
/** The stable lookup key the Stripe setup gave each price: `lemma_cloud_vinel_monthly`, ... */
|
|
17
|
+
export declare const priceLookupKey: (plan: SellablePlan, interval: Interval) => string;
|
|
18
|
+
export declare const founderCoupon: (plan: SellablePlan) => string;
|
|
19
|
+
export declare class StripeApi {
|
|
20
|
+
private readonly config;
|
|
21
|
+
private readonly fetchImpl;
|
|
22
|
+
constructor(config: StripeApiConfig);
|
|
23
|
+
private call;
|
|
24
|
+
/** Creates a Checkout Session for `tenantId` and returns its URL. */
|
|
25
|
+
createCheckout(input: {
|
|
26
|
+
tenantId: string;
|
|
27
|
+
plan: SellablePlan;
|
|
28
|
+
interval: Interval;
|
|
29
|
+
founder: boolean;
|
|
30
|
+
existingCustomerId: string | null;
|
|
31
|
+
email?: string;
|
|
32
|
+
}): Promise<{
|
|
33
|
+
url: string;
|
|
34
|
+
expiresAt: number;
|
|
35
|
+
}>;
|
|
36
|
+
/** Creates a customer-portal session (payment method, invoices, cancel) for an existing Stripe customer. */
|
|
37
|
+
createPortal(customerId: string): Promise<{
|
|
38
|
+
url: string;
|
|
39
|
+
}>;
|
|
40
|
+
}
|
|
41
|
+
/** The client for the operator routes, or undefined when STRIPE_SECRET_KEY is not set (the routes are then not mounted). */
|
|
42
|
+
export declare function stripeApiFromEnv(env?: NodeJS.ProcessEnv): StripeApi | undefined;
|
|
43
|
+
//# sourceMappingURL=stripeApi.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stripeApi.d.ts","sourceRoot":"","sources":["../../../../src/cloud/billing/stripeApi.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,UAAU,KAAK,CAAC;AAC7B,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AACxC,eAAO,MAAM,cAAc,8BAA2D,CAAC;AACvF,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,mDAAmD;IACnD,eAAe,EAAE,MAAM,CAAC;IACxB,+CAA+C;IAC/C,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAID,wBAAgB,sBAAsB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,eAAe,GAAG,IAAI,CASnG;AAED,+FAA+F;AAC/F,eAAO,MAAM,cAAc,GAAI,MAAM,YAAY,EAAE,UAAU,QAAQ,KAAG,MAA6C,CAAC;AACtH,eAAO,MAAM,aAAa,GAAI,MAAM,YAAY,KAAG,MAAyC,CAAC;AAK7F,qBAAa,SAAS;IAER,OAAO,CAAC,QAAQ,CAAC,MAAM;IADnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;gBACZ,MAAM,EAAE,eAAe;YAItC,IAAI;IAmBlB,qEAAqE;IAC/D,cAAc,CAAC,KAAK,EAAE;QAC1B,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,YAAY,CAAC;QACnB,QAAQ,EAAE,QAAQ,CAAC;QACnB,OAAO,EAAE,OAAO,CAAC;QACjB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;QAClC,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAmC/C,4GAA4G;IACtG,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CAKjE;AAED,4HAA4H;AAC5H,wBAAgB,gBAAgB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,SAAS,GAAG,SAAS,CAG5F"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StripeApi = exports.founderCoupon = exports.priceLookupKey = exports.SELLABLE_PLANS = exports.TRIAL_DAYS = void 0;
|
|
4
|
+
exports.stripeApiConfigFromEnv = stripeApiConfigFromEnv;
|
|
5
|
+
exports.stripeApiFromEnv = stripeApiFromEnv;
|
|
6
|
+
/**
|
|
7
|
+
* Lemma Cloud — the two Stripe calls an operator needs: a Checkout link for a tenant, and a billing
|
|
8
|
+
* portal link for a tenant that already pays. A thin client over `fetch` (the webhook already avoids
|
|
9
|
+
* the Stripe SDK; this keeps the dependency list unchanged and the form encoding visible in tests).
|
|
10
|
+
*
|
|
11
|
+
* What makes a checkout Cloud's rather than anyone else's in the same Stripe account:
|
|
12
|
+
* - `client_reference_id` = the tenant id, and `metadata.lemma_product = "cloud"` (the Pro license
|
|
13
|
+
* site's webhook skips sessions with either, and our webhook links the customer through the first);
|
|
14
|
+
* - the same tenant id on the SUBSCRIPTION metadata, so `customer.subscription.*` finds the tenant
|
|
15
|
+
* even when it overtakes `checkout.session.completed`.
|
|
16
|
+
*
|
|
17
|
+
* The secret key never appears in a response or a log line: Stripe errors are reduced to their message.
|
|
18
|
+
*/
|
|
19
|
+
const errors_1 = require("../../contracts/errors");
|
|
20
|
+
exports.TRIAL_DAYS = 14;
|
|
21
|
+
exports.SELLABLE_PLANS = ['vinel', 'regnum'];
|
|
22
|
+
const DEFAULT_URL = 'https://lemma.nxus.studio/';
|
|
23
|
+
function stripeApiConfigFromEnv(env = process.env) {
|
|
24
|
+
const secretKey = env.STRIPE_SECRET_KEY;
|
|
25
|
+
if (!secretKey)
|
|
26
|
+
return null;
|
|
27
|
+
return {
|
|
28
|
+
secretKey,
|
|
29
|
+
successUrl: env.CLOUD_CHECKOUT_SUCCESS_URL || `${DEFAULT_URL}?cloud=success`,
|
|
30
|
+
cancelUrl: env.CLOUD_CHECKOUT_CANCEL_URL || `${DEFAULT_URL}?cloud=cancelled`,
|
|
31
|
+
portalReturnUrl: env.CLOUD_PORTAL_RETURN_URL || DEFAULT_URL,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/** The stable lookup key the Stripe setup gave each price: `lemma_cloud_vinel_monthly`, ... */
|
|
35
|
+
const priceLookupKey = (plan, interval) => `lemma_cloud_${plan}_${interval}ly`;
|
|
36
|
+
exports.priceLookupKey = priceLookupKey;
|
|
37
|
+
const founderCoupon = (plan) => `FOUNDER_${plan.toUpperCase()}`;
|
|
38
|
+
exports.founderCoupon = founderCoupon;
|
|
39
|
+
const upstream = (what, detail) => new errors_1.LemmaApiError({ code: 'internal', status: 502, message: `billing provider error while ${what}${detail ? `: ${detail}` : ''}` });
|
|
40
|
+
class StripeApi {
|
|
41
|
+
constructor(config) {
|
|
42
|
+
this.config = config;
|
|
43
|
+
this.fetchImpl = config.fetchImpl ?? fetch;
|
|
44
|
+
}
|
|
45
|
+
async call(method, path, form, what = 'calling Stripe') {
|
|
46
|
+
let res;
|
|
47
|
+
try {
|
|
48
|
+
res = await this.fetchImpl('https://api.stripe.com/v1' + path, {
|
|
49
|
+
method,
|
|
50
|
+
headers: {
|
|
51
|
+
Authorization: 'Basic ' + Buffer.from(this.config.secretKey + ':').toString('base64'),
|
|
52
|
+
...(form ? { 'Content-Type': 'application/x-www-form-urlencoded' } : {}),
|
|
53
|
+
},
|
|
54
|
+
body: form ? new URLSearchParams(form).toString() : undefined,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
throw upstream(what, 'unreachable');
|
|
59
|
+
}
|
|
60
|
+
const json = await res.json().catch(() => null);
|
|
61
|
+
if (!res.ok || !json || json.error)
|
|
62
|
+
throw upstream(what, typeof json?.error?.message === 'string' ? json.error.message : `HTTP ${res.status}`);
|
|
63
|
+
return json;
|
|
64
|
+
}
|
|
65
|
+
/** Creates a Checkout Session for `tenantId` and returns its URL. */
|
|
66
|
+
async createCheckout(input) {
|
|
67
|
+
const { tenantId, plan, interval } = input;
|
|
68
|
+
const lookup = (0, exports.priceLookupKey)(plan, interval);
|
|
69
|
+
const prices = await this.call('GET', `/prices?lookup_keys[]=${encodeURIComponent(lookup)}&active=true`, undefined, 'looking up the price');
|
|
70
|
+
const price = prices.data?.[0];
|
|
71
|
+
if (!price?.id)
|
|
72
|
+
throw upstream('looking up the price', `no active price with lookup key ${lookup}`);
|
|
73
|
+
const form = {
|
|
74
|
+
mode: 'subscription',
|
|
75
|
+
'line_items[0][price]': price.id,
|
|
76
|
+
'line_items[0][quantity]': '1',
|
|
77
|
+
client_reference_id: tenantId,
|
|
78
|
+
'metadata[lemma_product]': 'cloud',
|
|
79
|
+
'metadata[tenantId]': tenantId,
|
|
80
|
+
'subscription_data[metadata][lemma_product]': 'cloud',
|
|
81
|
+
'subscription_data[metadata][tenantId]': tenantId,
|
|
82
|
+
'subscription_data[trial_period_days]': String(exports.TRIAL_DAYS),
|
|
83
|
+
success_url: this.config.successUrl,
|
|
84
|
+
cancel_url: this.config.cancelUrl,
|
|
85
|
+
};
|
|
86
|
+
if (input.founder) {
|
|
87
|
+
form['discounts[0][coupon]'] = (0, exports.founderCoupon)(plan);
|
|
88
|
+
// The webhook marks the tenant a founder from this (it keeps the founder limits): on the session for
|
|
89
|
+
// checkout.session.completed, on the subscription for every customer.subscription.* after it.
|
|
90
|
+
form['metadata[founder]'] = 'true';
|
|
91
|
+
form['subscription_data[metadata][founder]'] = 'true';
|
|
92
|
+
}
|
|
93
|
+
if (input.existingCustomerId)
|
|
94
|
+
form.customer = input.existingCustomerId;
|
|
95
|
+
else if (input.email)
|
|
96
|
+
form.customer_email = input.email;
|
|
97
|
+
const session = await this.call('POST', '/checkout/sessions', form, 'creating the checkout');
|
|
98
|
+
if (typeof session.url !== 'string')
|
|
99
|
+
throw upstream('creating the checkout', 'no URL returned');
|
|
100
|
+
return { url: session.url, expiresAt: typeof session.expires_at === 'number' ? session.expires_at * 1000 : 0 };
|
|
101
|
+
}
|
|
102
|
+
/** Creates a customer-portal session (payment method, invoices, cancel) for an existing Stripe customer. */
|
|
103
|
+
async createPortal(customerId) {
|
|
104
|
+
const session = await this.call('POST', '/billing_portal/sessions', { customer: customerId, return_url: this.config.portalReturnUrl }, 'creating the portal session');
|
|
105
|
+
if (typeof session.url !== 'string')
|
|
106
|
+
throw upstream('creating the portal session', 'no URL returned');
|
|
107
|
+
return { url: session.url };
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
exports.StripeApi = StripeApi;
|
|
111
|
+
/** The client for the operator routes, or undefined when STRIPE_SECRET_KEY is not set (the routes are then not mounted). */
|
|
112
|
+
function stripeApiFromEnv(env = process.env) {
|
|
113
|
+
const config = stripeApiConfigFromEnv(env);
|
|
114
|
+
return config ? new StripeApi(config) : undefined;
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=stripeApi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stripeApi.js","sourceRoot":"","sources":["../../../../src/cloud/billing/stripeApi.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type Router } from 'express';
|
|
2
|
+
import type { IdentityStore } from '../identity/identityStore';
|
|
3
|
+
import type { PlanId } from '../identity/PlanPolicy';
|
|
4
|
+
export interface StripeBillingConfig {
|
|
5
|
+
/** `whsec_...` of the webhook endpoint. */
|
|
6
|
+
webhookSecret: string;
|
|
7
|
+
/** Stripe price id -> the Cloud plan it buys. Prices not listed here are not ours. */
|
|
8
|
+
prices: Readonly<Record<string, PlanId>>;
|
|
9
|
+
/** Max age of a signed payload; Stripe's own libraries default to 5 minutes. */
|
|
10
|
+
toleranceSeconds?: number;
|
|
11
|
+
}
|
|
12
|
+
/** Verify `Stripe-Signature` (`t=<unix>,v1=<hex>[,v1=<hex>]`) over `${t}.${rawBody}`. */
|
|
13
|
+
export declare function verifyStripeSignature(rawBody: Buffer, header: string | undefined, secret: string, toleranceSeconds?: number, nowMs?: number): boolean;
|
|
14
|
+
interface StripeEvent {
|
|
15
|
+
id?: string;
|
|
16
|
+
type?: string;
|
|
17
|
+
created?: number;
|
|
18
|
+
data?: {
|
|
19
|
+
object?: Record<string, any>;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/** `unresolved`: the event is for one of OUR prices but no tenant is linked yet; Stripe must retry it. */
|
|
23
|
+
export type BillingOutcome = 'applied' | 'ignored' | 'stale' | 'unresolved';
|
|
24
|
+
/** Apply one event. Pure of HTTP, so tests drive it without a signature. */
|
|
25
|
+
export declare function applyStripeEvent(event: StripeEvent, store: IdentityStore, config: Pick<StripeBillingConfig, 'prices'>): Promise<BillingOutcome>;
|
|
26
|
+
/** POST /v2/billing/stripe/webhook. Mount BEFORE express.json(): the signature needs the raw bytes. */
|
|
27
|
+
export declare function stripeWebhookRouter(store: IdentityStore, config: StripeBillingConfig): Router;
|
|
28
|
+
/**
|
|
29
|
+
* Reads the Stripe settings from the environment; null when billing is not configured (the route is then not mounted).
|
|
30
|
+
* A plan can be sold through several Stripe prices (monthly, yearly), so each variable takes a comma-separated list:
|
|
31
|
+
* STRIPE_PRICES_VINEL=price_a,price_b
|
|
32
|
+
*/
|
|
33
|
+
export declare function stripeConfigFromEnv(env?: NodeJS.ProcessEnv): StripeBillingConfig | null;
|
|
34
|
+
export {};
|
|
35
|
+
//# sourceMappingURL=stripeWebhook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stripeWebhook.d.ts","sourceRoot":"","sources":["../../../../src/cloud/billing/stripeWebhook.ts"],"names":[],"mappings":"AAiBA,OAAgB,EAAE,KAAK,MAAM,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,aAAa,EAA+B,MAAM,2BAA2B,CAAC;AAC5F,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAErD,MAAM,WAAW,mBAAmB;IAClC,2CAA2C;IAC3C,aAAa,EAAE,MAAM,CAAC;IACtB,sFAAsF;IACtF,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACzC,gFAAgF;IAChF,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAKD,yFAAyF;AACzF,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,SAAsB,EAAE,KAAK,SAAa,GAAG,OAAO,CAmBtK;AAED,UAAU,WAAW;IACnB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;KAAE,CAAC;CACzC;AAED,0GAA0G;AAC1G,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,YAAY,CAAC;AAgB5E,4EAA4E;AAC5E,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,IAAI,CAAC,mBAAmB,EAAE,QAAQ,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC,CA4DrJ;AAED,uGAAuG;AACvG,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,mBAAmB,GAAG,MAAM,CA4B7F;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,mBAAmB,GAAG,IAAI,CAUpG"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.verifyStripeSignature = verifyStripeSignature;
|
|
7
|
+
exports.applyStripeEvent = applyStripeEvent;
|
|
8
|
+
exports.stripeWebhookRouter = stripeWebhookRouter;
|
|
9
|
+
exports.stripeConfigFromEnv = stripeConfigFromEnv;
|
|
10
|
+
/**
|
|
11
|
+
* Lemma Cloud — Stripe webhook.
|
|
12
|
+
*
|
|
13
|
+
* Stripe owns the money; this turns its subscription events into the tenant's `plan` and the billing
|
|
14
|
+
* state the console shows. Authenticated by the Stripe signature alone (no API key), so it is
|
|
15
|
+
* mounted before the /v2 auth and the JSON parser: the signature covers the RAW body.
|
|
16
|
+
*
|
|
17
|
+
* Shape of the rules, each one a trap if wrong:
|
|
18
|
+
* - The same Stripe account also sells the local Pro license, and every event of the account reaches
|
|
19
|
+
* this endpoint. A subscription whose price is not one of ours, or whose tenant cannot be found,
|
|
20
|
+
* is acknowledged (200) and ignored: a 4xx/5xx would make Stripe retry it for days.
|
|
21
|
+
* - Delivery is unordered, so an event older than the last applied one is dropped (`billing.eventAt`).
|
|
22
|
+
* - A late payment (`past_due`) keeps the plan: the tenant is downgraded when Stripe gives up on the
|
|
23
|
+
* invoice and cancels the subscription (the retry window is set in the Stripe dashboard), not by
|
|
24
|
+
* a timer here. `unpaid`, `canceled` and `incomplete_expired` drop the tenant to `free`.
|
|
25
|
+
*/
|
|
26
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
27
|
+
const express_1 = __importDefault(require("express"));
|
|
28
|
+
const DEFAULT_TOLERANCE_S = 300;
|
|
29
|
+
const MAX_BODY_BYTES = 256 * 1024;
|
|
30
|
+
/** Verify `Stripe-Signature` (`t=<unix>,v1=<hex>[,v1=<hex>]`) over `${t}.${rawBody}`. */
|
|
31
|
+
function verifyStripeSignature(rawBody, header, secret, toleranceSeconds = DEFAULT_TOLERANCE_S, nowMs = Date.now()) {
|
|
32
|
+
if (!header)
|
|
33
|
+
return false;
|
|
34
|
+
let t = '';
|
|
35
|
+
const sigs = [];
|
|
36
|
+
for (const part of header.split(',')) {
|
|
37
|
+
const i = part.indexOf('=');
|
|
38
|
+
if (i < 0)
|
|
39
|
+
continue;
|
|
40
|
+
const k = part.slice(0, i).trim();
|
|
41
|
+
const v = part.slice(i + 1).trim();
|
|
42
|
+
if (k === 't')
|
|
43
|
+
t = v;
|
|
44
|
+
else if (k === 'v1')
|
|
45
|
+
sigs.push(v);
|
|
46
|
+
}
|
|
47
|
+
if (!/^\d{1,12}$/.test(t) || sigs.length === 0)
|
|
48
|
+
return false;
|
|
49
|
+
if (Math.abs(nowMs / 1000 - Number(t)) > toleranceSeconds)
|
|
50
|
+
return false;
|
|
51
|
+
const expected = crypto_1.default.createHmac('sha256', secret).update(`${t}.`).update(rawBody).digest();
|
|
52
|
+
return sigs.some((s) => {
|
|
53
|
+
if (!/^[0-9a-f]{64}$/i.test(s))
|
|
54
|
+
return false;
|
|
55
|
+
return crypto_1.default.timingSafeEqual(expected, Buffer.from(s, 'hex'));
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
const asId = (v) => {
|
|
59
|
+
if (typeof v === 'string' && v)
|
|
60
|
+
return v;
|
|
61
|
+
if (v && typeof v === 'object' && typeof v.id === 'string')
|
|
62
|
+
return v.id;
|
|
63
|
+
return null;
|
|
64
|
+
};
|
|
65
|
+
/** Stripe moved `current_period_end` from the subscription to its items in newer API versions; accept both. */
|
|
66
|
+
const periodEndMs = (sub) => {
|
|
67
|
+
const s = sub.current_period_end ?? sub.items?.data?.[0]?.current_period_end;
|
|
68
|
+
return typeof s === 'number' ? s * 1000 : null;
|
|
69
|
+
};
|
|
70
|
+
const DROPS_TO_FREE = new Set(['unpaid', 'canceled', 'incomplete_expired']);
|
|
71
|
+
/** Apply one event. Pure of HTTP, so tests drive it without a signature. */
|
|
72
|
+
async function applyStripeEvent(event, store, config) {
|
|
73
|
+
const obj = event.data?.object;
|
|
74
|
+
if (!obj || typeof event.created !== 'number')
|
|
75
|
+
return 'ignored';
|
|
76
|
+
const eventAt = event.created * 1000;
|
|
77
|
+
let tenant = null;
|
|
78
|
+
let next = null;
|
|
79
|
+
if (event.type === 'checkout.session.completed') {
|
|
80
|
+
// Links the Stripe customer to our tenant (client_reference_id is the tenant id the checkout was created for).
|
|
81
|
+
const tenantId = typeof obj.client_reference_id === 'string' ? obj.client_reference_id : null;
|
|
82
|
+
const customerId = asId(obj.customer);
|
|
83
|
+
if (!tenantId || !customerId || obj.mode !== 'subscription')
|
|
84
|
+
return 'ignored';
|
|
85
|
+
tenant = await store.getTenant(tenantId);
|
|
86
|
+
if (!tenant || tenant.plan === 'internal')
|
|
87
|
+
return 'ignored';
|
|
88
|
+
// One Stripe customer belongs to one tenant. A checkout naming a customer that is already
|
|
89
|
+
// linked elsewhere is refused, not re-pointed (the unique index would turn it into a 500).
|
|
90
|
+
const owner = await store.findTenantByStripeCustomer(customerId);
|
|
91
|
+
if (owner && owner.id !== tenant.id)
|
|
92
|
+
return 'ignored';
|
|
93
|
+
next = { plan: tenant.plan, billing: { ...tenant.billing, customerId, subscriptionId: asId(obj.subscription) ?? tenant.billing.subscriptionId, eventAt } };
|
|
94
|
+
}
|
|
95
|
+
else if (event.type === 'customer.subscription.created' || event.type === 'customer.subscription.updated' || event.type === 'customer.subscription.deleted') {
|
|
96
|
+
const priceId = asId(obj.items?.data?.[0]?.price);
|
|
97
|
+
const bought = priceId ? config.prices[priceId] : undefined;
|
|
98
|
+
if (!bought)
|
|
99
|
+
return 'ignored'; // not a Cloud price: the local Pro license, or something else of the account
|
|
100
|
+
const customerId = asId(obj.customer);
|
|
101
|
+
const metaTenant = typeof obj.metadata?.tenantId === 'string' ? obj.metadata.tenantId : null;
|
|
102
|
+
tenant = metaTenant ? await store.getTenant(metaTenant) : customerId ? await store.findTenantByStripeCustomer(customerId) : null;
|
|
103
|
+
// A price of ours with no tenant yet usually means this event overtook `checkout.session.completed`
|
|
104
|
+
// (Stripe does not order them): answering 200 would lose the plan for good, so ask for a retry.
|
|
105
|
+
if (!tenant)
|
|
106
|
+
return 'unresolved';
|
|
107
|
+
if (tenant.plan === 'internal')
|
|
108
|
+
return 'ignored'; // not sold through Stripe: nothing it says may change it
|
|
109
|
+
const status = typeof obj.status === 'string' ? obj.status : null;
|
|
110
|
+
const gone = event.type === 'customer.subscription.deleted' || (status !== null && DROPS_TO_FREE.has(status));
|
|
111
|
+
// `incomplete` (first payment pending) changes nothing yet; the next event carries the outcome.
|
|
112
|
+
if (!gone && status === 'incomplete')
|
|
113
|
+
return 'ignored';
|
|
114
|
+
next = {
|
|
115
|
+
plan: gone ? 'free' : bought,
|
|
116
|
+
billing: {
|
|
117
|
+
customerId: customerId ?? tenant.billing.customerId,
|
|
118
|
+
subscriptionId: asId(obj.id) ?? tenant.billing.subscriptionId,
|
|
119
|
+
status: event.type === 'customer.subscription.deleted' ? 'canceled' : status,
|
|
120
|
+
currentPeriodEnd: periodEndMs(obj) ?? tenant.billing.currentPeriodEnd,
|
|
121
|
+
pastDueSince: status === 'past_due' ? tenant.billing.pastDueSince ?? eventAt : null,
|
|
122
|
+
eventAt,
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
return 'ignored';
|
|
128
|
+
}
|
|
129
|
+
const result = await store.applyBilling(tenant.id, next.plan, next.billing);
|
|
130
|
+
// A founder checkout (session or subscription metadata founder=true, set by createCheckout) makes the
|
|
131
|
+
// tenant a founder for good. Never the other way: a cancellation drops the plan, not the founder status.
|
|
132
|
+
if (obj.metadata?.founder === 'true' && !tenant.founder && (result.ok || result.reason === 'stale')) {
|
|
133
|
+
await store.setTenantFounder(tenant.id, true);
|
|
134
|
+
}
|
|
135
|
+
if (result.ok)
|
|
136
|
+
return 'applied';
|
|
137
|
+
return result.reason === 'stale' ? 'stale' : 'ignored';
|
|
138
|
+
}
|
|
139
|
+
/** POST /v2/billing/stripe/webhook. Mount BEFORE express.json(): the signature needs the raw bytes. */
|
|
140
|
+
function stripeWebhookRouter(store, config) {
|
|
141
|
+
const r = express_1.default.Router();
|
|
142
|
+
r.post('/', express_1.default.raw({ type: '*/*', limit: MAX_BODY_BYTES }), async (req, res, next) => {
|
|
143
|
+
try {
|
|
144
|
+
const raw = req.body;
|
|
145
|
+
if (!Buffer.isBuffer(raw) || !verifyStripeSignature(raw, req.header('stripe-signature'), config.webhookSecret, config.toleranceSeconds)) {
|
|
146
|
+
res.status(400).json({ error: { code: 'invalid_signature', status: 400, message: 'bad or missing Stripe signature' } });
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
let event;
|
|
150
|
+
try {
|
|
151
|
+
event = JSON.parse(raw.toString('utf8'));
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
res.status(400).json({ error: { code: 'invalid_request', status: 400, message: 'body is not JSON' } });
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
const outcome = await applyStripeEvent(event, store, config);
|
|
158
|
+
if (outcome === 'unresolved') {
|
|
159
|
+
// 409, not 2xx: Stripe retries with backoff for days, by which time the checkout event has linked the tenant.
|
|
160
|
+
res.status(409).json({ error: { code: 'tenant_not_linked', status: 409, message: 'no tenant linked to this customer yet, retry later' }, outcome });
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
res.json({ received: true, outcome });
|
|
164
|
+
}
|
|
165
|
+
catch (err) {
|
|
166
|
+
next(err); // a store failure is a 500: Stripe retries, which is what we want
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
return r;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Reads the Stripe settings from the environment; null when billing is not configured (the route is then not mounted).
|
|
173
|
+
* A plan can be sold through several Stripe prices (monthly, yearly), so each variable takes a comma-separated list:
|
|
174
|
+
* STRIPE_PRICES_VINEL=price_a,price_b
|
|
175
|
+
*/
|
|
176
|
+
function stripeConfigFromEnv(env = process.env) {
|
|
177
|
+
const webhookSecret = env.STRIPE_WEBHOOK_SECRET;
|
|
178
|
+
if (!webhookSecret)
|
|
179
|
+
return null;
|
|
180
|
+
const prices = {};
|
|
181
|
+
const add = (list, plan) => {
|
|
182
|
+
for (const id of (list ?? '').split(','))
|
|
183
|
+
if (id.trim())
|
|
184
|
+
prices[id.trim()] = plan;
|
|
185
|
+
};
|
|
186
|
+
add(env.STRIPE_PRICES_VINEL, 'vinel');
|
|
187
|
+
add(env.STRIPE_PRICES_REGNUM, 'regnum');
|
|
188
|
+
return { webhookSecret, prices };
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=stripeWebhook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stripeWebhook.js","sourceRoot":"","sources":["../../../../src/cloud/billing/stripeWebhook.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import type { Pool } from 'pg';
|
|
2
|
+
import type { IdentityStore } from '../identity/identityStore';
|
|
3
|
+
export declare const MEMBER_ROLES: readonly ["owner", "admin", "member"];
|
|
4
|
+
export type MemberRole = (typeof MEMBER_ROLES)[number];
|
|
5
|
+
export interface Member {
|
|
6
|
+
id: string;
|
|
7
|
+
tenantId: string;
|
|
8
|
+
email: string;
|
|
9
|
+
role: MemberRole;
|
|
10
|
+
createdAt: number;
|
|
11
|
+
}
|
|
12
|
+
export type AddMemberResult = {
|
|
13
|
+
ok: true;
|
|
14
|
+
member: Member;
|
|
15
|
+
} | {
|
|
16
|
+
ok: false;
|
|
17
|
+
reason: 'no_tenant' | 'exists' | 'other_tenant';
|
|
18
|
+
};
|
|
19
|
+
export interface SessionInfo {
|
|
20
|
+
tenantId: string;
|
|
21
|
+
email: string;
|
|
22
|
+
role: MemberRole;
|
|
23
|
+
}
|
|
24
|
+
export interface ConsoleStore {
|
|
25
|
+
addMember(tenantId: string, email: string, role: MemberRole): Promise<AddMemberResult>;
|
|
26
|
+
listMembers(tenantId: string): Promise<Member[]>;
|
|
27
|
+
/** Soft-removes the member and ends their sessions. */
|
|
28
|
+
removeMember(tenantId: string, email: string): Promise<boolean>;
|
|
29
|
+
/** The active member with this email, in any tenant. */
|
|
30
|
+
findMemberByEmail(email: string): Promise<Member | null>;
|
|
31
|
+
createLoginToken(input: {
|
|
32
|
+
tokenHash: string;
|
|
33
|
+
tenantId: string;
|
|
34
|
+
email: string;
|
|
35
|
+
expiresAt: number;
|
|
36
|
+
}): Promise<void>;
|
|
37
|
+
/** Atomic and single use: the first caller gets the member, everyone after (or after expiry) gets null. */
|
|
38
|
+
consumeLoginToken(tokenHash: string, now: number): Promise<{
|
|
39
|
+
tenantId: string;
|
|
40
|
+
email: string;
|
|
41
|
+
} | null>;
|
|
42
|
+
createSession(input: {
|
|
43
|
+
tokenHash: string;
|
|
44
|
+
tenantId: string;
|
|
45
|
+
email: string;
|
|
46
|
+
expiresAt: number;
|
|
47
|
+
}): Promise<void>;
|
|
48
|
+
/** The session if it is live AND its member is still active; the role is the member's current one. */
|
|
49
|
+
findSession(tokenHash: string, now: number): Promise<SessionInfo | null>;
|
|
50
|
+
deleteSession(tokenHash: string): Promise<void>;
|
|
51
|
+
}
|
|
52
|
+
export declare const normalizeEmail: (email: string) => string;
|
|
53
|
+
export declare const hashToken: (token: string) => string;
|
|
54
|
+
/** 256 bits, URL-safe. Only its hash is ever stored. */
|
|
55
|
+
export declare const newToken: () => string;
|
|
56
|
+
export declare class InMemoryConsoleStore implements ConsoleStore {
|
|
57
|
+
private readonly identity;
|
|
58
|
+
private readonly members;
|
|
59
|
+
private readonly loginTokens;
|
|
60
|
+
private readonly sessions;
|
|
61
|
+
constructor(identity: Pick<IdentityStore, 'getTenant'>);
|
|
62
|
+
addMember(tenantId: string, rawEmail: string, role: MemberRole): Promise<AddMemberResult>;
|
|
63
|
+
listMembers(tenantId: string): Promise<Member[]>;
|
|
64
|
+
removeMember(tenantId: string, rawEmail: string): Promise<boolean>;
|
|
65
|
+
findMemberByEmail(rawEmail: string): Promise<Member | null>;
|
|
66
|
+
createLoginToken(i: {
|
|
67
|
+
tokenHash: string;
|
|
68
|
+
tenantId: string;
|
|
69
|
+
email: string;
|
|
70
|
+
expiresAt: number;
|
|
71
|
+
}): Promise<void>;
|
|
72
|
+
consumeLoginToken(tokenHash: string, now: number): Promise<{
|
|
73
|
+
tenantId: string;
|
|
74
|
+
email: string;
|
|
75
|
+
} | null>;
|
|
76
|
+
createSession(i: {
|
|
77
|
+
tokenHash: string;
|
|
78
|
+
tenantId: string;
|
|
79
|
+
email: string;
|
|
80
|
+
expiresAt: number;
|
|
81
|
+
}): Promise<void>;
|
|
82
|
+
findSession(tokenHash: string, now: number): Promise<SessionInfo | null>;
|
|
83
|
+
deleteSession(tokenHash: string): Promise<void>;
|
|
84
|
+
}
|
|
85
|
+
export declare class PostgresConsoleStore implements ConsoleStore {
|
|
86
|
+
private readonly pool;
|
|
87
|
+
constructor(pool: Pool);
|
|
88
|
+
addMember(tenantId: string, rawEmail: string, role: MemberRole): Promise<AddMemberResult>;
|
|
89
|
+
listMembers(tenantId: string): Promise<Member[]>;
|
|
90
|
+
removeMember(tenantId: string, rawEmail: string): Promise<boolean>;
|
|
91
|
+
findMemberByEmail(rawEmail: string): Promise<Member | null>;
|
|
92
|
+
createLoginToken(i: {
|
|
93
|
+
tokenHash: string;
|
|
94
|
+
tenantId: string;
|
|
95
|
+
email: string;
|
|
96
|
+
expiresAt: number;
|
|
97
|
+
}): Promise<void>;
|
|
98
|
+
consumeLoginToken(tokenHash: string, now: number): Promise<{
|
|
99
|
+
tenantId: string;
|
|
100
|
+
email: string;
|
|
101
|
+
} | null>;
|
|
102
|
+
createSession(i: {
|
|
103
|
+
tokenHash: string;
|
|
104
|
+
tenantId: string;
|
|
105
|
+
email: string;
|
|
106
|
+
expiresAt: number;
|
|
107
|
+
}): Promise<void>;
|
|
108
|
+
findSession(tokenHash: string, now: number): Promise<SessionInfo | null>;
|
|
109
|
+
deleteSession(tokenHash: string): Promise<void>;
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=ConsoleStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConsoleStore.d.ts","sourceRoot":"","sources":["../../../../src/cloud/console/ConsoleStore.ts"],"names":[],"mappings":"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"}
|