kavachos 0.2.0 → 0.3.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/dist/index.js CHANGED
@@ -1912,8 +1912,16 @@ function getCookie(request, name) {
1912
1912
  const match = header.match(new RegExp(`(?:^|;\\s*)${name}=([^;]*)`));
1913
1913
  return match?.[1] ? decodeURIComponent(match[1]) : null;
1914
1914
  }
1915
- function buildSetCookie(name, value, maxAge, path = "/") {
1916
- return `${name}=${encodeURIComponent(value)}; HttpOnly; Secure; SameSite=Lax; Path=${path}; Max-Age=${maxAge}`;
1915
+ function buildSetCookie(name, value, maxAge, path = "/", secure = true) {
1916
+ const parts = [
1917
+ `${name}=${encodeURIComponent(value)}`,
1918
+ "HttpOnly",
1919
+ "SameSite=Lax",
1920
+ `Path=${path}`,
1921
+ `Max-Age=${maxAge}`
1922
+ ];
1923
+ if (secure) parts.splice(1, 0, "Secure");
1924
+ return parts.join("; ");
1917
1925
  }
1918
1926
  function buildClearCookie(name, path = "/") {
1919
1927
  return `${name}=; HttpOnly; Secure; SameSite=Lax; Path=${path}; Max-Age=0`;
@@ -5764,7 +5772,8 @@ function oauth(config) {
5764
5772
  if (userId !== "__pending__") {
5765
5773
  const { session, token } = await sessionManager.create(userId);
5766
5774
  const maxAge = Math.floor((session.expiresAt.getTime() - Date.now()) / 1e3);
5767
- const cookie = buildSetCookie("kavach_session", token, maxAge);
5775
+ const isSecure = baseUrl.startsWith("https://");
5776
+ const cookie = buildSetCookie("kavach_session", token, maxAge, "/", isSecure);
5768
5777
  const userInfo = encodeURIComponent(JSON.stringify({ id: userId, email }));
5769
5778
  const callbackUrl = `${baseUrl}/?auth_user=${userInfo}`;
5770
5779
  return new Response(null, {
@@ -6068,13 +6077,14 @@ function createGithubProvider(config) {
6068
6077
  });
6069
6078
  return `${AUTHORIZATION_URL3}?${params.toString()}`;
6070
6079
  }
6071
- async function exchangeCode(code2, _codeVerifier, redirectUri) {
6080
+ async function exchangeCode(code2, codeVerifier, redirectUri) {
6072
6081
  const effectiveRedirectUri = config.redirectUri ?? redirectUri;
6073
6082
  const body = new URLSearchParams({
6074
6083
  client_id: config.clientId,
6075
6084
  client_secret: config.clientSecret,
6076
6085
  code: code2,
6077
- redirect_uri: effectiveRedirectUri
6086
+ redirect_uri: effectiveRedirectUri,
6087
+ code_verifier: codeVerifier
6078
6088
  });
6079
6089
  const response = await fetch(TOKEN_URL3, {
6080
6090
  method: "POST",
@@ -6370,14 +6380,15 @@ function createLinkedInProvider(config) {
6370
6380
  });
6371
6381
  return `${AUTHORIZATION_URL6}?${params.toString()}`;
6372
6382
  }
6373
- async function exchangeCode(code2, _codeVerifier, redirectUri) {
6383
+ async function exchangeCode(code2, codeVerifier, redirectUri) {
6374
6384
  const effectiveRedirectUri = config.redirectUri ?? redirectUri;
6375
6385
  const body = new URLSearchParams({
6376
6386
  grant_type: "authorization_code",
6377
6387
  client_id: config.clientId,
6378
6388
  client_secret: config.clientSecret,
6379
6389
  code: code2,
6380
- redirect_uri: effectiveRedirectUri
6390
+ redirect_uri: effectiveRedirectUri,
6391
+ code_verifier: codeVerifier
6381
6392
  });
6382
6393
  const response = await fetch(TOKEN_URL6, {
6383
6394
  method: "POST",
@@ -6561,14 +6572,15 @@ function createSlackProvider(config) {
6561
6572
  });
6562
6573
  return `${AUTHORIZATION_URL8}?${params.toString()}`;
6563
6574
  }
6564
- async function exchangeCode(code2, _codeVerifier, redirectUri) {
6575
+ async function exchangeCode(code2, codeVerifier, redirectUri) {
6565
6576
  const effectiveRedirectUri = config.redirectUri ?? redirectUri;
6566
6577
  const body = new URLSearchParams({
6567
6578
  grant_type: "authorization_code",
6568
6579
  client_id: config.clientId,
6569
6580
  client_secret: config.clientSecret,
6570
6581
  code: code2,
6571
- redirect_uri: effectiveRedirectUri
6582
+ redirect_uri: effectiveRedirectUri,
6583
+ code_verifier: codeVerifier
6572
6584
  });
6573
6585
  const response = await fetch(TOKEN_URL8, {
6574
6586
  method: "POST",
@@ -10680,7 +10692,13 @@ function passkey(config) {
10680
10692
  status: 200,
10681
10693
  headers: {
10682
10694
  "Content-Type": "application/json",
10683
- "Set-Cookie": buildSetCookie("kavach_session", token, maxAge)
10695
+ "Set-Cookie": buildSetCookie(
10696
+ "kavach_session",
10697
+ token,
10698
+ maxAge,
10699
+ "/",
10700
+ (ctx.config.baseUrl ?? "").startsWith("https://")
10701
+ )
10684
10702
  }
10685
10703
  }
10686
10704
  );
@@ -15412,6 +15430,70 @@ function createDatabaseSync(config) {
15412
15430
  }
15413
15431
 
15414
15432
  // src/db/migrations.ts
15433
+ var ALL_FEATURES_ENABLED = {
15434
+ core: true,
15435
+ session: true,
15436
+ agent: true,
15437
+ audit: true,
15438
+ oauth: true,
15439
+ tenant: true,
15440
+ mcp: true,
15441
+ org: true,
15442
+ rateLimit: true,
15443
+ budget: true,
15444
+ magicLink: true,
15445
+ emailOtp: true,
15446
+ totp: true,
15447
+ passkey: true,
15448
+ sso: true,
15449
+ apiKey: true,
15450
+ username: true,
15451
+ phone: true,
15452
+ device: true,
15453
+ oneTimeToken: true,
15454
+ loginHistory: true,
15455
+ oidcProvider: true,
15456
+ jwt: true,
15457
+ rebac: true,
15458
+ federation: true
15459
+ };
15460
+ function resolveEnabledFeatures(config) {
15461
+ if (!config) {
15462
+ return ALL_FEATURES_ENABLED;
15463
+ }
15464
+ const hasAgents = !!config.agents || !!config.did;
15465
+ const hasSession = !!config.auth?.session;
15466
+ const hasOAuth = config.plugins?.some((p2) => p2.id === "kavach-oauth") ?? false;
15467
+ const hasOidc = config.plugins?.some((p2) => p2.id === "kavach-oidc-provider") ?? false;
15468
+ return {
15469
+ core: true,
15470
+ session: hasSession,
15471
+ agent: hasAgents,
15472
+ audit: hasAgents,
15473
+ oauth: hasOAuth,
15474
+ tenant: hasAgents,
15475
+ mcp: !!config.mcp,
15476
+ org: !!config.org,
15477
+ rateLimit: hasAgents,
15478
+ budget: hasAgents,
15479
+ magicLink: !!config.magicLink,
15480
+ emailOtp: !!config.emailOtp,
15481
+ totp: !!config.totp,
15482
+ passkey: !!config.passkey,
15483
+ sso: !!config.sso,
15484
+ apiKey: !!config.apiKeys,
15485
+ username: !!config.username,
15486
+ phone: !!config.phone,
15487
+ device: hasSession,
15488
+ oneTimeToken: !!config.magicLink || !!config.emailOtp || !!config.passwordReset,
15489
+ loginHistory: hasSession,
15490
+ oidcProvider: hasOidc,
15491
+ jwt: hasSession,
15492
+ rebac: hasAgents,
15493
+ federation: false
15494
+ // only when explicitly configured (no config key yet)
15495
+ };
15496
+ }
15415
15497
  function buildStatements(provider) {
15416
15498
  const isPostgres = provider === "postgres";
15417
15499
  const isMysql = provider === "mysql";
@@ -15424,7 +15506,9 @@ function buildStatements(provider) {
15424
15506
  // ------------------------------------------------------------------
15425
15507
  // kavach_users
15426
15508
  // ------------------------------------------------------------------
15427
- `CREATE TABLE ${ifne} kavach_users (
15509
+ {
15510
+ feature: "core",
15511
+ sql: `CREATE TABLE ${ifne} kavach_users (
15428
15512
  id TEXT NOT NULL PRIMARY KEY,
15429
15513
  email TEXT NOT NULL UNIQUE,
15430
15514
  username TEXT UNIQUE,
@@ -15451,11 +15535,14 @@ function buildStatements(provider) {
15451
15535
  polar_cancel_at_period_end ${bool} NOT NULL DEFAULT ${isPostgres ? "FALSE" : "0"},
15452
15536
  created_at ${ts} NOT NULL,
15453
15537
  updated_at ${ts} NOT NULL
15454
- )`,
15538
+ )`
15539
+ },
15455
15540
  // ------------------------------------------------------------------
15456
15541
  // kavach_tenants (must come before kavach_agents – agents FK to tenants)
15457
15542
  // ------------------------------------------------------------------
15458
- `CREATE TABLE ${ifne} kavach_tenants (
15543
+ {
15544
+ feature: "tenant",
15545
+ sql: `CREATE TABLE ${ifne} kavach_tenants (
15459
15546
  id TEXT NOT NULL PRIMARY KEY,
15460
15547
  name TEXT NOT NULL,
15461
15548
  slug TEXT NOT NULL UNIQUE,
@@ -15463,11 +15550,14 @@ function buildStatements(provider) {
15463
15550
  status TEXT NOT NULL DEFAULT 'active',
15464
15551
  created_at ${ts} NOT NULL,
15465
15552
  updated_at ${ts} NOT NULL
15466
- )`,
15553
+ )`
15554
+ },
15467
15555
  // ------------------------------------------------------------------
15468
15556
  // kavach_agents
15469
15557
  // ------------------------------------------------------------------
15470
- `CREATE TABLE ${ifne} kavach_agents (
15558
+ {
15559
+ feature: "agent",
15560
+ sql: `CREATE TABLE ${ifne} kavach_agents (
15471
15561
  id TEXT NOT NULL PRIMARY KEY,
15472
15562
  owner_id TEXT NOT NULL REFERENCES kavach_users(id),
15473
15563
  tenant_id TEXT REFERENCES kavach_tenants(id),
@@ -15481,22 +15571,28 @@ function buildStatements(provider) {
15481
15571
  metadata ${json2},
15482
15572
  created_at ${ts} NOT NULL,
15483
15573
  updated_at ${ts} NOT NULL
15484
- )`,
15574
+ )`
15575
+ },
15485
15576
  // ------------------------------------------------------------------
15486
15577
  // kavach_permissions
15487
15578
  // ------------------------------------------------------------------
15488
- `CREATE TABLE ${ifne} kavach_permissions (
15579
+ {
15580
+ feature: "agent",
15581
+ sql: `CREATE TABLE ${ifne} kavach_permissions (
15489
15582
  id TEXT NOT NULL PRIMARY KEY,
15490
15583
  agent_id TEXT NOT NULL REFERENCES kavach_agents(id) ON DELETE CASCADE,
15491
15584
  resource TEXT NOT NULL,
15492
15585
  actions ${json2} NOT NULL,
15493
15586
  constraints ${json2},
15494
15587
  created_at ${ts} NOT NULL
15495
- )`,
15588
+ )`
15589
+ },
15496
15590
  // ------------------------------------------------------------------
15497
15591
  // kavach_delegation_chains
15498
15592
  // ------------------------------------------------------------------
15499
- `CREATE TABLE ${ifne} kavach_delegation_chains (
15593
+ {
15594
+ feature: "agent",
15595
+ sql: `CREATE TABLE ${ifne} kavach_delegation_chains (
15500
15596
  id TEXT NOT NULL PRIMARY KEY,
15501
15597
  from_agent_id TEXT NOT NULL REFERENCES kavach_agents(id),
15502
15598
  to_agent_id TEXT NOT NULL REFERENCES kavach_agents(id),
@@ -15506,11 +15602,14 @@ function buildStatements(provider) {
15506
15602
  status TEXT NOT NULL DEFAULT 'active',
15507
15603
  expires_at ${ts} NOT NULL,
15508
15604
  created_at ${ts} NOT NULL
15509
- )`,
15605
+ )`
15606
+ },
15510
15607
  // ------------------------------------------------------------------
15511
15608
  // kavach_audit_logs
15512
15609
  // ------------------------------------------------------------------
15513
- `CREATE TABLE ${ifne} kavach_audit_logs (
15610
+ {
15611
+ feature: "audit",
15612
+ sql: `CREATE TABLE ${ifne} kavach_audit_logs (
15514
15613
  id TEXT NOT NULL PRIMARY KEY,
15515
15614
  agent_id TEXT NOT NULL REFERENCES kavach_agents(id),
15516
15615
  user_id TEXT NOT NULL REFERENCES kavach_users(id),
@@ -15524,21 +15623,27 @@ function buildStatements(provider) {
15524
15623
  ip TEXT,
15525
15624
  user_agent TEXT,
15526
15625
  timestamp ${ts} NOT NULL
15527
- )`,
15626
+ )`
15627
+ },
15528
15628
  // ------------------------------------------------------------------
15529
15629
  // kavach_rate_limits
15530
15630
  // ------------------------------------------------------------------
15531
- `CREATE TABLE ${ifne} kavach_rate_limits (
15631
+ {
15632
+ feature: "rateLimit",
15633
+ sql: `CREATE TABLE ${ifne} kavach_rate_limits (
15532
15634
  id TEXT NOT NULL PRIMARY KEY,
15533
15635
  agent_id TEXT NOT NULL REFERENCES kavach_agents(id) ON DELETE CASCADE,
15534
15636
  resource TEXT NOT NULL,
15535
15637
  window_start ${ts} NOT NULL,
15536
15638
  count INTEGER NOT NULL DEFAULT 0
15537
- )`,
15639
+ )`
15640
+ },
15538
15641
  // ------------------------------------------------------------------
15539
15642
  // kavach_mcp_servers
15540
15643
  // ------------------------------------------------------------------
15541
- `CREATE TABLE ${ifne} kavach_mcp_servers (
15644
+ {
15645
+ feature: "mcp",
15646
+ sql: `CREATE TABLE ${ifne} kavach_mcp_servers (
15542
15647
  id TEXT NOT NULL PRIMARY KEY,
15543
15648
  name TEXT NOT NULL,
15544
15649
  endpoint TEXT NOT NULL UNIQUE,
@@ -15548,21 +15653,27 @@ function buildStatements(provider) {
15548
15653
  status TEXT NOT NULL DEFAULT 'active',
15549
15654
  created_at ${ts} NOT NULL,
15550
15655
  updated_at ${ts} NOT NULL
15551
- )`,
15656
+ )`
15657
+ },
15552
15658
  // ------------------------------------------------------------------
15553
15659
  // kavach_sessions
15554
15660
  // ------------------------------------------------------------------
15555
- `CREATE TABLE ${ifne} kavach_sessions (
15661
+ {
15662
+ feature: "session",
15663
+ sql: `CREATE TABLE ${ifne} kavach_sessions (
15556
15664
  id TEXT NOT NULL PRIMARY KEY,
15557
15665
  user_id TEXT NOT NULL REFERENCES kavach_users(id),
15558
15666
  expires_at ${ts} NOT NULL,
15559
15667
  metadata ${json2},
15560
15668
  created_at ${ts} NOT NULL
15561
- )`,
15669
+ )`
15670
+ },
15562
15671
  // ------------------------------------------------------------------
15563
15672
  // kavach_oauth_clients
15564
15673
  // ------------------------------------------------------------------
15565
- `CREATE TABLE ${ifne} kavach_oauth_clients (
15674
+ {
15675
+ feature: "oauth",
15676
+ sql: `CREATE TABLE ${ifne} kavach_oauth_clients (
15566
15677
  id TEXT NOT NULL PRIMARY KEY,
15567
15678
  client_id TEXT NOT NULL UNIQUE,
15568
15679
  client_secret TEXT,
@@ -15577,11 +15688,14 @@ function buildStatements(provider) {
15577
15688
  metadata ${json2},
15578
15689
  created_at ${ts} NOT NULL,
15579
15690
  updated_at ${ts} NOT NULL
15580
- )`,
15691
+ )`
15692
+ },
15581
15693
  // ------------------------------------------------------------------
15582
15694
  // kavach_oauth_access_tokens
15583
15695
  // ------------------------------------------------------------------
15584
- `CREATE TABLE ${ifne} kavach_oauth_access_tokens (
15696
+ {
15697
+ feature: "oauth",
15698
+ sql: `CREATE TABLE ${ifne} kavach_oauth_access_tokens (
15585
15699
  id TEXT NOT NULL PRIMARY KEY,
15586
15700
  access_token TEXT NOT NULL UNIQUE,
15587
15701
  refresh_token TEXT UNIQUE,
@@ -15592,11 +15706,14 @@ function buildStatements(provider) {
15592
15706
  access_token_expires_at ${ts} NOT NULL,
15593
15707
  refresh_token_expires_at ${tsNull},
15594
15708
  created_at ${ts} NOT NULL
15595
- )`,
15709
+ )`
15710
+ },
15596
15711
  // ------------------------------------------------------------------
15597
15712
  // kavach_oauth_authorization_codes
15598
15713
  // ------------------------------------------------------------------
15599
- `CREATE TABLE ${ifne} kavach_oauth_authorization_codes (
15714
+ {
15715
+ feature: "oauth",
15716
+ sql: `CREATE TABLE ${ifne} kavach_oauth_authorization_codes (
15600
15717
  id TEXT NOT NULL PRIMARY KEY,
15601
15718
  code TEXT NOT NULL UNIQUE,
15602
15719
  client_id TEXT NOT NULL REFERENCES kavach_oauth_clients(client_id),
@@ -15608,11 +15725,14 @@ function buildStatements(provider) {
15608
15725
  resource TEXT,
15609
15726
  expires_at ${ts} NOT NULL,
15610
15727
  created_at ${ts} NOT NULL
15611
- )`,
15728
+ )`
15729
+ },
15612
15730
  // ------------------------------------------------------------------
15613
15731
  // kavach_oauth_accounts (provider account linking)
15614
15732
  // ------------------------------------------------------------------
15615
- `CREATE TABLE ${ifne} kavach_oauth_accounts (
15733
+ {
15734
+ feature: "oauth",
15735
+ sql: `CREATE TABLE ${ifne} kavach_oauth_accounts (
15616
15736
  id TEXT NOT NULL PRIMARY KEY,
15617
15737
  user_id TEXT NOT NULL,
15618
15738
  provider TEXT NOT NULL,
@@ -15622,22 +15742,28 @@ function buildStatements(provider) {
15622
15742
  expires_at ${tsNull},
15623
15743
  created_at ${ts} NOT NULL,
15624
15744
  updated_at ${ts} NOT NULL
15625
- )`,
15745
+ )`
15746
+ },
15626
15747
  // ------------------------------------------------------------------
15627
15748
  // kavach_oauth_states (PKCE state for CSRF protection)
15628
15749
  // ------------------------------------------------------------------
15629
- `CREATE TABLE ${ifne} kavach_oauth_states (
15750
+ {
15751
+ feature: "oauth",
15752
+ sql: `CREATE TABLE ${ifne} kavach_oauth_states (
15630
15753
  state TEXT NOT NULL PRIMARY KEY,
15631
15754
  code_verifier TEXT NOT NULL,
15632
15755
  redirect_uri TEXT NOT NULL,
15633
15756
  provider TEXT NOT NULL,
15634
15757
  expires_at ${ts} NOT NULL,
15635
15758
  created_at ${ts} NOT NULL
15636
- )`,
15759
+ )`
15760
+ },
15637
15761
  // ------------------------------------------------------------------
15638
15762
  // kavach_budget_policies
15639
15763
  // ------------------------------------------------------------------
15640
- `CREATE TABLE ${ifne} kavach_budget_policies (
15764
+ {
15765
+ feature: "budget",
15766
+ sql: `CREATE TABLE ${ifne} kavach_budget_policies (
15641
15767
  id TEXT NOT NULL PRIMARY KEY,
15642
15768
  agent_id TEXT REFERENCES kavach_agents(id) ON DELETE CASCADE,
15643
15769
  user_id TEXT REFERENCES kavach_users(id),
@@ -15647,11 +15773,14 @@ function buildStatements(provider) {
15647
15773
  action TEXT NOT NULL DEFAULT 'warn',
15648
15774
  status TEXT NOT NULL DEFAULT 'active',
15649
15775
  created_at ${ts} NOT NULL
15650
- )`,
15776
+ )`
15777
+ },
15651
15778
  // ------------------------------------------------------------------
15652
15779
  // kavach_agent_cards (A2A discovery)
15653
15780
  // ------------------------------------------------------------------
15654
- `CREATE TABLE ${ifne} kavach_agent_cards (
15781
+ {
15782
+ feature: "agent",
15783
+ sql: `CREATE TABLE ${ifne} kavach_agent_cards (
15655
15784
  id TEXT NOT NULL PRIMARY KEY,
15656
15785
  agent_id TEXT NOT NULL REFERENCES kavach_agents(id) ON DELETE CASCADE,
15657
15786
  name TEXT NOT NULL,
@@ -15664,11 +15793,14 @@ function buildStatements(provider) {
15664
15793
  metadata ${json2},
15665
15794
  created_at ${ts} NOT NULL,
15666
15795
  updated_at ${ts} NOT NULL
15667
- )`,
15796
+ )`
15797
+ },
15668
15798
  // ------------------------------------------------------------------
15669
15799
  // kavach_approval_requests (CIBA async approval flows)
15670
15800
  // ------------------------------------------------------------------
15671
- `CREATE TABLE ${ifne} kavach_approval_requests (
15801
+ {
15802
+ feature: "agent",
15803
+ sql: `CREATE TABLE ${ifne} kavach_approval_requests (
15672
15804
  id TEXT NOT NULL PRIMARY KEY,
15673
15805
  agent_id TEXT NOT NULL REFERENCES kavach_agents(id) ON DELETE CASCADE,
15674
15806
  user_id TEXT NOT NULL REFERENCES kavach_users(id),
@@ -15680,21 +15812,27 @@ function buildStatements(provider) {
15680
15812
  responded_at ${tsNull},
15681
15813
  responded_by TEXT,
15682
15814
  created_at ${ts} NOT NULL
15683
- )`,
15815
+ )`
15816
+ },
15684
15817
  // ------------------------------------------------------------------
15685
15818
  // kavach_trust_scores (graduated autonomy scoring)
15686
15819
  // ------------------------------------------------------------------
15687
- `CREATE TABLE ${ifne} kavach_trust_scores (
15820
+ {
15821
+ feature: "agent",
15822
+ sql: `CREATE TABLE ${ifne} kavach_trust_scores (
15688
15823
  agent_id TEXT NOT NULL PRIMARY KEY REFERENCES kavach_agents(id) ON DELETE CASCADE,
15689
15824
  score INTEGER NOT NULL,
15690
15825
  level TEXT NOT NULL,
15691
15826
  factors ${json2} NOT NULL,
15692
15827
  computed_at ${ts} NOT NULL
15693
- )`,
15828
+ )`
15829
+ },
15694
15830
  // ------------------------------------------------------------------
15695
15831
  // kavach_organizations
15696
15832
  // ------------------------------------------------------------------
15697
- `CREATE TABLE ${ifne} kavach_organizations (
15833
+ {
15834
+ feature: "org",
15835
+ sql: `CREATE TABLE ${ifne} kavach_organizations (
15698
15836
  id TEXT NOT NULL PRIMARY KEY,
15699
15837
  name TEXT NOT NULL,
15700
15838
  slug TEXT NOT NULL UNIQUE,
@@ -15702,22 +15840,28 @@ function buildStatements(provider) {
15702
15840
  metadata ${json2},
15703
15841
  created_at ${ts} NOT NULL,
15704
15842
  updated_at ${ts} NOT NULL
15705
- )`,
15843
+ )`
15844
+ },
15706
15845
  // ------------------------------------------------------------------
15707
15846
  // kavach_org_members
15708
15847
  // ------------------------------------------------------------------
15709
- `CREATE TABLE ${ifne} kavach_org_members (
15848
+ {
15849
+ feature: "org",
15850
+ sql: `CREATE TABLE ${ifne} kavach_org_members (
15710
15851
  id TEXT NOT NULL PRIMARY KEY,
15711
15852
  org_id TEXT NOT NULL REFERENCES kavach_organizations(id) ON DELETE CASCADE,
15712
15853
  user_id TEXT NOT NULL REFERENCES kavach_users(id),
15713
15854
  role TEXT NOT NULL DEFAULT 'member',
15714
15855
  joined_at ${ts} NOT NULL,
15715
15856
  UNIQUE(org_id, user_id)
15716
- )`,
15857
+ )`
15858
+ },
15717
15859
  // ------------------------------------------------------------------
15718
15860
  // kavach_org_invitations
15719
15861
  // ------------------------------------------------------------------
15720
- `CREATE TABLE ${ifne} kavach_org_invitations (
15862
+ {
15863
+ feature: "org",
15864
+ sql: `CREATE TABLE ${ifne} kavach_org_invitations (
15721
15865
  id TEXT NOT NULL PRIMARY KEY,
15722
15866
  org_id TEXT NOT NULL REFERENCES kavach_organizations(id) ON DELETE CASCADE,
15723
15867
  email TEXT NOT NULL,
@@ -15726,21 +15870,27 @@ function buildStatements(provider) {
15726
15870
  status TEXT NOT NULL DEFAULT 'pending',
15727
15871
  expires_at ${ts} NOT NULL,
15728
15872
  created_at ${ts} NOT NULL
15729
- )`,
15873
+ )`
15874
+ },
15730
15875
  // ------------------------------------------------------------------
15731
15876
  // kavach_org_roles
15732
15877
  // ------------------------------------------------------------------
15733
- `CREATE TABLE ${ifne} kavach_org_roles (
15878
+ {
15879
+ feature: "org",
15880
+ sql: `CREATE TABLE ${ifne} kavach_org_roles (
15734
15881
  id TEXT NOT NULL PRIMARY KEY,
15735
15882
  org_id TEXT NOT NULL REFERENCES kavach_organizations(id) ON DELETE CASCADE,
15736
15883
  name TEXT NOT NULL,
15737
15884
  permissions ${json2} NOT NULL,
15738
15885
  UNIQUE(org_id, name)
15739
- )`,
15886
+ )`
15887
+ },
15740
15888
  // ------------------------------------------------------------------
15741
15889
  // kavach_passkey_credentials (WebAuthn / FIDO2 passkeys)
15742
15890
  // ------------------------------------------------------------------
15743
- `CREATE TABLE ${ifne} kavach_passkey_credentials (
15891
+ {
15892
+ feature: "passkey",
15893
+ sql: `CREATE TABLE ${ifne} kavach_passkey_credentials (
15744
15894
  id TEXT NOT NULL PRIMARY KEY,
15745
15895
  user_id TEXT NOT NULL REFERENCES kavach_users(id),
15746
15896
  credential_id TEXT NOT NULL UNIQUE,
@@ -15750,22 +15900,28 @@ function buildStatements(provider) {
15750
15900
  transports TEXT,
15751
15901
  created_at ${ts} NOT NULL,
15752
15902
  last_used_at ${ts} NOT NULL
15753
- )`,
15903
+ )`
15904
+ },
15754
15905
  // ------------------------------------------------------------------
15755
15906
  // kavach_passkey_challenges (short-lived WebAuthn challenges)
15756
15907
  // ------------------------------------------------------------------
15757
- `CREATE TABLE ${ifne} kavach_passkey_challenges (
15908
+ {
15909
+ feature: "passkey",
15910
+ sql: `CREATE TABLE ${ifne} kavach_passkey_challenges (
15758
15911
  id TEXT NOT NULL PRIMARY KEY,
15759
15912
  challenge TEXT NOT NULL UNIQUE,
15760
15913
  user_id TEXT,
15761
15914
  type TEXT NOT NULL,
15762
15915
  expires_at ${ts} NOT NULL,
15763
15916
  created_at ${ts} NOT NULL
15764
- )`,
15917
+ )`
15918
+ },
15765
15919
  // ------------------------------------------------------------------
15766
15920
  // kavach_one_time_tokens (email verify, password reset, invitation)
15767
15921
  // ------------------------------------------------------------------
15768
- `CREATE TABLE ${ifne} kavach_one_time_tokens (
15922
+ {
15923
+ feature: "oneTimeToken",
15924
+ sql: `CREATE TABLE ${ifne} kavach_one_time_tokens (
15769
15925
  id TEXT NOT NULL PRIMARY KEY,
15770
15926
  token_hash TEXT NOT NULL UNIQUE,
15771
15927
  purpose TEXT NOT NULL,
@@ -15774,55 +15930,70 @@ function buildStatements(provider) {
15774
15930
  used ${bool} NOT NULL DEFAULT ${isPostgres ? "FALSE" : "0"},
15775
15931
  expires_at ${ts} NOT NULL,
15776
15932
  created_at ${ts} NOT NULL
15777
- )`,
15933
+ )`
15934
+ },
15778
15935
  // ------------------------------------------------------------------
15779
15936
  // kavach_agent_dids (W3C Decentralized Identifiers per agent)
15780
15937
  // ------------------------------------------------------------------
15781
- `CREATE TABLE ${ifne} kavach_agent_dids (
15938
+ {
15939
+ feature: "agent",
15940
+ sql: `CREATE TABLE ${ifne} kavach_agent_dids (
15782
15941
  agent_id TEXT NOT NULL PRIMARY KEY REFERENCES kavach_agents(id) ON DELETE CASCADE,
15783
15942
  did TEXT NOT NULL UNIQUE,
15784
15943
  method TEXT NOT NULL,
15785
15944
  public_key_jwk TEXT NOT NULL,
15786
15945
  did_document TEXT NOT NULL,
15787
15946
  created_at ${ts} NOT NULL
15788
- )`,
15947
+ )`
15948
+ },
15789
15949
  // ------------------------------------------------------------------
15790
15950
  // kavach_magic_links (passwordless email login)
15791
15951
  // ------------------------------------------------------------------
15792
- `CREATE TABLE ${ifne} kavach_magic_links (
15952
+ {
15953
+ feature: "magicLink",
15954
+ sql: `CREATE TABLE ${ifne} kavach_magic_links (
15793
15955
  id TEXT NOT NULL PRIMARY KEY,
15794
15956
  email TEXT NOT NULL,
15795
15957
  token TEXT NOT NULL UNIQUE,
15796
15958
  expires_at ${ts} NOT NULL,
15797
15959
  used ${bool} NOT NULL DEFAULT ${isPostgres ? "FALSE" : "0"},
15798
15960
  created_at ${ts} NOT NULL
15799
- )`,
15961
+ )`
15962
+ },
15800
15963
  // ------------------------------------------------------------------
15801
15964
  // kavach_email_otps (one-time password login)
15802
15965
  // ------------------------------------------------------------------
15803
- `CREATE TABLE ${ifne} kavach_email_otps (
15966
+ {
15967
+ feature: "emailOtp",
15968
+ sql: `CREATE TABLE ${ifne} kavach_email_otps (
15804
15969
  id TEXT NOT NULL PRIMARY KEY,
15805
15970
  email TEXT NOT NULL,
15806
15971
  code_hash TEXT NOT NULL,
15807
15972
  expires_at ${ts} NOT NULL,
15808
15973
  attempts INTEGER NOT NULL DEFAULT 0,
15809
15974
  created_at ${ts} NOT NULL
15810
- )`,
15975
+ )`
15976
+ },
15811
15977
  // ------------------------------------------------------------------
15812
15978
  // kavach_totp (TOTP two-factor authentication)
15813
15979
  // ------------------------------------------------------------------
15814
- `CREATE TABLE ${ifne} kavach_totp (
15980
+ {
15981
+ feature: "totp",
15982
+ sql: `CREATE TABLE ${ifne} kavach_totp (
15815
15983
  user_id TEXT NOT NULL PRIMARY KEY REFERENCES kavach_users(id),
15816
15984
  secret TEXT NOT NULL,
15817
15985
  enabled ${bool} NOT NULL DEFAULT ${isPostgres ? "FALSE" : "0"},
15818
15986
  backup_codes ${json2} NOT NULL,
15819
15987
  created_at ${ts} NOT NULL,
15820
15988
  updated_at ${ts} NOT NULL
15821
- )`,
15989
+ )`
15990
+ },
15822
15991
  // ------------------------------------------------------------------
15823
15992
  // kavach_sso_connections (SAML 2.0 / OIDC enterprise SSO)
15824
15993
  // ------------------------------------------------------------------
15825
- `CREATE TABLE ${ifne} kavach_sso_connections (
15994
+ {
15995
+ feature: "sso",
15996
+ sql: `CREATE TABLE ${ifne} kavach_sso_connections (
15826
15997
  id TEXT NOT NULL PRIMARY KEY,
15827
15998
  org_id TEXT NOT NULL,
15828
15999
  provider_id TEXT NOT NULL,
@@ -15830,11 +16001,14 @@ function buildStatements(provider) {
15830
16001
  domain TEXT NOT NULL UNIQUE,
15831
16002
  enabled INTEGER NOT NULL DEFAULT 1,
15832
16003
  created_at ${ts} NOT NULL
15833
- )`,
16004
+ )`
16005
+ },
15834
16006
  // ------------------------------------------------------------------
15835
16007
  // kavach_api_keys (static bearer tokens with permission scopes)
15836
16008
  // ------------------------------------------------------------------
15837
- `CREATE TABLE ${ifne} kavach_api_keys (
16009
+ {
16010
+ feature: "apiKey",
16011
+ sql: `CREATE TABLE ${ifne} kavach_api_keys (
15838
16012
  id TEXT NOT NULL PRIMARY KEY,
15839
16013
  user_id TEXT NOT NULL REFERENCES kavach_users(id),
15840
16014
  name TEXT NOT NULL,
@@ -15844,57 +16018,75 @@ function buildStatements(provider) {
15844
16018
  expires_at ${tsNull},
15845
16019
  last_used_at ${tsNull},
15846
16020
  created_at ${ts} NOT NULL
15847
- )`,
16021
+ )`
16022
+ },
15848
16023
  // ------------------------------------------------------------------
15849
16024
  // kavach_username_accounts (username + password auth)
15850
16025
  // ------------------------------------------------------------------
15851
- `CREATE TABLE ${ifne} kavach_username_accounts (
16026
+ {
16027
+ feature: "username",
16028
+ sql: `CREATE TABLE ${ifne} kavach_username_accounts (
15852
16029
  id TEXT NOT NULL PRIMARY KEY,
15853
16030
  user_id TEXT NOT NULL REFERENCES kavach_users(id) ON DELETE CASCADE,
15854
16031
  username TEXT NOT NULL UNIQUE,
15855
16032
  password_hash TEXT NOT NULL,
15856
16033
  created_at ${ts} NOT NULL,
15857
16034
  updated_at ${ts} NOT NULL
15858
- )`,
16035
+ )`
16036
+ },
15859
16037
  // ------------------------------------------------------------------
