kavachos 0.0.6 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +170 -37
  2. package/dist/a2a/index.d.ts +2 -1
  3. package/dist/a2a/index.js +7 -2
  4. package/dist/a2a/index.js.map +1 -1
  5. package/dist/agent/index.d.ts +3 -2
  6. package/dist/agent/index.js +789 -4
  7. package/dist/agent/index.js.map +1 -1
  8. package/dist/audit/index.d.ts +2 -1
  9. package/dist/audit/index.js +635 -3
  10. package/dist/audit/index.js.map +1 -1
  11. package/dist/auth/index.d.ts +600 -3
  12. package/dist/auth/index.js +14668 -4
  13. package/dist/auth/index.js.map +1 -1
  14. package/dist/crypto/index.d.ts +55 -0
  15. package/dist/{chunk-QCRHJMDX.js → crypto/index.js} +2 -2
  16. package/dist/crypto/index.js.map +1 -0
  17. package/dist/index.d.ts +251 -58
  18. package/dist/index.js +16369 -233
  19. package/dist/index.js.map +1 -1
  20. package/dist/mcp/index.js +19 -2
  21. package/dist/mcp/index.js.map +1 -1
  22. package/dist/permission/index.d.ts +3 -2
  23. package/dist/permission/index.js +790 -4
  24. package/dist/permission/index.js.map +1 -1
  25. package/dist/redirect/index.d.ts +118 -0
  26. package/dist/redirect/index.js +292 -0
  27. package/dist/redirect/index.js.map +1 -0
  28. package/dist/{types-W8X0PXE7.d.ts → types-5Ua5KlPc.d.ts} +222 -124
  29. package/dist/vc/index.js +542 -3
  30. package/dist/vc/index.js.map +1 -1
  31. package/package.json +39 -22
  32. package/LICENSE +0 -21
  33. package/dist/chunk-FKVAXCNJ.js +0 -12516
  34. package/dist/chunk-FKVAXCNJ.js.map +0 -1
  35. package/dist/chunk-IKTOSJ4O.js +0 -214
  36. package/dist/chunk-IKTOSJ4O.js.map +0 -1
  37. package/dist/chunk-KDL6A76K.js +0 -569
  38. package/dist/chunk-KDL6A76K.js.map +0 -1
  39. package/dist/chunk-NSBPE2FW.js +0 -15
  40. package/dist/chunk-NSBPE2FW.js.map +0 -1
  41. package/dist/chunk-NSTER7KE.js +0 -538
  42. package/dist/chunk-NSTER7KE.js.map +0 -1
  43. package/dist/chunk-QCRHJMDX.js.map +0 -1
  44. package/dist/chunk-VHKZARMM.js +0 -251
  45. package/dist/chunk-VHKZARMM.js.map +0 -1
  46. package/dist/chunk-Y3OWAJHK.js +0 -101
  47. package/dist/chunk-Y3OWAJHK.js.map +0 -1
