@nxuss/lemma 1.43.0 → 1.44.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 +1 -1
- package/bin/brain-ingest.js +18 -0
- package/bin/cloud.js +228 -0
- package/dist/cjs/cli/hostHooks.d.ts +6 -0
- package/dist/cjs/cli/hostHooks.d.ts.map +1 -1
- package/dist/cjs/cli/hostHooks.js +13 -3
- package/dist/cjs/cli/hostHooks.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 +111 -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 +185 -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 +263 -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 +16 -1
- package/dist/cjs/cloud/identity/PlanPolicy.d.ts.map +1 -1
- package/dist/cjs/cloud/identity/PlanPolicy.js +47 -7
- 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 +4 -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 +85 -10
- package/dist/cjs/cloud/identity/identityStore.d.ts.map +1 -1
- package/dist/cjs/cloud/identity/identityStore.js +184 -2
- package/dist/cjs/cloud/identity/identityStore.js.map +1 -1
- package/dist/cjs/cloud/metering/PostgresLedgerStore.d.ts +16 -0
- package/dist/cjs/cloud/metering/PostgresLedgerStore.d.ts.map +1 -0
- package/dist/cjs/cloud/metering/PostgresLedgerStore.js +44 -0
- package/dist/cjs/cloud/metering/PostgresLedgerStore.js.map +1 -0
- package/dist/cjs/cloud/metering/UsageLedger.d.ts +37 -0
- package/dist/cjs/cloud/metering/UsageLedger.d.ts.map +1 -1
- package/dist/cjs/cloud/metering/UsageLedger.js +80 -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 +1 -0
- package/dist/cjs/cloud/store/FileBrainStore.d.ts.map +1 -1
- package/dist/cjs/cloud/store/FileBrainStore.js +3 -0
- package/dist/cjs/cloud/store/FileBrainStore.js.map +1 -1
- package/dist/cjs/cloud/store/PostgresBrainStore.d.ts +1 -0
- package/dist/cjs/cloud/store/PostgresBrainStore.d.ts.map +1 -1
- package/dist/cjs/cloud/store/PostgresBrainStore.js +4 -0
- package/dist/cjs/cloud/store/PostgresBrainStore.js.map +1 -1
- 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 +329 -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 +35 -0
- package/dist/cjs/cloud/v2/routes/tenant.d.ts.map +1 -0
- package/dist/cjs/cloud/v2/routes/tenant.js +62 -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 +90 -2
- package/dist/cjs/contracts/api-v2.types.d.ts.map +1 -1
- package/dist/cjs/contracts/store.d.ts +2 -0
- package/dist/cjs/contracts/store.d.ts.map +1 -1
- package/dist/cjs/mcp/index.js +3 -0
- 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.d.ts.map +1 -1
- 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/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/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 +2 -0
- package/dist/cjs/utils/SessionCapture.d.ts.map +1 -1
- package/dist/cjs/utils/SessionCapture.js +5 -0
- 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/esm/cli/hostHooks.d.ts +6 -0
- package/dist/esm/cli/hostHooks.d.ts.map +1 -1
- package/dist/esm/cli/hostHooks.js +12 -2
- package/dist/esm/cli/hostHooks.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 +103 -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 +176 -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 +252 -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 +16 -1
- package/dist/esm/cloud/identity/PlanPolicy.d.ts.map +1 -1
- package/dist/esm/cloud/identity/PlanPolicy.js +46 -6
- 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 +4 -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 +85 -10
- package/dist/esm/cloud/identity/identityStore.d.ts.map +1 -1
- package/dist/esm/cloud/identity/identityStore.js +180 -1
- package/dist/esm/cloud/identity/identityStore.js.map +1 -1
- package/dist/esm/cloud/metering/PostgresLedgerStore.d.ts +16 -0
- package/dist/esm/cloud/metering/PostgresLedgerStore.d.ts.map +1 -0
- package/dist/esm/cloud/metering/PostgresLedgerStore.js +40 -0
- package/dist/esm/cloud/metering/PostgresLedgerStore.js.map +1 -0
- package/dist/esm/cloud/metering/UsageLedger.d.ts +37 -0
- package/dist/esm/cloud/metering/UsageLedger.d.ts.map +1 -1
- package/dist/esm/cloud/metering/UsageLedger.js +78 -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 +1 -0
- package/dist/esm/cloud/store/FileBrainStore.d.ts.map +1 -1
- package/dist/esm/cloud/store/FileBrainStore.js +3 -0
- package/dist/esm/cloud/store/FileBrainStore.js.map +1 -1
- package/dist/esm/cloud/store/PostgresBrainStore.d.ts +1 -0
- package/dist/esm/cloud/store/PostgresBrainStore.d.ts.map +1 -1
- package/dist/esm/cloud/store/PostgresBrainStore.js +4 -0
- package/dist/esm/cloud/store/PostgresBrainStore.js.map +1 -1
- 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 +322 -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 +35 -0
- package/dist/esm/cloud/v2/routes/tenant.d.ts.map +1 -0
- package/dist/esm/cloud/v2/routes/tenant.js +58 -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 +90 -2
- package/dist/esm/contracts/api-v2.types.d.ts.map +1 -1
- package/dist/esm/contracts/store.d.ts +2 -0
- package/dist/esm/contracts/store.d.ts.map +1 -1
- package/dist/esm/mcp/index.js +3 -0
- 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.d.ts.map +1 -1
- 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/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/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 +2 -0
- package/dist/esm/utils/SessionCapture.d.ts.map +1 -1
- package/dist/esm/utils/SessionCapture.js +5 -0
- 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/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
|
@@ -1,8 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lemma API v2 — PlanPolicy (Lane D)
|
|
3
|
+
*
|
|
4
|
+
* Replaces `src/cloud/types.ts` PLAN_LIMITS. Quota is measured by ACTIVE-VERIFIED
|
|
5
|
+
* memories and by SEAT, not only by request count, and `Infinity` is gone —
|
|
6
|
+
* every plan has an explicit, positive ceiling. Exceeding a cap yields a 429
|
|
7
|
+
* with an actionable body: limit, current use, reset time and upgrade link.
|
|
8
|
+
*
|
|
9
|
+
* This module owns the plan table. The DB migration only stores tenancy; keeping
|
|
10
|
+
* a second copy of the limits in SQL would guarantee drift.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Cloud plans. `vinel` is the team tier (every seat also unlocks the local Pro tools) and `regnum`
|
|
14
|
+
* is the large-organisation tier. They used to be `pro` and `scale`; `pro` now means only the local
|
|
15
|
+
* Pro license, so the two are never confused. `internal` is not sold: it is for the maintainers' own
|
|
16
|
+
* accounts (huge but finite ceilings, because Infinity is banned), assigned only through the admin API,
|
|
17
|
+
* and the Stripe webhook never touches a tenant on it. Add a plan here and the type, the admin API validation
|
|
18
|
+
* and the SQL CHECK (a new migration) follow from this list.
|
|
19
|
+
*/
|
|
20
|
+
export const PLAN_IDS = ['free', 'vinel', 'regnum', 'internal'];
|
|
1
21
|
export const RATE_LIMIT_WINDOW_MS = 24 * 60 * 60 * 1000;
|
|
2
22
|
export const PLAN_UPGRADE_URL = Object.freeze({
|
|
3
23
|
free: 'https://lemma.dev/pricing',
|
|
4
|
-
|
|
5
|
-
|
|
24
|
+
vinel: 'https://lemma.dev/pricing',
|
|
25
|
+
regnum: 'https://lemma.dev/contact',
|
|
26
|
+
internal: 'https://lemma.dev/contact',
|
|
6
27
|
});
|
|
7
28
|
/** Single source of truth for plan ceilings. Every value finite and > 0. */
|
|
8
29
|
export const PLAN_LIMITS = Object.freeze({
|
|
@@ -14,22 +35,41 @@ export const PLAN_LIMITS = Object.freeze({
|
|
|
14
35
|
rateLimitWindowMs: RATE_LIMIT_WINDOW_MS,
|
|
15
36
|
upgradeUrl: PLAN_UPGRADE_URL.free,
|
|
16
37
|
}),
|
|
17
|
-
|
|
38
|
+
vinel: Object.freeze({
|
|
18
39
|
activeMemories: 10000,
|
|
19
40
|
seats: 10,
|
|
20
41
|
dailyRequests: 5000,
|
|
21
42
|
monthlyRequests: 60000,
|
|
22
43
|
rateLimitWindowMs: RATE_LIMIT_WINDOW_MS,
|
|
23
|
-
upgradeUrl: PLAN_UPGRADE_URL.
|
|
44
|
+
upgradeUrl: PLAN_UPGRADE_URL.vinel,
|
|
24
45
|
}),
|
|
25
|
-
|
|
46
|
+
regnum: Object.freeze({
|
|
26
47
|
activeMemories: 100000,
|
|
27
48
|
seats: 50,
|
|
28
49
|
dailyRequests: 20000,
|
|
29
50
|
monthlyRequests: 250000,
|
|
30
51
|
rateLimitWindowMs: RATE_LIMIT_WINDOW_MS,
|
|
31
|
-
upgradeUrl: PLAN_UPGRADE_URL.
|
|
52
|
+
upgradeUrl: PLAN_UPGRADE_URL.regnum,
|
|
32
53
|
}),
|
|
54
|
+
internal: Object.freeze({
|
|
55
|
+
activeMemories: 10000000,
|
|
56
|
+
seats: 25,
|
|
57
|
+
dailyRequests: 1000000,
|
|
58
|
+
monthlyRequests: 30000000,
|
|
59
|
+
rateLimitWindowMs: RATE_LIMIT_WINDOW_MS,
|
|
60
|
+
upgradeUrl: PLAN_UPGRADE_URL.internal,
|
|
61
|
+
}),
|
|
62
|
+
});
|
|
63
|
+
/**
|
|
64
|
+
* Whether a seat on the plan also unlocks the local Pro tools. A Record over PlanId, so adding a plan
|
|
65
|
+
* to PLAN_IDS without deciding this does not compile. The client never decides it: it asks the server
|
|
66
|
+
* (GET /v2/entitlement), so changing a plan here changes what every connected dev gets.
|
|
67
|
+
*/
|
|
68
|
+
export const PLAN_INCLUDES_PRO = Object.freeze({
|
|
69
|
+
free: false,
|
|
70
|
+
vinel: true,
|
|
71
|
+
regnum: true,
|
|
72
|
+
internal: true,
|
|
33
73
|
});
|
|
34
74
|
export const DEFAULT_PLAN = 'free';
|
|
35
75
|
const NUMERIC_LIMIT_KEYS = [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlanPolicy.js","sourceRoot":"","sources":["../../../../src/cloud/identity/PlanPolicy.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"PlanPolicy.js","sourceRoot":"","sources":["../../../../src/cloud/identity/PlanPolicy.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,13 +19,22 @@ export interface RateLimitDecision {
|
|
|
19
19
|
}
|
|
20
20
|
export interface RateLimiter {
|
|
21
21
|
consume(tenantId: string, limit: number, windowMs: number, now?: number): Promise<RateLimitDecision>;
|
|
22
|
+
/** Requests counted in the current window, WITHOUT counting this call. For reporting, never for enforcing. */
|
|
23
|
+
peek?(tenantId: string, windowMs: number, now?: number): Promise<number>;
|
|
24
|
+
/** One request against the tenant's calendar-month (UTC) allowance; resetAt is the first instant of the next month. */
|
|
25
|
+
consumeMonthly?(tenantId: string, limit: number, now?: number): Promise<RateLimitDecision>;
|
|
26
|
+
/** Requests counted this calendar month, WITHOUT counting this call. For reporting, never for enforcing. */
|
|
27
|
+
peekMonthly?(tenantId: string, now?: number): Promise<number>;
|
|
22
28
|
}
|
|
29
|
+
/** Which allowance a 429 came from. */
|
|
30
|
+
export type RateLimitWindow = 'day' | 'month';
|
|
23
31
|
/** The 429 body for rate_limited (additive to the LemmaApiError envelope). */
|
|
24
32
|
export interface RateLimitErrorBody {
|
|
25
33
|
error: {
|
|
26
34
|
code: 'rate_limited';
|
|
27
35
|
status: 429;
|
|
28
36
|
message: string;
|
|
37
|
+
window: RateLimitWindow;
|
|
29
38
|
limit: number;
|
|
30
39
|
used: number;
|
|
31
40
|
remaining: number;
|
|
@@ -34,16 +43,27 @@ export interface RateLimitErrorBody {
|
|
|
34
43
|
upgradeUrl: string;
|
|
35
44
|
};
|
|
36
45
|
}
|
|
37
|
-
export declare function rateLimitErrorBody(decision: RateLimitDecision, retryAfterSeconds: number, upgradeUrl: string): RateLimitErrorBody;
|
|
46
|
+
export declare function rateLimitErrorBody(decision: RateLimitDecision, retryAfterSeconds: number, upgradeUrl: string, window?: RateLimitWindow): RateLimitErrorBody;
|
|
47
|
+
/** Bucket id of the calendar month (UTC) that contains `now`, e.g. `m:2026-10`. Text, so it shares the daily buckets' table without clashing. */
|
|
48
|
+
export declare function monthBucket(now: number): string;
|
|
49
|
+
/** First instant (epoch ms) of the UTC month after the one containing `now`. */
|
|
50
|
+
export declare function nextMonthStart(now: number): number;
|
|
38
51
|
/** In-process fixed-window limiter. Suitable for single-instance dev and tests. */
|
|
39
52
|
export declare class InMemoryRateLimiter implements RateLimiter {
|
|
40
53
|
private readonly buckets;
|
|
41
54
|
consume(tenantId: string, limit: number, windowMs: number, now?: number): Promise<RateLimitDecision>;
|
|
55
|
+
peek(tenantId: string, windowMs: number, now?: number): Promise<number>;
|
|
56
|
+
private readonly months;
|
|
57
|
+
consumeMonthly(tenantId: string, limit: number, now?: number): Promise<RateLimitDecision>;
|
|
58
|
+
peekMonthly(tenantId: string, now?: number): Promise<number>;
|
|
42
59
|
}
|
|
43
60
|
/** Postgres-backed fixed-window limiter, atomic via a single upsert. */
|
|
44
61
|
export declare class PostgresRateLimiter implements RateLimiter {
|
|
45
62
|
private readonly pool;
|
|
46
63
|
constructor(pool: Pool);
|
|
47
64
|
consume(tenantId: string, limit: number, windowMs: number, now?: number): Promise<RateLimitDecision>;
|
|
65
|
+
peek(tenantId: string, windowMs: number, now?: number): Promise<number>;
|
|
66
|
+
consumeMonthly(tenantId: string, limit: number, now?: number): Promise<RateLimitDecision>;
|
|
67
|
+
peekMonthly(tenantId: string, now?: number): Promise<number>;
|
|
48
68
|
}
|
|
49
69
|
//# sourceMappingURL=RateLimiter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RateLimiter.d.ts","sourceRoot":"","sources":["../../../../src/cloud/identity/RateLimiter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAE/B,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"RateLimiter.d.ts","sourceRoot":"","sources":["../../../../src/cloud/identity/RateLimiter.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
export function rateLimitErrorBody(decision, retryAfterSeconds, upgradeUrl) {
|
|
1
|
+
export function rateLimitErrorBody(decision, retryAfterSeconds, upgradeUrl, window = 'day') {
|
|
2
|
+
const scope = window === 'month' ? 'requests this month' : 'requests in the current window';
|
|
2
3
|
return {
|
|
3
4
|
error: {
|
|
4
5
|
code: 'rate_limited',
|
|
5
6
|
status: 429,
|
|
6
|
-
message: `rate limit exceeded: ${decision.used}/${decision.limit}
|
|
7
|
+
message: `rate limit exceeded: ${decision.used}/${decision.limit} ${scope}. ` +
|
|
7
8
|
`Back off and retry after ${retryAfterSeconds}s, or upgrade at ${upgradeUrl}.`,
|
|
9
|
+
window,
|
|
8
10
|
limit: decision.limit,
|
|
9
11
|
used: decision.used,
|
|
10
12
|
remaining: decision.remaining,
|
|
@@ -14,10 +16,21 @@ export function rateLimitErrorBody(decision, retryAfterSeconds, upgradeUrl) {
|
|
|
14
16
|
},
|
|
15
17
|
};
|
|
16
18
|
}
|
|
19
|
+
/** Bucket id of the calendar month (UTC) that contains `now`, e.g. `m:2026-10`. Text, so it shares the daily buckets' table without clashing. */
|
|
20
|
+
export function monthBucket(now) {
|
|
21
|
+
const d = new Date(now);
|
|
22
|
+
return `m:${d.getUTCFullYear()}-${String(d.getUTCMonth() + 1).padStart(2, '0')}`;
|
|
23
|
+
}
|
|
24
|
+
/** First instant (epoch ms) of the UTC month after the one containing `now`. */
|
|
25
|
+
export function nextMonthStart(now) {
|
|
26
|
+
const d = new Date(now);
|
|
27
|
+
return Date.UTC(d.getUTCFullYear(), d.getUTCMonth() + 1, 1);
|
|
28
|
+
}
|
|
17
29
|
/** In-process fixed-window limiter. Suitable for single-instance dev and tests. */
|
|
18
30
|
export class InMemoryRateLimiter {
|
|
19
31
|
constructor() {
|
|
20
32
|
this.buckets = new Map();
|
|
33
|
+
this.months = new Map();
|
|
21
34
|
}
|
|
22
35
|
async consume(tenantId, limit, windowMs, now = Date.now()) {
|
|
23
36
|
const bucket = Math.floor(now / windowMs);
|
|
@@ -42,6 +55,24 @@ export class InMemoryRateLimiter {
|
|
|
42
55
|
resetAt,
|
|
43
56
|
};
|
|
44
57
|
}
|
|
58
|
+
async peek(tenantId, windowMs, now = Date.now()) {
|
|
59
|
+
return this.buckets.get(`${tenantId}:${Math.floor(now / windowMs)}`)?.count ?? 0;
|
|
60
|
+
}
|
|
61
|
+
async consumeMonthly(tenantId, limit, now = Date.now()) {
|
|
62
|
+
const bucket = monthBucket(now);
|
|
63
|
+
// Keep only the current month, as the daily map does: no background timers.
|
|
64
|
+
for (const k of this.months.keys()) {
|
|
65
|
+
if (!k.endsWith(`:${bucket}`))
|
|
66
|
+
this.months.delete(k);
|
|
67
|
+
}
|
|
68
|
+
const key = `${tenantId}:${bucket}`;
|
|
69
|
+
const used = (this.months.get(key) ?? 0) + 1;
|
|
70
|
+
this.months.set(key, used);
|
|
71
|
+
return { allowed: used <= limit, used, limit, remaining: Math.max(0, limit - used), resetAt: nextMonthStart(now) };
|
|
72
|
+
}
|
|
73
|
+
async peekMonthly(tenantId, now = Date.now()) {
|
|
74
|
+
return this.months.get(`${tenantId}:${monthBucket(now)}`) ?? 0;
|
|
75
|
+
}
|
|
45
76
|
}
|
|
46
77
|
/** Postgres-backed fixed-window limiter, atomic via a single upsert. */
|
|
47
78
|
export class PostgresRateLimiter {
|
|
@@ -65,5 +96,29 @@ export class PostgresRateLimiter {
|
|
|
65
96
|
resetAt: (bucket + 1) * windowMs,
|
|
66
97
|
};
|
|
67
98
|
}
|
|
99
|
+
async peek(tenantId, windowMs, now = Date.now()) {
|
|
100
|
+
const { rows } = await this.pool.query('SELECT request_count FROM tenant_rate_limits WHERE tenant_id = $1 AND bucket = $2', [
|
|
101
|
+
tenantId,
|
|
102
|
+
String(Math.floor(now / windowMs)),
|
|
103
|
+
]);
|
|
104
|
+
return Number(rows[0]?.request_count ?? 0);
|
|
105
|
+
}
|
|
106
|
+
async consumeMonthly(tenantId, limit, now = Date.now()) {
|
|
107
|
+
const { rows } = await this.pool.query(`INSERT INTO tenant_rate_limits (tenant_id, bucket, request_count)
|
|
108
|
+
VALUES ($1, $2, 1)
|
|
109
|
+
ON CONFLICT (tenant_id, bucket) DO UPDATE
|
|
110
|
+
SET request_count = tenant_rate_limits.request_count + 1,
|
|
111
|
+
updated_at = CURRENT_TIMESTAMP
|
|
112
|
+
RETURNING request_count`, [tenantId, monthBucket(now)]);
|
|
113
|
+
const used = Number(rows[0]?.request_count ?? 1);
|
|
114
|
+
return { allowed: used <= limit, used, limit, remaining: Math.max(0, limit - used), resetAt: nextMonthStart(now) };
|
|
115
|
+
}
|
|
116
|
+
async peekMonthly(tenantId, now = Date.now()) {
|
|
117
|
+
const { rows } = await this.pool.query('SELECT request_count FROM tenant_rate_limits WHERE tenant_id = $1 AND bucket = $2', [
|
|
118
|
+
tenantId,
|
|
119
|
+
monthBucket(now),
|
|
120
|
+
]);
|
|
121
|
+
return Number(rows[0]?.request_count ?? 0);
|
|
122
|
+
}
|
|
68
123
|
}
|
|
69
124
|
//# sourceMappingURL=RateLimiter.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RateLimiter.js","sourceRoot":"","sources":["../../../../src/cloud/identity/RateLimiter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"RateLimiter.js","sourceRoot":"","sources":["../../../../src/cloud/identity/RateLimiter.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { IdentityStore } from './identityStore.js';
|
|
2
|
+
import type { PlanId } from './PlanPolicy.js';
|
|
2
3
|
export interface Tenant {
|
|
3
4
|
id: string;
|
|
4
|
-
plan:
|
|
5
|
+
plan: PlanId;
|
|
5
6
|
keyId: string;
|
|
7
|
+
/** Human label of the presented key (e.g. "dev-a"); recorded as the memory's author. */
|
|
8
|
+
keyName?: string;
|
|
6
9
|
}
|
|
7
10
|
export declare class TenantResolver {
|
|
8
11
|
private readonly store;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TenantResolver.d.ts","sourceRoot":"","sources":["../../../../src/cloud/identity/TenantResolver.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"TenantResolver.d.ts","sourceRoot":"","sources":["../../../../src/cloud/identity/TenantResolver.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,wFAAwF;IACxF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,cAAc;IAGb,OAAO,CAAC,QAAQ,CAAC,KAAK;IAFlC,QAAQ,CAAC,IAAI,OAAO;gBAES,KAAK,EAAE,aAAa;IAEjD;;;;OAIG;IACG,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAY3D;AAED,eAAe,cAAc,CAAC"}
|
|
@@ -29,7 +29,7 @@ export class TenantResolver {
|
|
|
29
29
|
return null;
|
|
30
30
|
if (record.expiresAt !== null && Date.now() > record.expiresAt)
|
|
31
31
|
return null;
|
|
32
|
-
return { id: record.tenantId, plan: record.plan, keyId: record.id };
|
|
32
|
+
return { id: record.tenantId, plan: record.plan, keyId: record.id, keyName: record.name };
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
export default TenantResolver;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TenantResolver.js","sourceRoot":"","sources":["../../../../src/cloud/identity/TenantResolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"TenantResolver.js","sourceRoot":"","sources":["../../../../src/cloud/identity/TenantResolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAYvD,MAAM,OAAO,cAAc;IAGzB,YAA6B,KAAoB;QAApB,UAAK,GAAL,KAAK,CAAe;QAFxC,SAAI,GAAG,GAAG,CAAC;IAEgC,CAAC;IAErD;;;;OAIG;IACH,KAAK,CAAC,OAAO,CAAC,WAAmB;QAC/B,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC;YAAE,OAAO,IAAI,CAAC;QAE/C,MAAM,IAAI,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;QACrC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QAEpD,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QACzB,IAAI,CAAC,MAAM,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QAChC,IAAI,MAAM,CAAC,SAAS,KAAK,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,SAAS;YAAE,OAAO,IAAI,CAAC;QAE5E,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;IAC5F,CAAC;CACF;AAED,eAAe,cAAc,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authenticateV2.d.ts","sourceRoot":"","sources":["../../../../src/cloud/identity/authenticateV2.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEvD,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAE/D,OAAO,CAAC,MAAM,CAAC;IAEb,UAAU,OAAO,CAAC;QAChB,UAAU,OAAO;YACf,gEAAgE;YAChE,MAAM,CAAC,EAAE,MAAM,CAAC;SACjB;KACF;CACF;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;IAC1C,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,qFAAqF;IACrF,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,8CAA8C;IAC9C,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,oEAAoE;AACpE,MAAM,MAAM,oBAAoB,GAAG,OAAO,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAgBhE;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,kBAAkB,GAAG,cAAc,
|
|
1
|
+
{"version":3,"file":"authenticateV2.d.ts","sourceRoot":"","sources":["../../../../src/cloud/identity/authenticateV2.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEvD,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAE/D,OAAO,CAAC,MAAM,CAAC;IAEb,UAAU,OAAO,CAAC;QAChB,UAAU,OAAO;YACf,gEAAgE;YAChE,MAAM,CAAC,EAAE,MAAM,CAAC;SACjB;KACF;CACF;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;IAC1C,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,qFAAqF;IACrF,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,8CAA8C;IAC9C,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,oEAAoE;AACpE,MAAM,MAAM,oBAAoB,GAAG,OAAO,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAgBhE;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,kBAAkB,GAAG,cAAc,CA6CvE;AAED,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAChC,eAAe,cAAc,CAAC"}
|
|
@@ -36,16 +36,19 @@ export function authenticateV2(deps) {
|
|
|
36
36
|
return;
|
|
37
37
|
}
|
|
38
38
|
if (deps.rateLimiter) {
|
|
39
|
-
const
|
|
40
|
-
const
|
|
39
|
+
const limits = policy.limitsFor(tenant.plan);
|
|
40
|
+
const daily = await deps.rateLimiter.consume(tenant.id, limits.dailyRequests, windowMs, now());
|
|
41
|
+
// A request the day already refused does not eat the month's allowance.
|
|
42
|
+
const decision = !daily.allowed || !deps.rateLimiter.consumeMonthly
|
|
43
|
+
? daily
|
|
44
|
+
: await deps.rateLimiter.consumeMonthly(tenant.id, limits.monthlyRequests, now());
|
|
41
45
|
if (!decision.allowed) {
|
|
42
46
|
const retryAfter = Math.max(1, Math.ceil((decision.resetAt - now()) / 1000));
|
|
43
|
-
const upgradeUrl = policy.limitsFor(tenant.plan).upgradeUrl;
|
|
44
47
|
res
|
|
45
48
|
.status(429)
|
|
46
49
|
.set('Retry-After', String(retryAfter))
|
|
47
50
|
.set('WWW-Authenticate', 'Bearer')
|
|
48
|
-
.json(rateLimitErrorBody(decision, retryAfter, upgradeUrl));
|
|
51
|
+
.json(rateLimitErrorBody(decision, retryAfter, limits.upgradeUrl, decision === daily ? 'day' : 'month'));
|
|
49
52
|
return;
|
|
50
53
|
}
|
|
51
54
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authenticateV2.js","sourceRoot":"","sources":["../../../../src/cloud/identity/authenticateV2.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEhE,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AA0BnD,SAAS,WAAW,CAAC,MAA0B;IAC7C,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,MAAM,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IACrD,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACxC,CAAC;AAED,SAAS,oBAAoB;IAC3B,OAAO,IAAI,aAAa,CAAC;QACvB,IAAI,EAAE,iBAAiB;QACvB,MAAM,EAAE,GAAG;QACX,OAAO,EAAE,4BAA4B;KACtC,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,IAAwB;IACrD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;IAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,iBAAiB,IAAI,oBAAoB,CAAC;IAChE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;IAEjC,OAAO,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QAC9B,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;YAErD,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,oBAAoB,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC;gBACxF,OAAO;YACT,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAClD,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,oBAAoB,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC;gBACxF,OAAO;YACT,CAAC;YAED,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;gBACrB,MAAM,
|
|
1
|
+
{"version":3,"file":"authenticateV2.js","sourceRoot":"","sources":["../../../../src/cloud/identity/authenticateV2.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Lemma API v2 — identity store (Lane D)
|
|
3
|
-
*
|
|
4
|
-
* Persistence behind TenantResolver. Keys are stored as SHA-256 hashes only:
|
|
5
|
-
* `key_hash` is the sole column that ever touches key material, and every write
|
|
6
|
-
* is a parameterized insert that receives the hash, never the plaintext value.
|
|
7
|
-
*
|
|
8
|
-
* `InMemoryIdentityStore` powers unit tests and local/dev defaults.
|
|
9
|
-
* `PostgresIdentityStore` is the production implementation over `pg`.
|
|
10
|
-
*/
|
|
11
1
|
import type { Pool } from 'pg';
|
|
12
2
|
import type { KeyPrefix } from './ApiKey.js';
|
|
13
3
|
import type { PlanId } from './PlanPolicy.js';
|
|
@@ -30,6 +20,45 @@ export interface KeyRecord {
|
|
|
30
20
|
expiresAt: number | null;
|
|
31
21
|
revokedAt: number | null;
|
|
32
22
|
}
|
|
23
|
+
/** What Stripe last told us about the tenant's subscription. Display and webhook bookkeeping only: quota code reads `plan`. */
|
|
24
|
+
export interface TenantBilling {
|
|
25
|
+
customerId: string | null;
|
|
26
|
+
subscriptionId: string | null;
|
|
27
|
+
/** Stripe's subscription status verbatim (active, past_due, canceled, ...). */
|
|
28
|
+
status: string | null;
|
|
29
|
+
/** Epoch ms of the end of the paid period: the next charge, or the last day of service when cancelling. */
|
|
30
|
+
currentPeriodEnd: number | null;
|
|
31
|
+
/** Epoch ms of the first failed payment of the current late streak; null while paid up. */
|
|
32
|
+
pastDueSince: number | null;
|
|
33
|
+
/** Epoch ms `created` of the last Stripe event applied; older events are dropped (delivery is unordered). */
|
|
34
|
+
eventAt: number | null;
|
|
35
|
+
}
|
|
36
|
+
export declare const NO_BILLING: Readonly<TenantBilling>;
|
|
37
|
+
export interface TenantRecord {
|
|
38
|
+
id: string;
|
|
39
|
+
name: string;
|
|
40
|
+
plan: PlanId;
|
|
41
|
+
createdAt: number;
|
|
42
|
+
billing: TenantBilling;
|
|
43
|
+
}
|
|
44
|
+
/** Outcome of applying a Stripe event to a tenant. */
|
|
45
|
+
export type BillingApplyResult = {
|
|
46
|
+
ok: true;
|
|
47
|
+
tenant: TenantRecord;
|
|
48
|
+
} | {
|
|
49
|
+
ok: false;
|
|
50
|
+
reason: 'no_tenant' | 'stale';
|
|
51
|
+
};
|
|
52
|
+
/** Outcome of an atomic "issue a key if the tenant still has a free seat". */
|
|
53
|
+
export type SeatedKeyResult = {
|
|
54
|
+
ok: true;
|
|
55
|
+
key: KeyRecord;
|
|
56
|
+
} | {
|
|
57
|
+
ok: false;
|
|
58
|
+
reason: 'no_tenant' | 'seats_full' | 'duplicate_name';
|
|
59
|
+
seats: number;
|
|
60
|
+
used: number;
|
|
61
|
+
};
|
|
33
62
|
export interface IdentityStore {
|
|
34
63
|
/** Look up a key by its hash. The ONLY read path — plaintext never enters a query. */
|
|
35
64
|
findKeyByHash(hash: string): Promise<KeyRecord | null>;
|
|
@@ -37,12 +66,47 @@ export interface IdentityStore {
|
|
|
37
66
|
createKey(input: NewKeyInput): Promise<KeyRecord>;
|
|
38
67
|
/** Soft-revoke: the key dies on the NEXT lookup. No 24h cache can survive this. */
|
|
39
68
|
revokeKey(keyId: string): Promise<boolean>;
|
|
69
|
+
/** Create a tenant; resolves null when the id is already taken. */
|
|
70
|
+
createTenant(input: {
|
|
71
|
+
id: string;
|
|
72
|
+
name: string;
|
|
73
|
+
plan: PlanId;
|
|
74
|
+
}): Promise<TenantRecord | null>;
|
|
75
|
+
getTenant(id: string): Promise<TenantRecord | null>;
|
|
76
|
+
setTenantPlan(id: string, plan: PlanId): Promise<TenantRecord | null>;
|
|
77
|
+
findTenantByStripeCustomer(customerId: string): Promise<TenantRecord | null>;
|
|
78
|
+
/**
|
|
79
|
+
* Write the plan and the full billing state in one statement, unless a NEWER Stripe event was
|
|
80
|
+
* already applied (`billing.eventAt` older than the stored one): then nothing changes and the
|
|
81
|
+
* result says `stale`. The caller passes the complete state, so a field is cleared by sending null.
|
|
82
|
+
*/
|
|
83
|
+
applyBilling(id: string, plan: PlanId, billing: TenantBilling): Promise<BillingApplyResult>;
|
|
84
|
+
/** Every key the tenant ever had, newest first (hashes are never returned). */
|
|
85
|
+
listKeys(tenantId: string): Promise<KeyRecord[]>;
|
|
86
|
+
/**
|
|
87
|
+
* Issue a key only if the tenant has a free seat (active, unexpired keys < `seats`) and
|
|
88
|
+
* no active key already carries `input.name`. The check and the insert are atomic: two
|
|
89
|
+
* concurrent calls can never take the last seat twice.
|
|
90
|
+
*/
|
|
91
|
+
createKeyWithinSeats(input: NewKeyInput, seats: number): Promise<SeatedKeyResult>;
|
|
40
92
|
}
|
|
41
93
|
/** In-memory store. Records carry the hash only — same invariant as Postgres. */
|
|
42
94
|
export declare class InMemoryIdentityStore implements IdentityStore {
|
|
43
95
|
readonly records: Map<string, KeyRecord>;
|
|
44
96
|
findKeyByHash(hash: string): Promise<KeyRecord | null>;
|
|
45
97
|
createKey(input: NewKeyInput): Promise<KeyRecord>;
|
|
98
|
+
readonly tenants: Map<string, TenantRecord>;
|
|
99
|
+
createTenant(input: {
|
|
100
|
+
id: string;
|
|
101
|
+
name: string;
|
|
102
|
+
plan: PlanId;
|
|
103
|
+
}): Promise<TenantRecord | null>;
|
|
104
|
+
getTenant(id: string): Promise<TenantRecord | null>;
|
|
105
|
+
setTenantPlan(id: string, plan: PlanId): Promise<TenantRecord | null>;
|
|
106
|
+
findTenantByStripeCustomer(customerId: string): Promise<TenantRecord | null>;
|
|
107
|
+
applyBilling(id: string, plan: PlanId, billing: TenantBilling): Promise<BillingApplyResult>;
|
|
108
|
+
listKeys(tenantId: string): Promise<KeyRecord[]>;
|
|
109
|
+
createKeyWithinSeats(input: NewKeyInput, seats: number): Promise<SeatedKeyResult>;
|
|
46
110
|
revokeKey(keyId: string): Promise<boolean>;
|
|
47
111
|
}
|
|
48
112
|
/** Production store. All queries parameterized; key material appears only as hashed params. */
|
|
@@ -51,6 +115,17 @@ export declare class PostgresIdentityStore implements IdentityStore {
|
|
|
51
115
|
constructor(pool: Pool);
|
|
52
116
|
findKeyByHash(hash: string): Promise<KeyRecord | null>;
|
|
53
117
|
createKey(input: NewKeyInput): Promise<KeyRecord>;
|
|
118
|
+
createTenant(input: {
|
|
119
|
+
id: string;
|
|
120
|
+
name: string;
|
|
121
|
+
plan: PlanId;
|
|
122
|
+
}): Promise<TenantRecord | null>;
|
|
123
|
+
getTenant(id: string): Promise<TenantRecord | null>;
|
|
124
|
+
setTenantPlan(id: string, plan: PlanId): Promise<TenantRecord | null>;
|
|
125
|
+
findTenantByStripeCustomer(customerId: string): Promise<TenantRecord | null>;
|
|
126
|
+
applyBilling(id: string, plan: PlanId, b: TenantBilling): Promise<BillingApplyResult>;
|
|
127
|
+
listKeys(tenantId: string): Promise<KeyRecord[]>;
|
|
128
|
+
createKeyWithinSeats(input: NewKeyInput, seats: number): Promise<SeatedKeyResult>;
|
|
54
129
|
revokeKey(keyId: string): Promise<boolean>;
|
|
55
130
|
}
|
|
56
131
|
//# sourceMappingURL=identityStore.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"identityStore.d.ts","sourceRoot":"","sources":["../../../../src/cloud/identity/identityStore.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"identityStore.d.ts","sourceRoot":"","sources":["../../../../src/cloud/identity/identityStore.ts"],"names":[],"mappings":"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"}
|