15860
16038
  // kavach_phone_verifications (SMS OTP)
15861
16039
  // ------------------------------------------------------------------
15862
- `CREATE TABLE ${ifne} kavach_phone_verifications (
16040
+ {
16041
+ feature: "phone",
16042
+ sql: `CREATE TABLE ${ifne} kavach_phone_verifications (
15863
16043
  id TEXT NOT NULL PRIMARY KEY,
15864
16044
  phone_number TEXT NOT NULL,
15865
16045
  code_hash TEXT NOT NULL,
15866
16046
  attempts INTEGER NOT NULL DEFAULT 0,
15867
16047
  expires_at ${ts} NOT NULL,
15868
16048
  created_at ${ts} NOT NULL
15869
- )`,
16049
+ )`
16050
+ },
15870
16051
  // ------------------------------------------------------------------
15871
16052
  // kavach_trusted_devices (skip 2FA on trusted devices for a window)
15872
16053
  // ------------------------------------------------------------------
15873
- `CREATE TABLE ${ifne} kavach_trusted_devices (
16054
+ {
16055
+ feature: "device",
16056
+ sql: `CREATE TABLE ${ifne} kavach_trusted_devices (
15874
16057
  id TEXT NOT NULL PRIMARY KEY,
15875
16058
  user_id TEXT NOT NULL REFERENCES kavach_users(id) ON DELETE CASCADE,
15876
16059
  fingerprint TEXT NOT NULL,
15877
16060
  label TEXT NOT NULL,
15878
16061
  trusted_at ${ts} NOT NULL,
15879
16062
  expires_at ${ts} NOT NULL
15880
- )`,
16063
+ )`
16064
+ },
15881
16065
  // ------------------------------------------------------------------