@@ -1,5 +1,637 @@
1
- export { createAuditModule } from '../chunk-Y3OWAJHK.js';
2
- import '../chunk-KDL6A76K.js';
3
- import '../chunk-NSBPE2FW.js';
1
+ import { eq, gte, lte, desc, and, lt } from 'drizzle-orm';
2
+ import { sqliteTable, integer, text } from 'drizzle-orm/sqlite-core';
3
+
4
+ // src/audit/audit.ts
5
+ var users = sqliteTable("kavach_users", {
6
+ id: text("id").primaryKey(),
7
+ email: text("email").notNull().unique(),
8
+ name: text("name"),
9
+ username: text("username").unique(),
10
+ externalId: text("external_id"),
11
+ // ID from external auth (better-auth, Auth.js, etc.)
12
+ externalProvider: text("external_provider"),
13
+ // "better-auth", "authjs", "clerk", etc.
14
+ metadata: text("metadata", { mode: "json" }).$type(),
15
+ // Admin ban fields (populated by admin module)
16
+ banned: integer("banned").notNull().default(0),
17
+ banReason: text("ban_reason"),
18
+ banExpiresAt: integer("ban_expires_at", { mode: "timestamp" }),
19
+ forcePasswordReset: integer("force_password_reset").notNull().default(0),
20
+ emailVerified: integer("email_verified").notNull().default(0),
21
+ // Stripe integration fields (populated by kavach-stripe plugin)
22
+ stripeCustomerId: text("stripe_customer_id").unique(),
23
+ stripeSubscriptionId: text("stripe_subscription_id"),
24
+ stripeSubscriptionStatus: text("stripe_subscription_status"),
25
+ stripePriceId: text("stripe_price_id"),
26
+ stripeCurrentPeriodEnd: integer("stripe_current_period_end", { mode: "timestamp" }),
27
+ stripeCancelAtPeriodEnd: integer("stripe_cancel_at_period_end", { mode: "boolean" }).notNull().default(false),
28
+ // Polar integration fields (populated by kavach-polar plugin)
29
+ polarCustomerId: text("polar_customer_id").unique(),
30
+ polarSubscriptionId: text("polar_subscription_id"),
31
+ polarSubscriptionStatus: text("polar_subscription_status"),
32
+ polarProductId: text("polar_product_id"),
33
+ polarCurrentPeriodEnd: integer("polar_current_period_end", { mode: "timestamp" }),
34
+ polarCancelAtPeriodEnd: integer("polar_cancel_at_period_end", { mode: "boolean" }).notNull().default(false),
35
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull(),
36
+ updatedAt: integer("updated_at", { mode: "timestamp" }).notNull()
37
+ });
38
+ var tenants = sqliteTable("kavach_tenants", {
39
+ id: text("id").primaryKey(),
40
+ name: text("name").notNull(),
41
+ slug: text("slug").notNull().unique(),
42
+ settings: text("settings", { mode: "json" }).$type(),
43
+ status: text("status", { enum: ["active", "suspended"] }).notNull().default("active"),
44
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull(),
45
+ updatedAt: integer("updated_at", { mode: "timestamp" }).notNull()
46
+ });
47
+ var agents = sqliteTable("kavach_agents", {
48
+ id: text("id").primaryKey(),
49
+ ownerId: text("owner_id").notNull().references(() => users.id),
50
+ tenantId: text("tenant_id").references(() => tenants.id),
51
+ // nullable, for multi-tenant scoping
52
+ name: text("name").notNull(),
53
+ type: text("type", { enum: ["autonomous", "delegated", "service"] }).notNull(),
54
+ status: text("status", { enum: ["active", "revoked", "expired"] }).notNull().default("active"),
55
+ tokenHash: text("token_hash").notNull(),
56
+ // hashed agent token
57
+ tokenPrefix: text("token_prefix").notNull(),
58
+ // first 8 chars for identification
59
+ expiresAt: integer("expires_at", { mode: "timestamp" }),
60
+ lastActiveAt: integer("last_active_at", { mode: "timestamp" }),
61
+ metadata: text("metadata", { mode: "json" }).$type(),
62
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull(),
63
+ updatedAt: integer("updated_at", { mode: "timestamp" }).notNull()
64
+ });
65
+ sqliteTable("kavach_permissions", {
66
+ id: text("id").primaryKey(),
67
+ agentId: text("agent_id").notNull().references(() => agents.id, { onDelete: "cascade" }),
68
+ resource: text("resource").notNull(),
69
+ // e.g. "mcp:github:*", "tool:file_read"
70
+ actions: text("actions", { mode: "json" }).notNull().$type(),
71
+ // ["read", "write", "execute"]
72
+ constraints: text("constraints", { mode: "json" }).$type(),
73
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull()
74
+ });
75
+ sqliteTable("kavach_delegation_chains", {
76
+ id: text("id").primaryKey(),
77
+ fromAgentId: text("from_agent_id").notNull().references(() => agents.id),
78
+ toAgentId: text("to_agent_id").notNull().references(() => agents.id),
79
+ permissions: text("permissions", { mode: "json" }).notNull().$type(),
80
+ depth: integer("depth").notNull().default(1),
81
+ maxDepth: integer("max_depth").notNull().default(3),
82
+ status: text("status", { enum: ["active", "revoked", "expired"] }).notNull().default("active"),
83
+ expiresAt: integer("expires_at", { mode: "timestamp" }).notNull(),
84
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull()
85
+ });
86
+ var auditLogs = sqliteTable("kavach_audit_logs", {
87
+ id: text("id").primaryKey(),
88
+ agentId: text("agent_id").notNull().references(() => agents.id),
89
+ userId: text("user_id").notNull().references(() => users.id),
90
+ action: text("action").notNull(),
91
+ // "execute", "read", "write", "delete"
92
+ resource: text("resource").notNull(),
93
+ // "mcp:github:create_issue"
94
+ parameters: text("parameters", { mode: "json" }).$type(),
95
+ result: text("result", { enum: ["allowed", "denied", "rate_limited"] }).notNull(),
96
+ reason: text("reason"),
97
+ // why denied/rate_limited
98
+ durationMs: integer("duration_ms").notNull(),
99
+ tokensCost: integer("tokens_cost"),
100
+ ip: text("ip"),
101
+ userAgent: text("user_agent"),
102
+ timestamp: integer("timestamp", { mode: "timestamp" }).notNull()
103
+ });
104
+ sqliteTable("kavach_rate_limits", {
105
+ id: text("id").primaryKey(),
106
+ agentId: text("agent_id").notNull().references(() => agents.id, { onDelete: "cascade" }),
107
+ resource: text("resource").notNull(),
108
+ windowStart: integer("window_start", { mode: "timestamp" }).notNull(),
109
+ count: integer("count").notNull().default(0)
110
+ });
111
+ sqliteTable("kavach_mcp_servers", {
112
+ id: text("id").primaryKey(),
113
+ name: text("name").notNull(),
114
+ endpoint: text("endpoint").notNull().unique(),
115
+ tools: text("tools", { mode: "json" }).notNull().$type(),
116
+ authRequired: integer("auth_required", { mode: "boolean" }).notNull().default(true),
117
+ rateLimitRpm: integer("rate_limit_rpm"),
118
+ status: text("status", { enum: ["active", "inactive"] }).notNull().default("active"),
119
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull(),
120
+ updatedAt: integer("updated_at", { mode: "timestamp" }).notNull()
121
+ });
122
+ sqliteTable("kavach_sessions", {
123
+ id: text("id").primaryKey(),
124
+ userId: text("user_id").notNull().references(() => users.id),
125
+ expiresAt: integer("expires_at", { mode: "timestamp" }).notNull(),
126
+ metadata: text("metadata", { mode: "json" }).$type(),
127
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull()
128
+ });
129
+ var oauthClients = sqliteTable("kavach_oauth_clients", {
130
+ id: text("id").primaryKey(),
131
+ clientId: text("client_id").notNull().unique(),
132
+ clientSecret: text("client_secret"),
133
+ // null for public clients
134
+ clientName: text("client_name"),
135
+ clientUri: text("client_uri"),
136
+ redirectUris: text("redirect_uris", { mode: "json" }).notNull().$type(),
137
+ grantTypes: text("grant_types", { mode: "json" }).notNull().$type().default(["authorization_code"]),
138
+ responseTypes: text("response_types", { mode: "json" }).notNull().$type().default(["code"]),
139
+ tokenEndpointAuthMethod: text("token_endpoint_auth_method").notNull().default("client_secret_basic"),
140
+ type: text("type", { enum: ["public", "confidential"] }).notNull().default("confidential"),
141
+ disabled: integer("disabled", { mode: "boolean" }).notNull().default(false),
142
+ metadata: text("metadata", { mode: "json" }).$type(),
143
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull(),
144
+ updatedAt: integer("updated_at", { mode: "timestamp" }).notNull()
145
+ });
146
+ sqliteTable("kavach_oauth_access_tokens", {
147
+ id: text("id").primaryKey(),
148
+ accessToken: text("access_token").notNull().unique(),
149
+ refreshToken: text("refresh_token").unique(),
150
+ clientId: text("client_id").notNull().references(() => oauthClients.clientId),
151
+ userId: text("user_id").notNull().references(() => users.id),
152
+ scopes: text("scopes").notNull(),
153
+ // space-separated
154
+ resource: text("resource"),
155
+ // RFC 8707 - audience binding
156
+ accessTokenExpiresAt: integer("access_token_expires_at", { mode: "timestamp" }).notNull(),
157
+ refreshTokenExpiresAt: integer("refresh_token_expires_at", { mode: "timestamp" }),
158
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull()
159
+ });
160
+ sqliteTable("kavach_oauth_authorization_codes", {
161
+ id: text("id").primaryKey(),
162
+ code: text("code").notNull().unique(),
163
+ clientId: text("client_id").notNull().references(() => oauthClients.clientId),
164
+ userId: text("user_id").notNull().references(() => users.id),
165
+ redirectUri: text("redirect_uri").notNull(),
166
+ scopes: text("scopes").notNull(),
167
+ codeChallenge: text("code_challenge"),
168
+ // PKCE
169
+ codeChallengeMethod: text("code_challenge_method"),
170
+ // "S256"
171
+ resource: text("resource"),
172
+ // RFC 8707
173
+ expiresAt: integer("expires_at", { mode: "timestamp" }).notNull(),
174
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull()
175
+ });
176
+ sqliteTable("kavach_budget_policies", {
177
+ id: text("id").primaryKey(),
178
+ agentId: text("agent_id").references(() => agents.id, { onDelete: "cascade" }),
179
+ // nullable
180
+ userId: text("user_id").references(() => users.id),
181
+ // nullable
182
+ tenantId: text("tenant_id").references(() => tenants.id),
183
+ // nullable
184
+ limits: text("limits", { mode: "json" }).notNull().$type(),
185
+ currentUsage: text("current_usage", { mode: "json" }).notNull().$type(),
186
+ action: text("action", { enum: ["warn", "throttle", "block", "revoke"] }).notNull().default("warn"),
187
+ status: text("status", { enum: ["active", "triggered", "disabled"] }).notNull().default("active"),
188
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull()
189
+ });
190
+ sqliteTable("kavach_agent_cards", {
191
+ id: text("id").primaryKey(),
192
+ agentId: text("agent_id").notNull().references(() => agents.id, { onDelete: "cascade" }),
193
+ name: text("name").notNull(),
194
+ description: text("description"),
195
+ version: text("version").notNull(),
196
+ protocols: text("protocols", { mode: "json" }).notNull().$type(),
197
+ capabilities: text("capabilities", { mode: "json" }).notNull().$type(),
198
+ authRequirements: text("auth_requirements", { mode: "json" }).notNull().$type(),
199
+ endpoint: text("endpoint"),
200
+ metadata: text("metadata", { mode: "json" }).$type(),
201
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull(),
202
+ updatedAt: integer("updated_at", { mode: "timestamp" }).notNull()
203
+ });
204
+ sqliteTable("kavach_approval_requests", {
205
+ id: text("id").primaryKey(),
206
+ agentId: text("agent_id").notNull().references(() => agents.id, { onDelete: "cascade" }),
207
+ userId: text("user_id").notNull().references(() => users.id),
208
+ action: text("action").notNull(),
209
+ resource: text("resource").notNull(),
210
+ arguments: text("arguments", { mode: "json" }).$type(),
211
+ status: text("status", { enum: ["pending", "approved", "denied", "expired"] }).notNull().default("pending"),
212
+ expiresAt: integer("expires_at", { mode: "timestamp" }).notNull(),
213
+ respondedAt: integer("responded_at", { mode: "timestamp" }),
214
+ respondedBy: text("responded_by"),
215
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull()
216
+ });
217
+ sqliteTable("kavach_trust_scores", {
218
+ agentId: text("agent_id").primaryKey().references(() => agents.id, { onDelete: "cascade" }),
219
+ score: integer("score").notNull(),
220
+ level: text("level", {
221
+ enum: ["untrusted", "limited", "standard", "trusted", "elevated"]
222
+ }).notNull(),
223
+ factors: text("factors", { mode: "json" }).notNull().$type(),
224
+ computedAt: integer("computed_at", { mode: "timestamp" }).notNull()
225
+ });
226
+ sqliteTable("kavach_magic_links", {
227
+ id: text("id").primaryKey(),
228
+ email: text("email").notNull(),
229
+ token: text("token").notNull().unique(),
230
+ expiresAt: integer("expires_at", { mode: "timestamp" }).notNull(),
231
+ used: integer("used", { mode: "boolean" }).notNull().default(false),
232
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull()
233
+ });
234
+ sqliteTable("kavach_email_otps", {
235
+ id: text("id").primaryKey(),
236
+ email: text("email").notNull(),
237
+ codeHash: text("code_hash").notNull(),
238
+ expiresAt: integer("expires_at", { mode: "timestamp" }).notNull(),
239
+ attempts: integer("attempts").notNull().default(0),
240
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull()
241
+ });
242
+ sqliteTable("kavach_totp", {
243
+ userId: text("user_id").primaryKey().references(() => users.id),
244
+ secret: text("secret").notNull(),
245
+ // base32-encoded TOTP secret
246
+ enabled: integer("enabled", { mode: "boolean" }).notNull().default(false),
247
+ backupCodes: text("backup_codes", { mode: "json" }).notNull().$type(),
248
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull(),
249
+ updatedAt: integer("updated_at", { mode: "timestamp" }).notNull()
250
+ });
251
+ var organizations = sqliteTable("kavach_organizations", {
252
+ id: text("id").primaryKey(),
253
+ name: text("name").notNull(),
254
+ slug: text("slug").notNull().unique(),
255
+ ownerId: text("owner_id").notNull().references(() => users.id),
256
+ metadata: text("metadata", { mode: "json" }).$type(),
257
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull(),
258
+ updatedAt: integer("updated_at", { mode: "timestamp" }).notNull()
259
+ });
260
+ sqliteTable("kavach_org_members", {
261
+ id: text("id").primaryKey(),
262
+ orgId: text("org_id").notNull().references(() => organizations.id, { onDelete: "cascade" }),
263
+ userId: text("user_id").notNull().references(() => users.id),
264
+ role: text("role").notNull().default("member"),
265
+ joinedAt: integer("joined_at", { mode: "timestamp" }).notNull()
266
+ });
267
+ sqliteTable("kavach_org_invitations", {
268
+ id: text("id").primaryKey(),
269
+ orgId: text("org_id").notNull().references(() => organizations.id, { onDelete: "cascade" }),
270
+ email: text("email").notNull(),
271
+ role: text("role").notNull().default("member"),
272
+ invitedBy: text("invited_by").notNull().references(() => users.id),
273
+ status: text("status", { enum: ["pending", "accepted", "expired"] }).notNull().default("pending"),
274
+ expiresAt: integer("expires_at", { mode: "timestamp" }).notNull(),
275
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull()
276
+ });
277
+ sqliteTable("kavach_org_roles", {
278
+ id: text("id").primaryKey(),
279
+ orgId: text("org_id").notNull().references(() => organizations.id, { onDelete: "cascade" }),
280
+ name: text("name").notNull(),
281
+ permissions: text("permissions", { mode: "json" }).notNull().$type()
282
+ });
283
+ sqliteTable("kavach_passkey_credentials", {
284
+ id: text("id").primaryKey(),
285
+ userId: text("user_id").notNull().references(() => users.id),
286
+ credentialId: text("credential_id").notNull().unique(),
287
+ publicKey: text("public_key").notNull(),
288
+ // base64url-encoded COSE key
289
+ counter: integer("counter").notNull().default(0),
290
+ deviceName: text("device_name"),
291
+ transports: text("transports"),
292
+ // JSON array, e.g. '["internal","usb"]'
293
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull(),
294
+ lastUsedAt: integer("last_used_at", { mode: "timestamp" }).notNull()
295
+ });
296
+ sqliteTable("kavach_sso_connections", {
297
+ id: text("id").primaryKey(),
298
+ orgId: text("org_id").notNull(),
299
+ providerId: text("provider_id").notNull(),
300
+ type: text("type", { enum: ["saml", "oidc"] }).notNull(),
301
+ domain: text("domain").notNull().unique(),
302
+ enabled: integer("enabled").notNull().default(1),
303
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull()
304
+ });
305
+ sqliteTable("kavach_api_keys", {
306
+ id: text("id").primaryKey(),
307
+ userId: text("user_id").notNull().references(() => users.id),
308
+ name: text("name").notNull(),
309
+ keyHash: text("key_hash").notNull(),
310
+ keyPrefix: text("key_prefix").notNull(),
311
+ permissions: text("permissions", { mode: "json" }).notNull().$type(),
312
+ expiresAt: integer("expires_at", { mode: "timestamp" }),
313
+ lastUsedAt: integer("last_used_at", { mode: "timestamp" }),
314
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull()
315
+ });
316
+ sqliteTable("kavach_passkey_challenges", {
317
+ id: text("id").primaryKey(),
318
+ challenge: text("challenge").notNull().unique(),
319
+ userId: text("user_id"),
320
+ // null for discoverable credential flows
321
+ type: text("type", { enum: ["registration", "authentication"] }).notNull(),
322
+ expiresAt: integer("expires_at", { mode: "timestamp" }).notNull(),
323
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull()
324
+ });
325
+ sqliteTable("kavach_username_accounts", {
326
+ id: text("id").primaryKey(),
327
+ userId: text("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
328
+ username: text("username").notNull().unique(),
329
+ passwordHash: text("password_hash").notNull(),
330
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull(),
331
+ updatedAt: integer("updated_at", { mode: "timestamp" }).notNull()
332
+ });
333
+ sqliteTable("kavach_phone_verifications", {
334
+ id: text("id").primaryKey(),
335
+ phoneNumber: text("phone_number").notNull(),
336
+ codeHash: text("code_hash").notNull(),
337
+ attempts: integer("attempts").notNull().default(0),
338
+ expiresAt: integer("expires_at", { mode: "timestamp" }).notNull(),
339
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull()
340
+ });
341
+ sqliteTable("kavach_trusted_devices", {
342
+ id: text("id").primaryKey(),
343
+ userId: text("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
344
+ fingerprint: text("fingerprint").notNull(),
345
+ // HMAC-SHA256 of stable request headers
346
+ label: text("label").notNull(),
347
+ // human-readable, e.g. "Mac", "iPhone"
348
+ trustedAt: integer("trusted_at", { mode: "timestamp" }).notNull(),
349
+ expiresAt: integer("expires_at", { mode: "timestamp" }).notNull()
350
+ });
351
+ sqliteTable("kavach_one_time_tokens", {
352
+ id: text("id").primaryKey(),
353
+ tokenHash: text("token_hash").notNull().unique(),
354
+ // SHA-256 hex of the raw token
355
+ purpose: text("purpose", {
356
+ enum: ["email-verify", "password-reset", "invitation", "custom"]
357
+ }).notNull(),
358
+ identifier: text("identifier").notNull(),
359
+ // email, userId, or any caller-supplied key
360
+ metadata: text("metadata", { mode: "json" }).$type(),
361
+ used: integer("used", { mode: "boolean" }).notNull().default(false),
362
+ expiresAt: integer("expires_at", { mode: "timestamp" }).notNull(),
363
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull()
364
+ });
365
+ sqliteTable("kavach_login_history", {
366
+ id: text("id").primaryKey(),
367
+ userId: text("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
368
+ method: text("method").notNull(),
369
+ // LoginMethod — kept as text to support oauth:{provider} variants
370
+ ip: text("ip"),
371
+ userAgent: text("user_agent"),
372
+ timestamp: integer("timestamp", { mode: "timestamp_ms" }).notNull()
373
+ });
374
+ sqliteTable("kavach_agent_dids", {
375
+ agentId: text("agent_id").primaryKey().references(() => agents.id, { onDelete: "cascade" }),
376
+ did: text("did").notNull().unique(),
377
+ method: text("method", { enum: ["key", "web"] }).notNull(),
378
+ publicKeyJwk: text("public_key_jwk").notNull(),
379
+ // JSON-serialised JWK (public key only)
380
+ didDocument: text("did_document").notNull(),
381
+ // JSON-serialised DID Document
382
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull()
383
+ });
384
+ sqliteTable("kavach_oidc_clients", {
385
+ id: text("id").primaryKey(),
386
+ clientId: text("client_id").notNull().unique(),
387
+ clientSecretHash: text("client_secret_hash").notNull(),
388
+ // SHA-256 hex of the raw secret
389
+ clientName: text("client_name").notNull(),
390
+ redirectUris: text("redirect_uris", { mode: "json" }).notNull().$type(),
391
+ grantTypes: text("grant_types", { mode: "json" }).notNull().$type(),
392
+ responseTypes: text("response_types", { mode: "json" }).notNull().$type(),
393
+ scopes: text("scopes", { mode: "json" }).notNull().$type(),
394
+ tokenEndpointAuthMethod: text("token_endpoint_auth_method").notNull().default("client_secret_post"),
395
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull(),
396
+ updatedAt: integer("updated_at", { mode: "timestamp" }).notNull()
397
+ });
398
+ sqliteTable("kavach_oidc_auth_codes", {
399
+ id: text("id").primaryKey(),
400
+ codeHash: text("code_hash").notNull().unique(),
401
+ // SHA-256 hex of the raw code
402
+ clientId: text("client_id").notNull(),
403
+ userId: text("user_id").notNull(),
404
+ redirectUri: text("redirect_uri").notNull(),
405
+ scopes: text("scopes").notNull(),
406
+ // space-separated
407
+ nonce: text("nonce"),
408
+ codeChallenge: text("code_challenge"),
409
+ // PKCE S256
410
+ codeChallengeMethod: text("code_challenge_method"),
411
+ used: integer("used", { mode: "boolean" }).notNull().default(false),
412
+ expiresAt: integer("expires_at", { mode: "timestamp" }).notNull(),
413
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull()
414
+ });
415
+ sqliteTable("kavach_oidc_refresh_tokens", {
416
+ id: text("id").primaryKey(),
417
+ tokenHash: text("token_hash").notNull().unique(),
418
+ // SHA-256 hex of the raw token
419
+ clientId: text("client_id").notNull(),
420
+ userId: text("user_id").notNull(),
421
+ scopes: text("scopes").notNull(),
422
+ // space-separated
423
+ revoked: integer("revoked", { mode: "boolean" }).notNull().default(false),
424
+ expiresAt: integer("expires_at", { mode: "timestamp" }).notNull(),
425
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull()
426
+ });
427
+ sqliteTable("kavach_cost_events", {
428
+ id: text("id").primaryKey(),
429
+ agentId: text("agent_id").notNull().references(() => agents.id, { onDelete: "cascade" }),
430
+ tool: text("tool").notNull(),
431
+ // e.g. 'openai:gpt-4o', 'anthropic:claude-3-5-sonnet', 'mcp:github'
432
+ inputTokens: integer("input_tokens"),
433
+ outputTokens: integer("output_tokens"),
434
+ /** Cost stored as integer microdollars (costUsd × 1_000_000) to avoid float drift */
435
+ costMicros: integer("cost_micros").notNull(),
436
+ currency: text("currency").notNull().default("USD"),
437
+ metadata: text("metadata", { mode: "json" }).$type(),
438
+ delegationChainId: text("delegation_chain_id"),
439
+ // null when not part of a chain
440
+ recordedAt: integer("recorded_at", { mode: "timestamp" }).notNull()
441
+ });
442
+ sqliteTable("kavach_ephemeral_sessions", {
443
+ id: text("id").primaryKey(),
444
+ agentId: text("agent_id").notNull().references(() => agents.id, { onDelete: "cascade" }),
445
+ ownerId: text("owner_id").notNull().references(() => users.id),
446
+ tokenHash: text("token_hash").notNull().unique(),
447
+ expiresAt: integer("expires_at", { mode: "timestamp" }).notNull(),
448
+ maxActions: integer("max_actions"),
449
+ // null = unlimited
450
+ actionsUsed: integer("actions_used").notNull().default(0),
451
+ status: text("status", { enum: ["active", "expired", "exhausted", "revoked"] }).notNull().default("active"),
452
+ auditGroupId: text("audit_group_id").notNull(),
453
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull(),
454
+ updatedAt: integer("updated_at", { mode: "timestamp" }).notNull()
455
+ });
456
+ sqliteTable("kavach_stream_events", {
457
+ id: text("id").primaryKey(),
458
+ type: text("type").notNull(),
459
+ timestamp: integer("timestamp", { mode: "timestamp" }).notNull(),
460
+ data: text("data", { mode: "json" }).notNull().$type(),
461
+ agentId: text("agent_id"),
462
+ userId: text("user_id")
463
+ });
464
+ sqliteTable("kavach_jwt_refresh_tokens", {
465
+ id: text("id").primaryKey(),
466
+ /** SHA-256 hex of the raw refresh token. The raw token is never stored. */
467
+ tokenHash: text("token_hash").notNull().unique(),
468
+ /** The user who owns this session. */
469
+ userId: text("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
470
+ /** True once the token has been used in a refresh or explicit revocation. */
471
+ used: integer("used", { mode: "boolean" }).notNull().default(false),
472
+ expiresAt: integer("expires_at", { mode: "timestamp" }).notNull(),
473
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull()
474
+ });
475
+ sqliteTable("kavach_rebac_resources", {
476
+ id: text("id").notNull().primaryKey(),
477
+ type: text("type").notNull(),
478
+ // 'org', 'workspace', 'project', 'document', etc.
479
+ parentId: text("parent_id"),
480
+ parentType: text("parent_type"),
481
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull()
482
+ });
483
+ sqliteTable("kavach_rebac_relationships", {
484
+ id: text("id").primaryKey(),
485
+ subjectType: text("subject_type").notNull(),
486
+ // 'user', 'agent', 'team', 'role'
487
+ subjectId: text("subject_id").notNull(),
488
+ relation: text("relation").notNull(),
489
+ // 'owner', 'editor', 'viewer', 'member', 'parent'
490
+ objectType: text("object_type").notNull(),
491
+ objectId: text("object_id").notNull(),
492
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull()
493
+ });
494
+ sqliteTable("kavach_federation_instances", {
495
+ id: text("id").primaryKey(),
496
+ instanceId: text("instance_id").notNull().unique(),
497
+ instanceUrl: text("instance_url").notNull(),
498
+ publicKeyJwk: text("public_key_jwk"),
499
+ // JSON-serialised JWK (public key only)
500
+ trustLevel: text("trust_level", { enum: ["full", "limited", "verify-only"] }).notNull().default("verify-only"),
501
+ discoveredAt: integer("discovered_at", { mode: "timestamp" }),
502
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull(),
503
+ updatedAt: integer("updated_at", { mode: "timestamp" }).notNull()
504
+ });
505
+ sqliteTable("kavach_federation_tokens", {
506
+ id: text("id").primaryKey(),
507
+ tokenJti: text("token_jti").notNull().unique(),
508
+ // JWT ID for dedup
509
+ agentId: text("agent_id").notNull(),
510
+ sourceInstanceId: text("source_instance_id").notNull(),
511
+ targetInstanceId: text("target_instance_id"),
512
+ direction: text("direction", { enum: ["issued", "received"] }).notNull(),
513
+ permissions: text("permissions", { mode: "json" }).notNull().$type(),
514
+ trustScore: integer("trust_score"),
515
+ // stored as integer 0-100
516
+ expiresAt: integer("expires_at", { mode: "timestamp" }).notNull(),
517
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull()
518
+ });
519
+ var refreshTokenFamilies = sqliteTable("kavach_refresh_token_families", {
520
+ id: text("id").primaryKey(),
521
+ userId: text("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
522
+ /** Absolute session expiry — no rotation can extend beyond this date. */
523
+ absoluteExpiresAt: integer("absolute_expires_at", { mode: "timestamp" }).notNull(),
524
+ /** 0 = active, 1 = revoked (reuse detection or explicit logout). */
525
+ revoked: integer("revoked").notNull().default(0),
526
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull()
527
+ });
528
+ sqliteTable("kavach_refresh_tokens", {
529
+ id: text("id").primaryKey(),
530
+ familyId: text("family_id").notNull().references(() => refreshTokenFamilies.id, { onDelete: "cascade" }),
531
+ /** SHA-256 hash of the opaque token — never store the raw token. */
532
+ tokenHash: text("token_hash").notNull().unique(),
533
+ /** 0 = unused, 1 = already consumed (one-time use). */
534
+ used: integer("used").notNull().default(0),
535
+ expiresAt: integer("expires_at", { mode: "timestamp" }).notNull(),
536
+ createdAt: integer("created_at", { mode: "timestamp" }).notNull()
537
+ });
538
+
539
+ // src/audit/audit.ts
540
+ function createAuditModule(config) {
541
+ const { db } = config;
542
+ async function query(filter) {
543
+ const conditions = [];
544
+ if (filter.agentId) conditions.push(eq(auditLogs.agentId, filter.agentId));
545
+ if (filter.userId) conditions.push(eq(auditLogs.userId, filter.userId));
546
+ if (filter.since) conditions.push(gte(auditLogs.timestamp, filter.since));
547
+ if (filter.until) conditions.push(lte(auditLogs.timestamp, filter.until));
548
+ if (filter.result) conditions.push(eq(auditLogs.result, filter.result));
549
+ let q = db.select().from(auditLogs).orderBy(desc(auditLogs.timestamp)).$dynamic();
550
+ if (conditions.length > 0) {
551
+ q = q.where(and(...conditions));
552
+ }
553
+ if (filter.limit) {
554
+ q = q.limit(filter.limit);
555
+ }
556
+ if (filter.offset) {
557
+ q = q.offset(filter.offset);
558
+ }
559
+ const rows = await q;
560
+ return rows.filter((row) => {
561
+ if (filter.actions && filter.actions.length > 0) {
562
+ return filter.actions.includes(row.action);
563
+ }
564
+ return true;
565
+ }).map(toAuditEntry);
566
+ }
567
+ async function exportLogs(options) {
568
+ const entries = await query({
569
+ since: options.since,
570
+ until: options.until,
571
+ limit: 1e4
572
+ // cap exports
573
+ });
574
+ if (options.format === "json") {
575
+ return JSON.stringify(entries, null, 2);
576
+ }
577
+ const headers = [
578
+ "id",
579
+ "agentId",
580
+ "userId",
581
+ "action",
582
+ "resource",
583
+ "result",
584
+ "reason",
585
+ "durationMs",
586
+ "tokensCost",
587
+ "timestamp"
588
+ ];
589
+ const csvRows = [headers.join(",")];
590
+ for (const entry of entries) {
591
+ csvRows.push(
592
+ [
593
+ entry.id,
594
+ entry.agentId,
595
+ entry.userId,
596
+ entry.action,
597
+ entry.resource,
598
+ entry.result,
599
+ `"${entry.reason ?? ""}"`,
600
+ entry.durationMs,
601
+ entry.tokensCost ?? "",
602
+ entry.timestamp.toISOString()
603
+ ].join(",")
604
+ );
605
+ }
606
+ return csvRows.join("\n");
607
+ }
608
+ async function cleanup(options) {
609
+ const cutoff = new Date(Date.now() - options.retentionDays * 24 * 60 * 60 * 1e3);
610
+ const toDelete = await db.select({ id: auditLogs.id }).from(auditLogs).where(lt(auditLogs.timestamp, cutoff));
611
+ if (toDelete.length === 0) {
612
+ return { deleted: 0 };
613
+ }
614
+ await db.delete(auditLogs).where(lt(auditLogs.timestamp, cutoff));
615
+ return { deleted: toDelete.length };
616
+ }
617
+ return { query, export: exportLogs, cleanup };
618
+ }
619
+ function toAuditEntry(row) {
620
+ return {
621
+ id: row.id,
622
+ agentId: row.agentId,
623
+ userId: row.userId,
624
+ action: row.action,
625
+ resource: row.resource,
626
+ parameters: row.parameters ?? {},
627
+ result: row.result,
628
+ reason: row.reason ?? void 0,
629
+ durationMs: row.durationMs,
630
+ tokensCost: row.tokensCost ?? void 0,
631
+ timestamp: row.timestamp
632
+ };
633
+ }
634
+
635
+ export { createAuditModule };
4
636
  //# sourceMappingURL=index.js.map
5
637
  //# sourceMappingURL=index.js.map