kavachos 0.0.4 → 0.0.6
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/dist/a2a/index.d.ts +2340 -0
- package/dist/a2a/index.js +821 -0
- package/dist/a2a/index.js.map +1 -0
- package/dist/agent/index.d.ts +3 -4
- package/dist/agent/index.js +4 -3
- package/dist/audit/index.d.ts +2 -3
- package/dist/audit/index.js +3 -3
- package/dist/auth/index.d.ts +490 -93
- package/dist/auth/index.js +4 -3
- package/dist/{chunk-KL6XW4S4.js → chunk-FKVAXCNJ.js} +2375 -633
- package/dist/chunk-FKVAXCNJ.js.map +1 -0
- package/dist/{chunk-5DT4DN4Y.js → chunk-IKTOSJ4O.js} +13 -13
- package/dist/chunk-IKTOSJ4O.js.map +1 -0
- package/dist/{chunk-V66UUIA7.js → chunk-KDL6A76K.js} +93 -4
- package/dist/chunk-KDL6A76K.js.map +1 -0
- package/dist/chunk-NSBPE2FW.js +15 -0
- package/dist/{chunk-PZ5AY32C.js.map → chunk-NSBPE2FW.js.map} +1 -1
- package/dist/chunk-NSTER7KE.js +538 -0
- package/dist/chunk-NSTER7KE.js.map +1 -0
- package/dist/chunk-QCRHJMDX.js +186 -0
- package/dist/chunk-QCRHJMDX.js.map +1 -0
- package/dist/{chunk-OVGNZ5OX.js → chunk-VHKZARMM.js} +6 -6
- package/dist/chunk-VHKZARMM.js.map +1 -0
- package/dist/{chunk-SJGSPIAD.js → chunk-Y3OWAJHK.js} +3 -3
- package/dist/{chunk-SJGSPIAD.js.map → chunk-Y3OWAJHK.js.map} +1 -1
- package/dist/index.d.ts +138 -6
- package/dist/index.js +580 -35
- package/dist/index.js.map +1 -1
- package/dist/mcp/index.d.ts +2 -2
- package/dist/mcp/index.js +12 -16
- package/dist/mcp/index.js.map +1 -1
- package/dist/permission/index.d.ts +3 -4
- package/dist/permission/index.js +4 -3
- package/dist/{types-Xk83hv4O.d.ts → types-W8X0PXE7.d.ts} +1764 -99
- package/dist/vc/index.d.ts +800 -0
- package/dist/vc/index.js +5 -0
- package/dist/vc/index.js.map +1 -0
- package/package.json +17 -1
- package/dist/chunk-5DT4DN4Y.js.map +0 -1
- package/dist/chunk-KL6XW4S4.js.map +0 -1
- package/dist/chunk-OVGNZ5OX.js.map +0 -1
- package/dist/chunk-PZ5AY32C.js +0 -9
- package/dist/chunk-V66UUIA7.js.map +0 -1
- package/dist/{types-mwupB57A.d.ts → types-BuHrZcjE.d.ts} +2 -2
package/dist/index.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { createAgentModule } from './chunk-
|
|
2
|
-
export { createAgentModule } from './chunk-
|
|
3
|
-
import { createSessionManager, createMagicLinkModule, createEmailOtpModule, createTotpModule, createPasskeyModule, createOrgModule, createSsoModule, createAdminModule, createApiKeyManagerModule, createUsernameAuthModule, createPhoneAuthModule, createCaptchaModule, createWebhookModule } from './chunk-
|
|
4
|
-
export { HibpApiError, HibpBreachedError, OAuthProxyError, OneTapVerifyError, SSO_ERROR, SsoError, additionalFields, admin, anonymousAuth, apiKeys, bearerAuth, createAdditionalFieldsModule, createAdminModule, createAnonymousAuthModule, createApiKeyManagerModule, createCaptchaModule, createCustomSessionModule, createDeviceAuthModule, createEmailOtpModule, createGdprModule, createHibpModule, createJwtSessionModule, createLastLoginModule, createMagicLinkModule, createOAuthProxyModule, createOidcProviderModule, createOneTapModule, createOneTimeTokenModule, createOpenApiModule, createOrgModule, createPasskeyModule, createPhoneAuthModule, createPolarModule, createRateLimiter, createScimModule, createSessionManager, createSiweModule, createSsoModule, createStripeModule, createTotpModule, createTrustedDeviceModule, createUsernameAuthModule, customAuth, customSession, deviceAuth, deviceLabelFromRequest, emailOtp, gdpr, headerAuth, magicLink, oauthProxy, oneTap, organization, passkey, polar, scim, siwe, stripe, twoFactor, withRateLimit } from './chunk-
|
|
5
|
-
import { createPermissionEngine } from './chunk-
|
|
6
|
-
export { createPermissionEngine, getPermissionTemplate, permissionTemplates } from './chunk-
|
|
7
|
-
import { createAuditModule } from './chunk-
|
|
8
|
-
export { createAuditModule } from './chunk-
|
|
9
|
-
import { schema_exports, approvalRequests, sessions, delegationChains, agentDids, mcpServers, budgetPolicies, agents, permissions, auditLogs, tenants, trustScores } from './chunk-
|
|
10
|
-
export { agentCards, agentDids, agents, apiKeys as apiKeysTable, approvalRequests, auditLogs, budgetPolicies, delegationChains, emailOtps, magicLinks, mcpServers, oauthAccessTokens, oauthAuthorizationCodes, oauthClients, orgInvitations, orgMembers, orgRoles, organizations, passkeyChallenges, passkeyCredentials, permissions, rateLimits, sessions, ssoConnections, tenants, totpRecords, trustScores, users } from './chunk-
|
|
11
|
-
|
|
1
|
+
import { createAgentModule } from './chunk-IKTOSJ4O.js';
|
|
2
|
+
export { createAgentModule } from './chunk-IKTOSJ4O.js';
|
|
3
|
+
import { createSessionManager, createMagicLinkModule, createEmailOtpModule, createTotpModule, createPasskeyModule, createOrgModule, createSsoModule, createAdminModule, createApiKeyManagerModule, createUsernameAuthModule, createOneTimeTokenModule, createPasswordResetModule, createEmailVerificationModule, createPhoneAuthModule, createCaptchaModule, createWebhookModule } from './chunk-FKVAXCNJ.js';
|
|
4
|
+
export { EVENT_TYPES, HibpApiError, HibpBreachedError, OAuthProxyError, OneTapVerifyError, SSO_ERROR, SsoError, additionalFields, admin, anonymousAuth, apiKeys, bearerAuth, createAdditionalFieldsModule, createAdminModule, createAnonymousAuthModule, createApiKeyManagerModule, createCaptchaModule, createCostAttributionModule, createCustomSessionModule, createDeviceAuthModule, createEmailOtpModule, createEmailVerificationModule, createEphemeralSessionModule, createEventStreamModule, createFederationModule, createGdprModule, createHibpModule, createJwtSessionModule, createLastLoginModule, createMagicLinkModule, createOAuthProxyModule, createOidcProviderModule, createOneTapModule, createOneTimeTokenModule, createOpenApiModule, createOrgModule, createPasskeyModule, createPasswordResetModule, createPhoneAuthModule, createPolarModule, createRateLimiter, createReBACModule, createScimModule, createSessionManager, createSiweModule, createSsoModule, createStripeModule, createTotpModule, createTrustedDeviceModule, createUsernameAuthModule, customAuth, customSession, deviceAuth, deviceLabelFromRequest, emailOtp, gdpr, headerAuth, magicLink, oauthProxy, oneTap, organization, passkey, polar, scim, siwe, stripe, twoFactor, withRateLimit } from './chunk-FKVAXCNJ.js';
|
|
5
|
+
import { createPermissionEngine } from './chunk-VHKZARMM.js';
|
|
6
|
+
export { createPermissionEngine, getPermissionTemplate, permissionTemplates } from './chunk-VHKZARMM.js';
|
|
7
|
+
import { createAuditModule } from './chunk-Y3OWAJHK.js';
|
|
8
|
+
export { createAuditModule } from './chunk-Y3OWAJHK.js';
|
|
9
|
+
import { schema_exports, approvalRequests, sessions, delegationChains, agentDids, mcpServers, budgetPolicies, agents, permissions, auditLogs, tenants, trustScores } from './chunk-KDL6A76K.js';
|
|
10
|
+
export { agentCards, agentDids, agents, apiKeys as apiKeysTable, approvalRequests, auditLogs, budgetPolicies, delegationChains, emailOtps, magicLinks, mcpServers, oauthAccessTokens, oauthAuthorizationCodes, oauthClients, orgInvitations, orgMembers, orgRoles, organizations, passkeyChallenges, passkeyCredentials, permissions, rateLimits, sessions, ssoConnections, tenants, totpRecords, trustScores, users } from './chunk-KDL6A76K.js';
|
|
11
|
+
export { CredentialStatusSchema, CredentialSubjectSchema, KAVACH_AGENT_CREDENTIAL, KAVACH_DELEGATION_CREDENTIAL, KAVACH_PERMISSION_CREDENTIAL, ProofSchema, VC_CONTEXT_V1, VC_CONTEXT_V2, VC_TYPE_CREDENTIAL, VC_TYPE_PRESENTATION, VerifiableCredentialSchema, VerifiablePresentationSchema, createVCIssuer, createVCVerifier } from './chunk-NSTER7KE.js';
|
|
12
|
+
import { generateId } from './chunk-QCRHJMDX.js';
|
|
13
|
+
export { constantTimeEqual, fromBase64Url, fromHex, generateId, hmacSha1Raw, hmacSha256, hmacSha256Raw, importHmacKey, pbkdf2Hash, pbkdf2Verify, randomBytes, randomBytesHex, sha1, sha256, sha256Raw, toBase64Url, toHex } from './chunk-QCRHJMDX.js';
|
|
14
|
+
import { __require } from './chunk-NSBPE2FW.js';
|
|
12
15
|
import { eq, and, lt, ne, or, isNull, gte } from 'drizzle-orm';
|
|
13
|
-
import { randomUUID } from 'crypto';
|
|
14
|
-
import BetterSqlite3 from 'better-sqlite3';
|
|
15
|
-
import { drizzle } from 'drizzle-orm/better-sqlite3';
|
|
16
16
|
import { generateKeyPair, exportJWK, importJWK, SignJWT, jwtVerify } from 'jose';
|
|
17
17
|
|
|
18
18
|
var DEFAULT_LOOKBACK_DAYS = 30;
|
|
@@ -226,7 +226,7 @@ function createApprovalModule(config, db) {
|
|
|
226
226
|
const ttlSeconds = config.ttl ?? 300;
|
|
227
227
|
async function request(input) {
|
|
228
228
|
const now = /* @__PURE__ */ new Date();
|
|
229
|
-
const id = `apr_${
|
|
229
|
+
const id = `apr_${generateId()}`;
|
|
230
230
|
const expiresAt = new Date(now.getTime() + ttlSeconds * 1e3);
|
|
231
231
|
await db.insert(approvalRequests).values({
|
|
232
232
|
id,
|
|
@@ -314,12 +314,20 @@ function createApprovalModule(config, db) {
|
|
|
314
314
|
cleanup
|
|
315
315
|
};
|
|
316
316
|
}
|
|
317
|
+
|
|
318
|
+
// src/db/database.ts
|
|
317
319
|
async function createDatabase(config) {
|
|
318
320
|
if (config.provider === "sqlite") {
|
|
321
|
+
const BetterSqlite3 = (await import('better-sqlite3').catch(() => {
|
|
322
|
+
throw new Error(
|
|
323
|
+
'KavachOS: provider "sqlite" requires the "better-sqlite3" package. Install it with: npm install better-sqlite3'
|
|
324
|
+
);
|
|
325
|
+
})).default;
|
|
326
|
+
const { drizzle: drizzleSqlite } = await import('drizzle-orm/better-sqlite3');
|
|
319
327
|
const sqlite = new BetterSqlite3(config.url);
|
|
320
328
|
sqlite.pragma("journal_mode = WAL");
|
|
321
329
|
sqlite.pragma("foreign_keys = ON");
|
|
322
|
-
return
|
|
330
|
+
return drizzleSqlite(sqlite, { schema: schema_exports });
|
|
323
331
|
}
|
|
324
332
|
if (config.provider === "postgres") {
|
|
325
333
|
const { Pool } = await import('pg').catch(() => {
|
|
@@ -341,8 +349,12 @@ async function createDatabase(config) {
|
|
|
341
349
|
const pool = mysql2.createPool(config.url);
|
|
342
350
|
return drizzle(pool);
|
|
343
351
|
}
|
|
352
|
+
if (config.provider === "d1") {
|
|
353
|
+
const { drizzle } = await import('drizzle-orm/d1');
|
|
354
|
+
return drizzle(config.binding, { schema: schema_exports });
|
|
355
|
+
}
|
|
344
356
|
throw new Error(
|
|
345
|
-
`KavachOS: unsupported database provider "${config.provider}". Valid values are "sqlite", "postgres", "mysql".`
|
|
357
|
+
`KavachOS: unsupported database provider "${config.provider}". Valid values are "sqlite", "postgres", "mysql", "d1".`
|
|
346
358
|
);
|
|
347
359
|
}
|
|
348
360
|
function createDatabaseSync(config) {
|
|
@@ -351,10 +363,14 @@ function createDatabaseSync(config) {
|
|
|
351
363
|
`createDatabaseSync() only supports SQLite. Use the async createDatabase() for provider "${config.provider}".`
|
|
352
364
|
);
|
|
353
365
|
}
|
|
354
|
-
const
|
|
366
|
+
const { createRequire } = __require("module");
|
|
367
|
+
const req = createRequire(import.meta.url);
|
|
368
|
+
const BetterSqlite3Mod = req("better-sqlite3");
|
|
369
|
+
const { drizzle: drizzleSqliteMod } = req("drizzle-orm/better-sqlite3");
|
|
370
|
+
const sqlite = new BetterSqlite3Mod(config.url);
|
|
355
371
|
sqlite.pragma("journal_mode = WAL");
|
|
356
372
|
sqlite.pragma("foreign_keys = ON");
|
|
357
|
-
return
|
|
373
|
+
return drizzleSqliteMod(sqlite, { schema: schema_exports });
|
|
358
374
|
}
|
|
359
375
|
|
|
360
376
|
// src/db/migrations.ts
|
|
@@ -382,6 +398,7 @@ function buildStatements(provider) {
|
|
|
382
398
|
ban_reason TEXT,
|
|
383
399
|
ban_expires_at ${tsNull},
|
|
384
400
|
force_password_reset ${bool} NOT NULL DEFAULT ${isPostgres ? "FALSE" : "0"},
|
|
401
|
+
email_verified ${bool} NOT NULL DEFAULT ${isPostgres ? "FALSE" : "0"},
|
|
385
402
|
stripe_customer_id TEXT UNIQUE,
|
|
386
403
|
stripe_subscription_id TEXT,
|
|
387
404
|
stripe_subscription_status TEXT,
|
|
@@ -857,6 +874,45 @@ function buildStatements(provider) {
|
|
|
857
874
|
expires_at ${ts} NOT NULL,
|
|
858
875
|
created_at ${ts} NOT NULL
|
|
859
876
|
)`,
|
|
877
|
+
// ------------------------------------------------------------------
|
|
878
|
+
// kavach_cost_events (per-agent cost attribution)
|
|
879
|
+
// ------------------------------------------------------------------
|
|
880
|
+
`CREATE TABLE ${ifne} kavach_cost_events (
|
|
881
|
+
id TEXT NOT NULL PRIMARY KEY,
|
|
882
|
+
agent_id TEXT NOT NULL REFERENCES kavach_agents(id) ON DELETE CASCADE,
|
|
883
|
+
tool TEXT NOT NULL,
|
|
884
|
+
input_tokens INTEGER,
|
|
885
|
+
output_tokens INTEGER,
|
|
886
|
+
cost_micros INTEGER NOT NULL,
|
|
887
|
+
currency TEXT NOT NULL DEFAULT 'USD',
|
|
888
|
+
metadata ${json},
|
|
889
|
+
delegation_chain_id TEXT,
|
|
890
|
+
recorded_at ${ts} NOT NULL
|
|
891
|
+
)`,
|
|
892
|
+
`CREATE INDEX ${ifne} kavach_cost_events_agent_recorded
|
|
893
|
+
ON kavach_cost_events (agent_id, recorded_at DESC)`,
|
|
894
|
+
`CREATE INDEX ${ifne} kavach_cost_events_chain_id
|
|
895
|
+
ON kavach_cost_events (delegation_chain_id)`,
|
|
896
|
+
// ------------------------------------------------------------------
|
|
897
|
+
// kavach_ephemeral_sessions (short-lived agent credentials)
|
|
898
|
+
// ------------------------------------------------------------------
|
|
899
|
+
`CREATE TABLE ${ifne} kavach_ephemeral_sessions (
|
|
900
|
+
id TEXT NOT NULL PRIMARY KEY,
|
|
901
|
+
agent_id TEXT NOT NULL REFERENCES kavach_agents(id) ON DELETE CASCADE,
|
|
902
|
+
owner_id TEXT NOT NULL REFERENCES kavach_users(id),
|
|
903
|
+
token_hash TEXT NOT NULL UNIQUE,
|
|
904
|
+
expires_at ${ts} NOT NULL,
|
|
905
|
+
max_actions INTEGER,
|
|
906
|
+
actions_used INTEGER NOT NULL DEFAULT 0,
|
|
907
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
908
|
+
audit_group_id TEXT NOT NULL,
|
|
909
|
+
created_at ${ts} NOT NULL,
|
|
910
|
+
updated_at ${ts} NOT NULL
|
|
911
|
+
)`,
|
|
912
|
+
`CREATE INDEX ${ifne} kavach_ephemeral_sessions_owner_status
|
|
913
|
+
ON kavach_ephemeral_sessions (owner_id, status)`,
|
|
914
|
+
`CREATE INDEX ${ifne} kavach_ephemeral_sessions_expires_at
|
|
915
|
+
ON kavach_ephemeral_sessions (expires_at)`,
|
|
860
916
|
// ------------------------------------------------------------------
|
|
861
917
|
// kavach_jwt_refresh_tokens (JWT session plugin — general purpose)
|
|
862
918
|
// ------------------------------------------------------------------
|
|
@@ -869,7 +925,84 @@ function buildStatements(provider) {
|
|
|
869
925
|
created_at ${ts} NOT NULL
|
|
870
926
|
)`,
|
|
871
927
|
`CREATE INDEX ${ifne} kavach_jwt_refresh_tokens_user_id
|
|
872
|
-
ON kavach_jwt_refresh_tokens (user_id)
|
|
928
|
+
ON kavach_jwt_refresh_tokens (user_id)`,
|
|
929
|
+
// ------------------------------------------------------------------
|
|
930
|
+
// kavach_stream_events (persisted SSE events for replay)
|
|
931
|
+
// ------------------------------------------------------------------
|
|
932
|
+
`CREATE TABLE ${ifne} kavach_stream_events (
|
|
933
|
+
id TEXT NOT NULL PRIMARY KEY,
|
|
934
|
+
type TEXT NOT NULL,
|
|
935
|
+
timestamp ${ts} NOT NULL,
|
|
936
|
+
data ${json} NOT NULL,
|
|
937
|
+
agent_id TEXT,
|
|
938
|
+
user_id TEXT
|
|
939
|
+
)`,
|
|
940
|
+
`CREATE INDEX ${ifne} kavach_stream_events_timestamp
|
|
941
|
+
ON kavach_stream_events (timestamp DESC)`,
|
|
942
|
+
`CREATE INDEX ${ifne} kavach_stream_events_type_timestamp
|
|
943
|
+
ON kavach_stream_events (type, timestamp DESC)`,
|
|
944
|
+
// ------------------------------------------------------------------
|
|
945
|
+
// kavach_rebac_resources (ReBAC resource hierarchy)
|
|
946
|
+
// ------------------------------------------------------------------
|
|
947
|
+
`CREATE TABLE ${ifne} kavach_rebac_resources (
|
|
948
|
+
id TEXT NOT NULL PRIMARY KEY,
|
|
949
|
+
type TEXT NOT NULL,
|
|
950
|
+
parent_id TEXT,
|
|
951
|
+
parent_type TEXT,
|
|
952
|
+
created_at ${ts} NOT NULL
|
|
953
|
+
)`,
|
|
954
|
+
`CREATE INDEX ${ifne} kavach_rebac_resources_parent
|
|
955
|
+
ON kavach_rebac_resources (parent_id, parent_type)`,
|
|
956
|
+
// ------------------------------------------------------------------
|
|
957
|
+
// kavach_rebac_relationships (Zanzibar-style subject-relation-object tuples)
|
|
958
|
+
// ------------------------------------------------------------------
|
|
959
|
+
`CREATE TABLE ${ifne} kavach_rebac_relationships (
|
|
960
|
+
id TEXT NOT NULL PRIMARY KEY,
|
|
961
|
+
subject_type TEXT NOT NULL,
|
|
962
|
+
subject_id TEXT NOT NULL,
|
|
963
|
+
relation TEXT NOT NULL,
|
|
964
|
+
object_type TEXT NOT NULL,
|
|
965
|
+
object_id TEXT NOT NULL,
|
|
966
|
+
created_at ${ts} NOT NULL
|
|
967
|
+
)`,
|
|
968
|
+
`CREATE INDEX ${ifne} kavach_rebac_relationships_subject
|
|
969
|
+
ON kavach_rebac_relationships (subject_type, subject_id)`,
|
|
970
|
+
`CREATE INDEX ${ifne} kavach_rebac_relationships_object
|
|
971
|
+
ON kavach_rebac_relationships (object_type, object_id)`,
|
|
972
|
+
`CREATE UNIQUE INDEX ${ifne} kavach_rebac_relationships_tuple
|
|
973
|
+
ON kavach_rebac_relationships (subject_type, subject_id, relation, object_type, object_id)`,
|
|
974
|
+
// ------------------------------------------------------------------
|
|
975
|
+
// kavach_federation_instances (trusted remote KavachOS instances)
|
|
976
|
+
// ------------------------------------------------------------------
|
|
977
|
+
`CREATE TABLE ${ifne} kavach_federation_instances (
|
|
978
|
+
id TEXT NOT NULL PRIMARY KEY,
|
|
979
|
+
instance_id TEXT NOT NULL UNIQUE,
|
|
980
|
+
instance_url TEXT NOT NULL,
|
|
981
|
+
public_key_jwk TEXT,
|
|
982
|
+
trust_level TEXT NOT NULL DEFAULT 'verify-only',
|
|
983
|
+
discovered_at ${tsNull},
|
|
984
|
+
created_at ${ts} NOT NULL,
|
|
985
|
+
updated_at ${ts} NOT NULL
|
|
986
|
+
)`,
|
|
987
|
+
// ------------------------------------------------------------------
|
|
988
|
+
// kavach_federation_tokens (issued/received federation tokens)
|
|
989
|
+
// ------------------------------------------------------------------
|
|
990
|
+
`CREATE TABLE ${ifne} kavach_federation_tokens (
|
|
991
|
+
id TEXT NOT NULL PRIMARY KEY,
|
|
992
|
+
token_jti TEXT NOT NULL UNIQUE,
|
|
993
|
+
agent_id TEXT NOT NULL,
|
|
994
|
+
source_instance_id TEXT NOT NULL,
|
|
995
|
+
target_instance_id TEXT,
|
|
996
|
+
direction TEXT NOT NULL,
|
|
997
|
+
permissions ${json} NOT NULL,
|
|
998
|
+
trust_score INTEGER,
|
|
999
|
+
expires_at ${ts} NOT NULL,
|
|
1000
|
+
created_at ${ts} NOT NULL
|
|
1001
|
+
)`,
|
|
1002
|
+
`CREATE INDEX ${ifne} kavach_federation_tokens_agent
|
|
1003
|
+
ON kavach_federation_tokens (agent_id)`,
|
|
1004
|
+
`CREATE INDEX ${ifne} kavach_federation_tokens_source
|
|
1005
|
+
ON kavach_federation_tokens (source_instance_id)`
|
|
873
1006
|
// ------------------------------------------------------------------
|
|
874
1007
|
// kavach_users ban columns (ALTER TABLE IF NOT EXISTS — safe no-ops)
|
|
875
1008
|
// These are appended as separate ALTER statements for existing DBs.
|
|
@@ -960,7 +1093,7 @@ function createDelegationModule(config) {
|
|
|
960
1093
|
`Delegation depth ${currentDepth} exceeds maximum allowed depth of ${maxDepth}. This prevents infinite delegation chains.`
|
|
961
1094
|
);
|
|
962
1095
|
}
|
|
963
|
-
const id =
|
|
1096
|
+
const id = generateId();
|
|
964
1097
|
const now = /* @__PURE__ */ new Date();
|
|
965
1098
|
await db.insert(delegationChains).values({
|
|
966
1099
|
id,
|
|
@@ -2107,7 +2240,7 @@ function isExceeded(limits, usage) {
|
|
|
2107
2240
|
}
|
|
2108
2241
|
function createPolicyModule(db) {
|
|
2109
2242
|
async function create(input) {
|
|
2110
|
-
const id = `pol_${
|
|
2243
|
+
const id = `pol_${generateId().replace(/-/g, "")}`;
|
|
2111
2244
|
const now = /* @__PURE__ */ new Date();
|
|
2112
2245
|
const usage = emptyUsage();
|
|
2113
2246
|
await db.insert(budgetPolicies).values({
|
|
@@ -2262,6 +2395,334 @@ function createPolicyModule(db) {
|
|
|
2262
2395
|
}
|
|
2263
2396
|
return { create, get, list, update, remove, checkBudget, recordUsage, resetDaily, resetMonthly };
|
|
2264
2397
|
}
|
|
2398
|
+
|
|
2399
|
+
// src/redirect/chain.ts
|
|
2400
|
+
var DEFAULT_COOKIE_NAME = "kavach_redirect";
|
|
2401
|
+
var DEFAULT_MAX_AGE = 600;
|
|
2402
|
+
var DEFAULT_PATH = "/";
|
|
2403
|
+
var DEFAULT_MAX_DEPTH = 10;
|
|
2404
|
+
var DEFAULT_EXCLUDE_PATHS = [
|
|
2405
|
+
"/sign-in",
|
|
2406
|
+
"/sign-up",
|
|
2407
|
+
"/forgot-password",
|
|
2408
|
+
"/reset-password",
|
|
2409
|
+
"/verify-email",
|
|
2410
|
+
"/api/"
|
|
2411
|
+
];
|
|
2412
|
+
var encoder = new TextEncoder();
|
|
2413
|
+
var decoder = new TextDecoder();
|
|
2414
|
+
function encodeState(state) {
|
|
2415
|
+
const json = JSON.stringify(state);
|
|
2416
|
+
const bytes = encoder.encode(json);
|
|
2417
|
+
let binary = "";
|
|
2418
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
2419
|
+
binary += String.fromCharCode(bytes[i]);
|
|
2420
|
+
}
|
|
2421
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
2422
|
+
}
|
|
2423
|
+
function decodeState(encoded) {
|
|
2424
|
+
try {
|
|
2425
|
+
let base64 = encoded.replace(/-/g, "+").replace(/_/g, "/");
|
|
2426
|
+
while (base64.length % 4 !== 0) {
|
|
2427
|
+
base64 += "=";
|
|
2428
|
+
}
|
|
2429
|
+
const binary = atob(base64);
|
|
2430
|
+
const bytes = new Uint8Array(binary.length);
|
|
2431
|
+
for (let i = 0; i < binary.length; i++) {
|
|
2432
|
+
bytes[i] = binary.charCodeAt(i);
|
|
2433
|
+
}
|
|
2434
|
+
const json = decoder.decode(bytes);
|
|
2435
|
+
const parsed = JSON.parse(json);
|
|
2436
|
+
if (!isValidChainState(parsed)) return null;
|
|
2437
|
+
return parsed;
|
|
2438
|
+
} catch {
|
|
2439
|
+
return null;
|
|
2440
|
+
}
|
|
2441
|
+
}
|
|
2442
|
+
function isValidChainState(value) {
|
|
2443
|
+
if (typeof value !== "object" || value === null) return false;
|
|
2444
|
+
const obj = value;
|
|
2445
|
+
if (typeof obj.createdAt !== "number") return false;
|
|
2446
|
+
if (!isValidEntry(obj.origin)) return false;
|
|
2447
|
+
if (!Array.isArray(obj.steps)) return false;
|
|
2448
|
+
for (const step of obj.steps) {
|
|
2449
|
+
if (!isValidEntry(step)) return false;
|
|
2450
|
+
}
|
|
2451
|
+
return true;
|
|
2452
|
+
}
|
|
2453
|
+
function isValidEntry(value) {
|
|
2454
|
+
if (typeof value !== "object" || value === null) return false;
|
|
2455
|
+
const obj = value;
|
|
2456
|
+
return typeof obj.id === "string" && typeof obj.path === "string" && typeof obj.query === "object" && obj.query !== null && typeof obj.hash === "string" && typeof obj.createdAt === "number";
|
|
2457
|
+
}
|
|
2458
|
+
function parseCookies(request) {
|
|
2459
|
+
const header = request.headers.get("cookie");
|
|
2460
|
+
if (!header) return {};
|
|
2461
|
+
const cookies = {};
|
|
2462
|
+
for (const pair of header.split(";")) {
|
|
2463
|
+
const eqIdx = pair.indexOf("=");
|
|
2464
|
+
if (eqIdx === -1) continue;
|
|
2465
|
+
const key = pair.slice(0, eqIdx).trim();
|
|
2466
|
+
const val = pair.slice(eqIdx + 1).trim();
|
|
2467
|
+
cookies[key] = val;
|
|
2468
|
+
}
|
|
2469
|
+
return cookies;
|
|
2470
|
+
}
|
|
2471
|
+
function isExcluded(path, excludePaths) {
|
|
2472
|
+
for (const excluded of excludePaths) {
|
|
2473
|
+
if (excluded.endsWith("/")) {
|
|
2474
|
+
if (path.startsWith(excluded) || path === excluded.slice(0, -1)) return true;
|
|
2475
|
+
} else {
|
|
2476
|
+
if (path === excluded) return true;
|
|
2477
|
+
}
|
|
2478
|
+
}
|
|
2479
|
+
return false;
|
|
2480
|
+
}
|
|
2481
|
+
function createRedirectChain(config) {
|
|
2482
|
+
const cookieName = config?.cookieName ?? DEFAULT_COOKIE_NAME;
|
|
2483
|
+
const maxAge = config?.maxAge ?? DEFAULT_MAX_AGE;
|
|
2484
|
+
const defaultPath = config?.defaultPath ?? DEFAULT_PATH;
|
|
2485
|
+
const excludePaths = config?.excludePaths ?? DEFAULT_EXCLUDE_PATHS;
|
|
2486
|
+
const preserveQuery = config?.preserveQuery ?? true;
|
|
2487
|
+
const preserveHash = config?.preserveHash ?? true;
|
|
2488
|
+
const maxDepth = config?.maxDepth ?? DEFAULT_MAX_DEPTH;
|
|
2489
|
+
const cookieOpts = {
|
|
2490
|
+
httpOnly: config?.cookie?.httpOnly ?? true,
|
|
2491
|
+
secure: config?.cookie?.secure ?? true,
|
|
2492
|
+
sameSite: config?.cookie?.sameSite ?? "lax",
|
|
2493
|
+
path: config?.cookie?.path ?? "/",
|
|
2494
|
+
domain: config?.cookie?.domain
|
|
2495
|
+
};
|
|
2496
|
+
let currentState = null;
|
|
2497
|
+
function buildCookieHeader(value, age) {
|
|
2498
|
+
const parts = [`${cookieName}=${value}`, `Path=${cookieOpts.path}`, `Max-Age=${age}`];
|
|
2499
|
+
if (cookieOpts.httpOnly) parts.push("HttpOnly");
|
|
2500
|
+
if (cookieOpts.secure) parts.push("Secure");
|
|
2501
|
+
parts.push(
|
|
2502
|
+
`SameSite=${cookieOpts.sameSite.charAt(0).toUpperCase()}${cookieOpts.sameSite.slice(1)}`
|
|
2503
|
+
);
|
|
2504
|
+
if (cookieOpts.domain) parts.push(`Domain=${cookieOpts.domain}`);
|
|
2505
|
+
return parts.join("; ");
|
|
2506
|
+
}
|
|
2507
|
+
function buildClearCookie() {
|
|
2508
|
+
return buildCookieHeader("", 0);
|
|
2509
|
+
}
|
|
2510
|
+
function serializeAndSetCookie(state) {
|
|
2511
|
+
currentState = state;
|
|
2512
|
+
const encoded = encodeState(state);
|
|
2513
|
+
return buildCookieHeader(encoded, maxAge);
|
|
2514
|
+
}
|
|
2515
|
+
function parseFromRequest(request) {
|
|
2516
|
+
const cookies = parseCookies(request);
|
|
2517
|
+
const raw = cookies[cookieName];
|
|
2518
|
+
if (!raw) return null;
|
|
2519
|
+
const state = decodeState(raw);
|
|
2520
|
+
if (!state) return null;
|
|
2521
|
+
const elapsed = Date.now() - state.createdAt;
|
|
2522
|
+
if (elapsed > maxAge * 1e3) return null;
|
|
2523
|
+
currentState = state;
|
|
2524
|
+
return state;
|
|
2525
|
+
}
|
|
2526
|
+
function createEntryFromUrl(url, label) {
|
|
2527
|
+
let parsed;
|
|
2528
|
+
if (typeof url === "string") {
|
|
2529
|
+
if (url.startsWith("/")) {
|
|
2530
|
+
parsed = new URL(url, "http://localhost");
|
|
2531
|
+
} else {
|
|
2532
|
+
parsed = new URL(url);
|
|
2533
|
+
}
|
|
2534
|
+
} else {
|
|
2535
|
+
parsed = new URL(url.url);
|
|
2536
|
+
}
|
|
2537
|
+
const query = {};
|
|
2538
|
+
if (preserveQuery) {
|
|
2539
|
+
parsed.searchParams.forEach((value, key) => {
|
|
2540
|
+
query[key] = value;
|
|
2541
|
+
});
|
|
2542
|
+
}
|
|
2543
|
+
return {
|
|
2544
|
+
id: generateId(),
|
|
2545
|
+
path: parsed.pathname,
|
|
2546
|
+
query,
|
|
2547
|
+
hash: preserveHash ? parsed.hash.replace(/^#/, "") : "",
|
|
2548
|
+
createdAt: Date.now(),
|
|
2549
|
+
label
|
|
2550
|
+
};
|
|
2551
|
+
}
|
|
2552
|
+
function buildUrlFromEntry(entry) {
|
|
2553
|
+
let url = entry.path;
|
|
2554
|
+
const params = Object.entries(entry.query);
|
|
2555
|
+
if (params.length > 0) {
|
|
2556
|
+
const searchParams = new URLSearchParams();
|
|
2557
|
+
for (const [key, value] of params) {
|
|
2558
|
+
searchParams.set(key, value);
|
|
2559
|
+
}
|
|
2560
|
+
url += `?${searchParams.toString()}`;
|
|
2561
|
+
}
|
|
2562
|
+
if (entry.hash) {
|
|
2563
|
+
url += `#${entry.hash}`;
|
|
2564
|
+
}
|
|
2565
|
+
return url;
|
|
2566
|
+
}
|
|
2567
|
+
const manager = {
|
|
2568
|
+
capture(request) {
|
|
2569
|
+
const existing = parseFromRequest(request);
|
|
2570
|
+
if (existing) {
|
|
2571
|
+
return serializeAndSetCookie(existing);
|
|
2572
|
+
}
|
|
2573
|
+
const entry = createEntryFromUrl(request);
|
|
2574
|
+
if (isExcluded(entry.path, excludePaths)) {
|
|
2575
|
+
entry.path = defaultPath;
|
|
2576
|
+
entry.query = {};
|
|
2577
|
+
entry.hash = "";
|
|
2578
|
+
}
|
|
2579
|
+
const state = {
|
|
2580
|
+
origin: entry,
|
|
2581
|
+
steps: [],
|
|
2582
|
+
createdAt: Date.now()
|
|
2583
|
+
};
|
|
2584
|
+
return serializeAndSetCookie(state);
|
|
2585
|
+
},
|
|
2586
|
+
push(path, options) {
|
|
2587
|
+
if (!currentState) {
|
|
2588
|
+
currentState = {
|
|
2589
|
+
origin: {
|
|
2590
|
+
id: generateId(),
|
|
2591
|
+
path: defaultPath,
|
|
2592
|
+
query: {},
|
|
2593
|
+
hash: "",
|
|
2594
|
+
createdAt: Date.now()
|
|
2595
|
+
},
|
|
2596
|
+
steps: [],
|
|
2597
|
+
createdAt: Date.now()
|
|
2598
|
+
};
|
|
2599
|
+
}
|
|
2600
|
+
if (currentState.steps.length >= maxDepth) {
|
|
2601
|
+
return serializeAndSetCookie(currentState);
|
|
2602
|
+
}
|
|
2603
|
+
const entry = {
|
|
2604
|
+
id: generateId(),
|
|
2605
|
+
path,
|
|
2606
|
+
query: options?.query ?? {},
|
|
2607
|
+
hash: "",
|
|
2608
|
+
createdAt: Date.now(),
|
|
2609
|
+
label: options?.label
|
|
2610
|
+
};
|
|
2611
|
+
currentState.steps.push(entry);
|
|
2612
|
+
return serializeAndSetCookie(currentState);
|
|
2613
|
+
},
|
|
2614
|
+
pop(request) {
|
|
2615
|
+
const state = parseFromRequest(request);
|
|
2616
|
+
if (!state) {
|
|
2617
|
+
return { url: defaultPath, done: true, clearCookie: buildClearCookie() };
|
|
2618
|
+
}
|
|
2619
|
+
if (state.steps.length > 0) {
|
|
2620
|
+
const next = state.steps.shift();
|
|
2621
|
+
const url2 = buildUrlFromEntry(next);
|
|
2622
|
+
if (state.steps.length === 0) {
|
|
2623
|
+
currentState = state;
|
|
2624
|
+
return {
|
|
2625
|
+
url: url2,
|
|
2626
|
+
done: false,
|
|
2627
|
+
clearCookie: null
|
|
2628
|
+
};
|
|
2629
|
+
}
|
|
2630
|
+
return {
|
|
2631
|
+
url: url2,
|
|
2632
|
+
done: false,
|
|
2633
|
+
clearCookie: null
|
|
2634
|
+
};
|
|
2635
|
+
}
|
|
2636
|
+
const url = buildUrlFromEntry(state.origin);
|
|
2637
|
+
currentState = null;
|
|
2638
|
+
return {
|
|
2639
|
+
url,
|
|
2640
|
+
done: true,
|
|
2641
|
+
clearCookie: buildClearCookie()
|
|
2642
|
+
};
|
|
2643
|
+
},
|
|
2644
|
+
peek(request) {
|
|
2645
|
+
const state = parseFromRequest(request);
|
|
2646
|
+
if (!state) return null;
|
|
2647
|
+
if (state.steps.length > 0) {
|
|
2648
|
+
const next = state.steps[0];
|
|
2649
|
+
return {
|
|
2650
|
+
url: buildUrlFromEntry(next),
|
|
2651
|
+
remaining: state.steps.length
|
|
2652
|
+
// +origin is implicit
|
|
2653
|
+
};
|
|
2654
|
+
}
|
|
2655
|
+
return {
|
|
2656
|
+
url: buildUrlFromEntry(state.origin),
|
|
2657
|
+
remaining: 0
|
|
2658
|
+
};
|
|
2659
|
+
},
|
|
2660
|
+
getOrigin(request) {
|
|
2661
|
+
const state = parseFromRequest(request);
|
|
2662
|
+
if (!state) return null;
|
|
2663
|
+
return state.origin;
|
|
2664
|
+
},
|
|
2665
|
+
clear() {
|
|
2666
|
+
currentState = null;
|
|
2667
|
+
return buildClearCookie();
|
|
2668
|
+
},
|
|
2669
|
+
parse(request) {
|
|
2670
|
+
return parseFromRequest(request);
|
|
2671
|
+
},
|
|
2672
|
+
buildUrl(entry) {
|
|
2673
|
+
return buildUrlFromEntry(entry);
|
|
2674
|
+
},
|
|
2675
|
+
createEntry(url, label) {
|
|
2676
|
+
return createEntryFromUrl(url, label);
|
|
2677
|
+
}
|
|
2678
|
+
};
|
|
2679
|
+
return manager;
|
|
2680
|
+
}
|
|
2681
|
+
|
|
2682
|
+
// src/session/freshness.ts
|
|
2683
|
+
var DEFAULT_FRESH_AGE_SECONDS = 300;
|
|
2684
|
+
function createSessionFreshnessModule(config = {}) {
|
|
2685
|
+
const freshAge = config.freshAge ?? DEFAULT_FRESH_AGE_SECONDS;
|
|
2686
|
+
function isFresh(session) {
|
|
2687
|
+
const now = Date.now();
|
|
2688
|
+
const createdAt = session.createdAt.getTime();
|
|
2689
|
+
return now - createdAt < freshAge * 1e3;
|
|
2690
|
+
}
|
|
2691
|
+
function requireFresh(session) {
|
|
2692
|
+
if (isFresh(session)) {
|
|
2693
|
+
const freshUntil = new Date(session.createdAt.getTime() + freshAge * 1e3);
|
|
2694
|
+
return { success: true, data: { freshUntil } };
|
|
2695
|
+
}
|
|
2696
|
+
return {
|
|
2697
|
+
success: false,
|
|
2698
|
+
error: {
|
|
2699
|
+
code: "SESSION_NOT_FRESH",
|
|
2700
|
+
message: "Session is not fresh. Please re-authenticate to perform this action.",
|
|
2701
|
+
details: {
|
|
2702
|
+
createdAt: session.createdAt.toISOString(),
|
|
2703
|
+
freshAge,
|
|
2704
|
+
requiredAfter: new Date(session.createdAt.getTime() + freshAge * 1e3).toISOString()
|
|
2705
|
+
}
|
|
2706
|
+
}
|
|
2707
|
+
};
|
|
2708
|
+
}
|
|
2709
|
+
function guard(session) {
|
|
2710
|
+
if (isFresh(session)) return null;
|
|
2711
|
+
return new Response(
|
|
2712
|
+
JSON.stringify({
|
|
2713
|
+
error: {
|
|
2714
|
+
code: "SESSION_NOT_FRESH",
|
|
2715
|
+
message: "Session is not fresh. Please re-authenticate to perform this action."
|
|
2716
|
+
}
|
|
2717
|
+
}),
|
|
2718
|
+
{
|
|
2719
|
+
status: 403,
|
|
2720
|
+
headers: { "Content-Type": "application/json" }
|
|
2721
|
+
}
|
|
2722
|
+
);
|
|
2723
|
+
}
|
|
2724
|
+
return { isFresh, requireFresh, guard };
|
|
2725
|
+
}
|
|
2265
2726
|
function slugRegex() {
|
|
2266
2727
|
return /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
2267
2728
|
}
|
|
@@ -2287,7 +2748,7 @@ function createTenantModule(db) {
|
|
|
2287
2748
|
if (existing.length > 0) {
|
|
2288
2749
|
throw new Error(`Tenant with slug "${input.slug}" already exists.`);
|
|
2289
2750
|
}
|
|
2290
|
-
const id = `tnt_${
|
|
2751
|
+
const id = `tnt_${generateId().replace(/-/g, "")}`;
|
|
2291
2752
|
const now = /* @__PURE__ */ new Date();
|
|
2292
2753
|
const settings = input.settings ?? {};
|
|
2293
2754
|
await db.insert(tenants).values({
|
|
@@ -2529,8 +2990,12 @@ async function createKavach(config) {
|
|
|
2529
2990
|
const adminModule = config.admin ? createAdminModule(config.admin, db, sessionManager) : null;
|
|
2530
2991
|
const apiKeyManagerModule = config.apiKeys ? createApiKeyManagerModule(config.apiKeys, db) : null;
|
|
2531
2992
|
const usernameModule = config.username && sessionManager ? createUsernameAuthModule(config.username, db, sessionManager) : null;
|
|
2993
|
+
const oneTimeTokenModule = createOneTimeTokenModule({}, db);
|
|
2994
|
+
const passwordResetModule = config.passwordReset && sessionManager ? createPasswordResetModule(config.passwordReset, db, sessionManager, oneTimeTokenModule) : null;
|
|
2995
|
+
const emailVerificationModule = config.emailVerification ? createEmailVerificationModule(config.emailVerification, db, oneTimeTokenModule) : null;
|
|
2532
2996
|
const phoneModule = config.phone && sessionManager ? createPhoneAuthModule(config.phone, db, sessionManager) : null;
|
|
2533
2997
|
const captchaModule = config.captcha ? createCaptchaModule(config.captcha) : null;
|
|
2998
|
+
const redirectChain = createRedirectChain(config.redirects);
|
|
2534
2999
|
const webhookModule = config.webhooks && config.webhooks.length > 0 ? createWebhookModule(config.webhooks) : null;
|
|
2535
3000
|
const pluginRegistry = await initializePlugins(config.plugins ?? [], db, config);
|
|
2536
3001
|
const endpointCtx = {
|
|
@@ -2673,7 +3138,7 @@ async function createKavach(config) {
|
|
|
2673
3138
|
*/
|
|
2674
3139
|
async register(input) {
|
|
2675
3140
|
const now = /* @__PURE__ */ new Date();
|
|
2676
|
-
const id =
|
|
3141
|
+
const id = generateId();
|
|
2677
3142
|
await db.insert(mcpServers).values({
|
|
2678
3143
|
id,
|
|
2679
3144
|
name: input.name,
|
|
@@ -2967,6 +3432,65 @@ async function createKavach(config) {
|
|
|
2967
3432
|
* ```
|
|
2968
3433
|
*/
|
|
2969
3434
|
username: usernameModule,
|
|
3435
|
+
/**
|
|
3436
|
+
* Password reset (forgot password + reset password).
|
|
3437
|
+
*
|
|
3438
|
+
* Null when `passwordReset` config was not provided or `auth.session`
|
|
3439
|
+
* is not configured.
|
|
3440
|
+
*
|
|
3441
|
+
* @example
|
|
3442
|
+
* ```typescript
|
|
3443
|
+
* // In your route handler
|
|
3444
|
+
* const response = await kavach.passwordReset?.handleRequest(request);
|
|
3445
|
+
* if (response) return response;
|
|
3446
|
+
*
|
|
3447
|
+
* // Or programmatically
|
|
3448
|
+
* await kavach.passwordReset?.requestReset('alice@example.com');
|
|
3449
|
+
* await kavach.passwordReset?.resetPassword(token, 'new-password');
|
|
3450
|
+
* ```
|
|
3451
|
+
*/
|
|
3452
|
+
passwordReset: passwordResetModule,
|
|
3453
|
+
/**
|
|
3454
|
+
* Email address verification.
|
|
3455
|
+
*
|
|
3456
|
+
* Null when `emailVerification` config was not provided.
|
|
3457
|
+
*
|
|
3458
|
+
* @example
|
|
3459
|
+
* ```typescript
|
|
3460
|
+
* // Send a verification email after sign-up
|
|
3461
|
+
* await kavach.emailVerification?.sendVerification(userId, email);
|
|
3462
|
+
*
|
|
3463
|
+
* // Confirm from the link in the email
|
|
3464
|
+
* const result = await kavach.emailVerification?.verify(token);
|
|
3465
|
+
*
|
|
3466
|
+
* // Check status
|
|
3467
|
+
* const verified = await kavach.emailVerification?.isVerified(userId);
|
|
3468
|
+
* ```
|
|
3469
|
+
*/
|
|
3470
|
+
emailVerification: emailVerificationModule,
|
|
3471
|
+
/**
|
|
3472
|
+
* One-time tokens (email verify, password reset, invitations, custom).
|
|
3473
|
+
*
|
|
3474
|
+
* Always available. Used internally by password reset but exposed for
|
|
3475
|
+
* custom flows (email verification, invitation links, etc.).
|
|
3476
|
+
*/
|
|
3477
|
+
oneTimeTokens: oneTimeTokenModule,
|
|
3478
|
+
/**
|
|
3479
|
+
* Session freshness enforcement for sensitive operations.
|
|
3480
|
+
*
|
|
3481
|
+
* Use as middleware before password changes, passkey registration,
|
|
3482
|
+
* billing updates, or any action that requires a recently-authenticated
|
|
3483
|
+
* session rather than an auto-refreshed one.
|
|
3484
|
+
*
|
|
3485
|
+
* @example
|
|
3486
|
+
* ```typescript
|
|
3487
|
+
* const stale = kavach.sessionFreshness.guard(session);
|
|
3488
|
+
* if (stale) return stale; // 403 SESSION_NOT_FRESH
|
|
3489
|
+
* ```
|
|
3490
|
+
*/
|
|
3491
|
+
sessionFreshness: createSessionFreshnessModule(
|
|
3492
|
+
config.sessionFreshness
|
|
3493
|
+
),
|
|
2970
3494
|
/**
|
|
2971
3495
|
* Phone number (SMS OTP) authentication.
|
|
2972
3496
|
*
|
|
@@ -3003,6 +3527,27 @@ async function createKavach(config) {
|
|
|
3003
3527
|
* ```
|
|
3004
3528
|
*/
|
|
3005
3529
|
webhooks: webhookModule,
|
|
3530
|
+
/**
|
|
3531
|
+
* Redirect chain manager.
|
|
3532
|
+
*
|
|
3533
|
+
* Capture the user's original destination before auth redirects, push
|
|
3534
|
+
* intermediate steps (onboarding, email verification), and pop them
|
|
3535
|
+
* back in order. Cookie-based, works across page transitions and tabs.
|
|
3536
|
+
*
|
|
3537
|
+
* @example
|
|
3538
|
+
* ```typescript
|
|
3539
|
+
* // In auth middleware — save where the user was going
|
|
3540
|
+
* const setCookie = kavach.redirects.capture(request);
|
|
3541
|
+
* return new Response(null, { status: 302, headers: { Location: '/sign-in', 'Set-Cookie': setCookie } });
|
|
3542
|
+
*
|
|
3543
|
+
* // After sign-in — send user to their original destination
|
|
3544
|
+
* const { url, clearCookie } = kavach.redirects.pop(request);
|
|
3545
|
+
* const headers: Record<string, string> = { Location: url };
|
|
3546
|
+
* if (clearCookie) headers['Set-Cookie'] = clearCookie;
|
|
3547
|
+
* return new Response(null, { status: 302, headers });
|
|
3548
|
+
* ```
|
|
3549
|
+
*/
|
|
3550
|
+
redirects: redirectChain,
|
|
3006
3551
|
/**
|
|
3007
3552
|
* Plugin system.
|
|
3008
3553
|
*
|
|
@@ -3479,7 +4024,7 @@ function serializeCookieDeletion(name, options) {
|
|
|
3479
4024
|
expires: /* @__PURE__ */ new Date(0)
|
|
3480
4025
|
});
|
|
3481
4026
|
}
|
|
3482
|
-
function
|
|
4027
|
+
function parseCookies2(header) {
|
|
3483
4028
|
const result = {};
|
|
3484
4029
|
if (!header || !header.trim()) return result;
|
|
3485
4030
|
for (const pair of header.split(";")) {
|
|
@@ -3496,10 +4041,10 @@ function parseCookies(header) {
|
|
|
3496
4041
|
return result;
|
|
3497
4042
|
}
|
|
3498
4043
|
function getCookie(header, name) {
|
|
3499
|
-
return
|
|
4044
|
+
return parseCookies2(header)[name];
|
|
3500
4045
|
}
|
|
3501
4046
|
function parseCookiesFromRequest(request) {
|
|
3502
|
-
return
|
|
4047
|
+
return parseCookies2(request.headers.get("cookie") ?? "");
|
|
3503
4048
|
}
|
|
3504
4049
|
function capitalize(s) {
|
|
3505
4050
|
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
@@ -3793,15 +4338,15 @@ function buildSessionMetadata(request, extra) {
|
|
|
3793
4338
|
}
|
|
3794
4339
|
|
|
3795
4340
|
// src/webhooks/webhook.ts
|
|
3796
|
-
function
|
|
4341
|
+
function generateId2() {
|
|
3797
4342
|
const bytes = new Uint8Array(16);
|
|
3798
4343
|
crypto.getRandomValues(bytes);
|
|
3799
4344
|
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
3800
4345
|
}
|
|
3801
4346
|
async function signPayload2(secret, body) {
|
|
3802
|
-
const
|
|
3803
|
-
const keyData =
|
|
3804
|
-
const messageData =
|
|
4347
|
+
const encoder2 = new TextEncoder();
|
|
4348
|
+
const keyData = encoder2.encode(secret);
|
|
4349
|
+
const messageData = encoder2.encode(body);
|
|
3805
4350
|
const key = await crypto.subtle.importKey(
|
|
3806
4351
|
"raw",
|
|
3807
4352
|
keyData,
|
|
@@ -3838,7 +4383,7 @@ async function deliverWebhook(url, event, payload, deliveryId, timestamp, signat
|
|
|
3838
4383
|
}
|
|
3839
4384
|
}
|
|
3840
4385
|
async function dispatchWithRetry(url, event, payload, config) {
|
|
3841
|
-
const deliveryId =
|
|
4386
|
+
const deliveryId = generateId2();
|
|
3842
4387
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
3843
4388
|
const body = JSON.stringify(payload);
|
|
3844
4389
|
const signature = await signPayload2(config.secret, body);
|
|
@@ -3870,7 +4415,7 @@ function createWebhookModule2(config) {
|
|
|
3870
4415
|
const subscriptions = /* @__PURE__ */ new Map();
|
|
3871
4416
|
async function subscribe(url, events) {
|
|
3872
4417
|
const sub = {
|
|
3873
|
-
id:
|
|
4418
|
+
id: generateId2(),
|
|
3874
4419
|
url,
|
|
3875
4420
|
events,
|
|
3876
4421
|
active: true,
|
|
@@ -3898,7 +4443,7 @@ function createWebhookModule2(config) {
|
|
|
3898
4443
|
if (!sub) {
|
|
3899
4444
|
return { success: false, error: "Subscription not found" };
|
|
3900
4445
|
}
|
|
3901
|
-
const deliveryId =
|
|
4446
|
+
const deliveryId = generateId2();
|
|
3902
4447
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
3903
4448
|
const pingPayload = { event: "ping", subscriptionId, timestamp };
|
|
3904
4449
|
const body = JSON.stringify(pingPayload);
|
|
@@ -3928,6 +4473,6 @@ async function verifyWebhookSignature(secret, rawBody, signature) {
|
|
|
3928
4473
|
return diff === 0;
|
|
3929
4474
|
}
|
|
3930
4475
|
|
|
3931
|
-
export { MultiSessionLimitError, buildDidDocument, buildSessionMetadata, classifyViolation, createApprovalModule, createCookieSessionManager, createDatabase, createDatabaseSync, createDelegationModule, createDidModule, createEmailTemplates, createI18n, createKavach, createMultiSessionModule, createPluginRouter, createPolicyModule, createPresentation, createPrivilegeAnalyzer, createTables, createTenantModule, createTrustModule, createWebhookModule2 as createWebhookModule, de, en, es, fr, generateCsrfToken, generateDidKey, generateDidWeb, generateOpenAPISpec, getCookie, getDidWebUrl, initializePlugins, ja, parseCookies, parseCookiesFromRequest, resolveDidKey, resolveDidWeb, serializeCookie, serializeCookieDeletion, signPayload, validateCsrfToken, validateOrigin, verifyPayload, verifyPresentation, verifyWebhookSignature, zh };
|
|
4476
|
+
export { MultiSessionLimitError, buildDidDocument, buildSessionMetadata, classifyViolation, createApprovalModule, createCookieSessionManager, createDatabase, createDatabaseSync, createDelegationModule, createDidModule, createEmailTemplates, createI18n, createKavach, createMultiSessionModule, createPluginRouter, createPolicyModule, createPresentation, createPrivilegeAnalyzer, createRedirectChain, createSessionFreshnessModule, createTables, createTenantModule, createTrustModule, createWebhookModule2 as createWebhookModule, de, en, es, fr, generateCsrfToken, generateDidKey, generateDidWeb, generateOpenAPISpec, getCookie, getDidWebUrl, initializePlugins, ja, parseCookies2 as parseCookies, parseCookiesFromRequest, resolveDidKey, resolveDidWeb, serializeCookie, serializeCookieDeletion, signPayload, validateCsrfToken, validateOrigin, verifyPayload, verifyPresentation, verifyWebhookSignature, zh };
|
|
3932
4477
|
//# sourceMappingURL=index.js.map
|
|
3933
4478
|
//# sourceMappingURL=index.js.map
|