15882
16066
  // kavach_login_history (last-login method tracking per user)
15883
16067
  // ------------------------------------------------------------------
15884
- `CREATE TABLE ${ifne} kavach_login_history (
16068
+ {
16069
+ feature: "loginHistory",
16070
+ sql: `CREATE TABLE ${ifne} kavach_login_history (
15885
16071
  id TEXT NOT NULL PRIMARY KEY,
15886
16072
  user_id TEXT NOT NULL REFERENCES kavach_users(id) ON DELETE CASCADE,
15887
16073
  method TEXT NOT NULL,
15888
16074
  ip TEXT,
15889
16075
  user_agent TEXT,
15890
16076
  timestamp ${ts} NOT NULL
15891
- )`,
15892
- `CREATE INDEX ${ifne} kavach_login_history_user_ts
15893
- ON kavach_login_history (user_id, timestamp DESC)`,
16077
+ )`
16078
+ },
16079
+ {
16080
+ feature: "loginHistory",
16081
+ sql: `CREATE INDEX ${ifne} kavach_login_history_user_ts
16082
+ ON kavach_login_history (user_id, timestamp DESC)`
16083
+ },
15894
16084
  // ------------------------------------------------------------------
15895
16085
  // kavach_oidc_clients (OIDC Provider — registered relying parties)
15896
16086
  // ------------------------------------------------------------------
15897
- `CREATE TABLE ${ifne} kavach_oidc_clients (
16087
+ {
16088
+ feature: "oidcProvider",
16089
+ sql: `CREATE TABLE ${ifne} kavach_oidc_clients (
15898
16090
  id TEXT NOT NULL PRIMARY KEY,
15899
16091
  client_id TEXT NOT NULL UNIQUE,
15900
16092
  client_secret_hash TEXT NOT NULL,
@@ -15906,11 +16098,14 @@ function buildStatements(provider) {
15906
16098
  token_endpoint_auth_method TEXT NOT NULL DEFAULT 'client_secret_post',
15907
16099
  created_at ${ts} NOT NULL,
15908
16100
  updated_at ${ts} NOT NULL
15909
- )`,
16101
+ )`
16102
+ },
15910
16103
  // ------------------------------------------------------------------
15911
16104
  // kavach_oidc_auth_codes (OIDC Provider — authorization codes)
15912
16105
  // ------------------------------------------------------------------
15913
- `CREATE TABLE ${ifne} kavach_oidc_auth_codes (
16106
+ {
16107
+ feature: "oidcProvider",
16108
+ sql: `CREATE TABLE ${ifne} kavach_oidc_auth_codes (
15914
16109
  id TEXT NOT NULL PRIMARY KEY,
15915
16110
  code_hash TEXT NOT NULL UNIQUE,
15916
16111
  client_id TEXT NOT NULL,
@@ -15923,11 +16118,14 @@ function buildStatements(provider) {
15923
16118
  used ${bool} NOT NULL DEFAULT ${isPostgres ? "FALSE" : "0"},
15924
16119
  expires_at ${ts} NOT NULL,
15925
16120
  created_at ${ts} NOT NULL
15926
- )`,
16121
+ )`
16122
+ },
15927
16123
  // ------------------------------------------------------------------
15928
16124
  // kavach_oidc_refresh_tokens (OIDC Provider — refresh tokens)
15929
16125
  // ------------------------------------------------------------------
15930
- `CREATE TABLE ${ifne} kavach_oidc_refresh_tokens (
16126
+ {
16127
+ feature: "oidcProvider",
16128
+ sql: `CREATE TABLE ${ifne} kavach_oidc_refresh_tokens (
15931
16129
  id TEXT NOT NULL PRIMARY KEY,
15932
16130
  token_hash TEXT NOT NULL UNIQUE,
15933
16131
  client_id TEXT NOT NULL,
@@ -15936,11 +16134,14 @@ function buildStatements(provider) {
15936
16134
  revoked ${bool} NOT NULL DEFAULT ${isPostgres ? "FALSE" : "0"},
15937
16135
  expires_at ${ts} NOT NULL,
15938
16136
  created_at ${ts} NOT NULL
15939
- )`,
16137
+ )`
16138
+ },
15940
16139
  // ------------------------------------------------------------------
15941
16140
  // kavach_cost_events (per-agent cost attribution)
15942
16141
  // ------------------------------------------------------------------
15943
- `CREATE TABLE ${ifne} kavach_cost_events (
16142
+ {
16143
+ feature: "audit",
16144
+ sql: `CREATE TABLE ${ifne} kavach_cost_events (
15944
16145
  id TEXT NOT NULL PRIMARY KEY,
15945
16146
  agent_id TEXT NOT NULL REFERENCES kavach_agents(id) ON DELETE CASCADE,
15946
16147
  tool TEXT NOT NULL,
@@ -15951,15 +16152,24 @@ function buildStatements(provider) {
15951
16152
  metadata ${json2},
15952
16153
  delegation_chain_id TEXT,
15953
16154
  recorded_at ${ts} NOT NULL
15954
- )`,
15955
- `CREATE INDEX ${ifne} kavach_cost_events_agent_recorded
15956
- ON kavach_cost_events (agent_id, recorded_at DESC)`,
15957
- `CREATE INDEX ${ifne} kavach_cost_events_chain_id
15958
- ON kavach_cost_events (delegation_chain_id)`,
16155
+ )`
16156
+ },
16157
+ {
16158
+ feature: "audit",
16159
+ sql: `CREATE INDEX ${ifne} kavach_cost_events_agent_recorded
16160
+ ON kavach_cost_events (agent_id, recorded_at DESC)`
16161
+ },
16162
+ {
16163
+ feature: "audit",
16164
+ sql: `CREATE INDEX ${ifne} kavach_cost_events_chain_id
16165
+ ON kavach_cost_events (delegation_chain_id)`
16166
+ },
15959
16167
  // ------------------------------------------------------------------
15960
16168
  // kavach_ephemeral_sessions (short-lived agent credentials)
15961
16169
  // ------------------------------------------------------------------
15962
- `CREATE TABLE ${ifne} kavach_ephemeral_sessions (
16170
+ {
16171
+ feature: "agent",
16172
+ sql: `CREATE TABLE ${ifne} kavach_ephemeral_sessions (
15963
16173
  id TEXT NOT NULL PRIMARY KEY,
15964
16174
  agent_id TEXT NOT NULL REFERENCES kavach_agents(id) ON DELETE CASCADE,
15965
16175
  owner_id TEXT NOT NULL REFERENCES kavach_users(id),
@@ -15971,55 +16181,85 @@ function buildStatements(provider) {
15971
16181
  audit_group_id TEXT NOT NULL,
15972
16182
  created_at ${ts} NOT NULL,
15973
16183
  updated_at ${ts} NOT NULL
15974
- )`,
15975
- `CREATE INDEX ${ifne} kavach_ephemeral_sessions_owner_status
15976
- ON kavach_ephemeral_sessions (owner_id, status)`,
15977
- `CREATE INDEX ${ifne} kavach_ephemeral_sessions_expires_at
15978
- ON kavach_ephemeral_sessions (expires_at)`,
16184
+ )`
16185
+ },
16186
+ {
16187
+ feature: "agent",
16188
+ sql: `CREATE INDEX ${ifne} kavach_ephemeral_sessions_owner_status
16189
+ ON kavach_ephemeral_sessions (owner_id, status)`
16190
+ },
16191
+ {
16192
+ feature: "agent",
16193
+ sql: `CREATE INDEX ${ifne} kavach_ephemeral_sessions_expires_at
16194
+ ON kavach_ephemeral_sessions (expires_at)`
16195
+ },
15979
16196
  // ------------------------------------------------------------------
15980
16197
  // kavach_jwt_refresh_tokens (JWT session plugin — general purpose)
15981
16198
  // ------------------------------------------------------------------
15982
- `CREATE TABLE ${ifne} kavach_jwt_refresh_tokens (
16199
+ {
16200
+ feature: "jwt",
16201
+ sql: `CREATE TABLE ${ifne} kavach_jwt_refresh_tokens (
15983
16202
  id TEXT NOT NULL PRIMARY KEY,
15984
16203
  token_hash TEXT NOT NULL UNIQUE,
15985
16204
  user_id TEXT NOT NULL REFERENCES kavach_users(id) ON DELETE CASCADE,
15986
16205
  used ${bool} NOT NULL DEFAULT ${isPostgres ? "FALSE" : "0"},
15987
16206
  expires_at ${ts} NOT NULL,
15988
16207
  created_at ${ts} NOT NULL
15989
- )`,
15990
- `CREATE INDEX ${ifne} kavach_jwt_refresh_tokens_user_id
15991
- ON kavach_jwt_refresh_tokens (user_id)`,
16208
+ )`
16209
+ },
16210
+ {
16211
+ feature: "jwt",
16212
+ sql: `CREATE INDEX ${ifne} kavach_jwt_refresh_tokens_user_id
16213
+ ON kavach_jwt_refresh_tokens (user_id)`
16214
+ },
15992
16215
  // ------------------------------------------------------------------
15993
16216
  // kavach_stream_events (persisted SSE events for replay)
15994
16217
  // ------------------------------------------------------------------
15995
- `CREATE TABLE ${ifne} kavach_stream_events (
16218
+ {
16219
+ feature: "audit",
16220
+ sql: `CREATE TABLE ${ifne} kavach_stream_events (
15996
16221
  id TEXT NOT NULL PRIMARY KEY,
15997
16222
  type TEXT NOT NULL,
15998
16223
  timestamp ${ts} NOT NULL,
15999
16224
  data ${json2} NOT NULL,
16000
16225
  agent_id TEXT,
16001
16226
  user_id TEXT
16002
- )`,
16003
- `CREATE INDEX ${ifne} kavach_stream_events_timestamp
16004
- ON kavach_stream_events (timestamp DESC)`,
16005
- `CREATE INDEX ${ifne} kavach_stream_events_type_timestamp
16006
- ON kavach_stream_events (type, timestamp DESC)`,
16227
+ )`
16228
+ },
16229
+ {
16230
+ feature: "audit",
16231
+ sql: `CREATE INDEX ${ifne} kavach_stream_events_timestamp
16232
+ ON kavach_stream_events (timestamp DESC)`
16233
+ },
16234
+ {
16235
+ feature: "audit",
16236
+ sql: `CREATE INDEX ${ifne} kavach_stream_events_type_timestamp
16237
+ ON kavach_stream_events (type, timestamp DESC)`
16238
+ },
16007
16239
  // ------------------------------------------------------------------
16008
16240
  // kavach_rebac_resources (ReBAC resource hierarchy)
16009
16241
  // ------------------------------------------------------------------
16010
- `CREATE TABLE ${ifne} kavach_rebac_resources (
16242
+ {
16243
+ feature: "rebac",
16244
+ sql: `CREATE TABLE ${ifne} kavach_rebac_resources (
16011
16245
  id TEXT NOT NULL PRIMARY KEY,
16012
16246
  type TEXT NOT NULL,
16013
16247
  parent_id TEXT,
16014
16248
  parent_type TEXT,
16015
16249
  created_at ${ts} NOT NULL
16016
- )`,
16017
- `CREATE INDEX ${ifne} kavach_rebac_resources_parent
16018
- ON kavach_rebac_resources (parent_id, parent_type)`,
16250
+ )`
16251
+ },
16252
+ {
16253
+ feature: "rebac",
16254
+ sql: `CREATE INDEX ${ifne} kavach_rebac_resources_parent
16255
+ ON kavach_rebac_resources (parent_id, parent_type)`
16256
+ },
16019
16257
  // ------------------------------------------------------------------
16020
16258
  // kavach_rebac_relationships (Zanzibar-style subject-relation-object tuples)
16021
16259
  // ------------------------------------------------------------------
16022
- `CREATE TABLE ${ifne} kavach_rebac_relationships (
16260
+ {
16261
+ feature: "rebac",
16262
+ sql: `CREATE TABLE ${ifne} kavach_rebac_relationships (
16023
16263
  id TEXT NOT NULL PRIMARY KEY,
16024
16264
  subject_type TEXT NOT NULL,
16025
16265
  subject_id TEXT NOT NULL,
@@ -16027,17 +16267,29 @@ function buildStatements(provider) {
16027
16267
  object_type TEXT NOT NULL,
16028
16268
  object_id TEXT NOT NULL,
16029
16269
  created_at ${ts} NOT NULL
16030
- )`,
16031
- `CREATE INDEX ${ifne} kavach_rebac_relationships_subject
16032
- ON kavach_rebac_relationships (subject_type, subject_id)`,
16033
- `CREATE INDEX ${ifne} kavach_rebac_relationships_object
16034
- ON kavach_rebac_relationships (object_type, object_id)`,
16035
- `CREATE UNIQUE INDEX ${ifne} kavach_rebac_relationships_tuple
16036
- ON kavach_rebac_relationships (subject_type, subject_id, relation, object_type, object_id)`,
16270
+ )`
16271
+ },
16272
+ {
16273
+ feature: "rebac",
16274
+ sql: `CREATE INDEX ${ifne} kavach_rebac_relationships_subject
16275
+ ON kavach_rebac_relationships (subject_type, subject_id)`
16276
+ },
16277
+ {
16278
+ feature: "rebac",
16279
+ sql: `CREATE INDEX ${ifne} kavach_rebac_relationships_object
16280
+ ON kavach_rebac_relationships (object_type, object_id)`
16281
+ },
16282
+ {
16283
+ feature: "rebac",
16284
+ sql: `CREATE UNIQUE INDEX ${ifne} kavach_rebac_relationships_tuple
16285
+ ON kavach_rebac_relationships (subject_type, subject_id, relation, object_type, object_id)`
16286
+ },
16037
16287
  // ------------------------------------------------------------------
16038
16288
  // kavach_federation_instances (trusted remote KavachOS instances)
16039
16289
  // ------------------------------------------------------------------
16040
- `CREATE TABLE ${ifne} kavach_federation_instances (
16290
+ {
16291
+ feature: "federation",
16292
+ sql: `CREATE TABLE ${ifne} kavach_federation_instances (
16041
16293
  id TEXT NOT NULL PRIMARY KEY,
16042
16294
  instance_id TEXT NOT NULL UNIQUE,
16043
16295
  instance_url TEXT NOT NULL,
@@ -16046,11 +16298,14 @@ function buildStatements(provider) {
16046
16298
  discovered_at ${tsNull},
16047
16299
  created_at ${ts} NOT NULL,
16048
16300
  updated_at ${ts} NOT NULL
16049
- )`,
16301
+ )`
16302
+ },
16050
16303
  // ------------------------------------------------------------------
16051
16304
  // kavach_federation_tokens (issued/received federation tokens)
16052
16305
  // ------------------------------------------------------------------
16053
- `CREATE TABLE ${ifne} kavach_federation_tokens (
16306
+ {
16307
+ feature: "federation",
16308
+ sql: `CREATE TABLE ${ifne} kavach_federation_tokens (
16054
16309
  id TEXT NOT NULL PRIMARY KEY,
16055
16310
  token_jti TEXT NOT NULL UNIQUE,
16056
16311
  agent_id TEXT NOT NULL,
@@ -16061,45 +16316,61 @@ function buildStatements(provider) {
16061
16316
  trust_score INTEGER,
16062
16317
  expires_at ${ts} NOT NULL,
16063
16318
  created_at ${ts} NOT NULL
16064
- )`,
16065
- `CREATE INDEX ${ifne} kavach_federation_tokens_agent
16066
- ON kavach_federation_tokens (agent_id)`,
16067
- `CREATE INDEX ${ifne} kavach_federation_tokens_source
16068
- ON kavach_federation_tokens (source_instance_id)`,
16319
+ )`
16320
+ },
16321
+ {
16322
+ feature: "federation",
16323
+ sql: `CREATE INDEX ${ifne} kavach_federation_tokens_agent
16324
+ ON kavach_federation_tokens (agent_id)`
16325
+ },
16326
+ {
16327
+ feature: "federation",
16328
+ sql: `CREATE INDEX ${ifne} kavach_federation_tokens_source
16329
+ ON kavach_federation_tokens (source_instance_id)`
16330
+ },
16069
16331
  // ------------------------------------------------------------------
16070
16332
  // kavach_refresh_token_families (token rotation / reuse detection)
16071
16333
  // ------------------------------------------------------------------
16072
- `CREATE TABLE ${ifne} kavach_refresh_token_families (
16334
+ {
16335
+ feature: "jwt",
16336
+ sql: `CREATE TABLE ${ifne} kavach_refresh_token_families (
16073
16337
  id TEXT NOT NULL PRIMARY KEY,
16074
16338
  user_id TEXT NOT NULL REFERENCES kavach_users(id) ON DELETE CASCADE,
16075
16339
  absolute_expires_at ${ts} NOT NULL,
16076
16340
  revoked ${bool} NOT NULL DEFAULT ${isPostgres ? "FALSE" : "0"},
16077
16341
  created_at ${ts} NOT NULL
16078
- )`,
16079
- `CREATE INDEX ${ifne} kavach_refresh_token_families_user_id
16080
- ON kavach_refresh_token_families (user_id)`,
16342
+ )`
16343
+ },
16344
+ {
16345
+ feature: "jwt",
16346
+ sql: `CREATE INDEX ${ifne} kavach_refresh_token_families_user_id
16347
+ ON kavach_refresh_token_families (user_id)`
16348
+ },
16081
16349
  // ------------------------------------------------------------------
16082
16350
  // kavach_refresh_tokens (individual one-time-use tokens per family)
16083
16351
  // ------------------------------------------------------------------
16084
- `CREATE TABLE ${ifne} kavach_refresh_tokens (
16352
+ {
16353
+ feature: "jwt",
16354
+ sql: `CREATE TABLE ${ifne} kavach_refresh_tokens (
16085
16355
  id TEXT NOT NULL PRIMARY KEY,
16086
16356
  family_id TEXT NOT NULL REFERENCES kavach_refresh_token_families(id) ON DELETE CASCADE,
16087
16357
  token_hash TEXT NOT NULL UNIQUE,
16088
16358
  used ${bool} NOT NULL DEFAULT ${isPostgres ? "FALSE" : "0"},
16089
16359
  expires_at ${ts} NOT NULL,
16090
16360
  created_at ${ts} NOT NULL
16091
- )`,
16092
- `CREATE INDEX ${ifne} kavach_refresh_tokens_family_id
16361
+ )`
16362
+ },
16363
+ {
16364
+ feature: "jwt",
16365
+ sql: `CREATE INDEX ${ifne} kavach_refresh_tokens_family_id
16093
16366
  ON kavach_refresh_tokens (family_id)`
16094
- // ------------------------------------------------------------------
16095
- // kavach_users ban columns (ALTER TABLE IF NOT EXISTS — safe no-ops)
16096
- // These are appended as separate ALTER statements for existing DBs.
16097
- // For SQLite we use a separate migration path since SQLite ALTER is limited.
16098
- // ------------------------------------------------------------------
16367
+ }
16099
16368
  ];
16100
16369
  }
16101
- async function createTables(db, provider) {
16102
- const statements = buildStatements(provider);
16370
+ async function createTables(db, provider, config) {
16371
+ const allStatements = buildStatements(provider);
16372
+ const features = resolveEnabledFeatures(config);
16373
+ const statements = allStatements.filter((s) => features[s.feature]).map((s) => s.sql);
16103
16374
  if (provider === "sqlite" || provider === "sqlite-native") {
16104
16375
  const session = db.session;
16105
16376
  if (session?.client?.exec) {
@@ -18281,7 +18552,7 @@ async function createKavach(config) {
18281
18552
  const authAdapter = config.auth?.adapter ?? null;
18282
18553
  const db = await createDatabase(config.database);
18283
18554
  if (!config.database.skipMigrations) {
18284
- await createTables(db, config.database.provider);
18555
+ await createTables(db, config.database.provider, config);
18285
18556
  }
18286
18557
  const agentConfig = {
18287
18558
  db,