@inkeep/agents-core 0.0.0-dev-20260118155108 → 0.0.0-dev-20260119163620

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.
@@ -2,7 +2,7 @@ import { AgentsRunDatabaseClient } from "../db/runtime/runtime-client.js";
2
2
  import * as _better_auth_sso0 from "@better-auth/sso";
3
3
  import * as better_auth0 from "better-auth";
4
4
  import { BetterAuthAdvancedOptions } from "better-auth";
5
- import * as better_auth_plugins0 from "better-auth/plugins";
5
+ import * as better_auth_plugins20 from "better-auth/plugins";
6
6
  import * as zod0 from "zod";
7
7
  import { GoogleOptions } from "better-auth/social-providers";
8
8
 
@@ -213,7 +213,7 @@ declare function createAuth(config: BetterAuthConfig): better_auth0.Auth<{
213
213
  handler: (inputContext: better_auth0.MiddlewareInputContext<better_auth0.MiddlewareOptions>) => Promise<void>;
214
214
  }[];
215
215
  };
216
- options: better_auth_plugins0.BearerOptions | undefined;
216
+ options: better_auth_plugins20.BearerOptions | undefined;
217
217
  }, {
218
218
  id: "sso";
219
219
  endpoints: {
@@ -841,30 +841,30 @@ declare function createAuth(config: BetterAuthConfig): better_auth0.Auth<{
841
841
  };
842
842
  }, {
843
843
  id: "organization";
844
- endpoints: better_auth_plugins0.OrganizationEndpoints<{
844
+ endpoints: better_auth_plugins20.OrganizationEndpoints<{
845
845
  allowUserToCreateOrganization: true;
846
- ac: better_auth_plugins0.AccessControl;
846
+ ac: better_auth_plugins20.AccessControl;
847
847
  roles: {
848
848
  member: {
849
- authorize<K_1 extends "function" | "agent" | "organization" | "member" | "invitation" | "ac" | "project" | "sub_agent" | "tool" | "api_key" | "credential" | "data_component" | "artifact_component" | "external_agent" | "context_config" | "team">(request: K_1 extends infer T extends K ? { [key in T]?: better_auth_plugins0.Subset<"function" | "agent" | "organization" | "member" | "invitation" | "ac" | "project" | "sub_agent" | "tool" | "api_key" | "credential" | "data_component" | "artifact_component" | "external_agent" | "context_config" | "team", better_auth_plugins0.Statements>[key] | {
850
- actions: better_auth_plugins0.Subset<"function" | "agent" | "organization" | "member" | "invitation" | "ac" | "project" | "sub_agent" | "tool" | "api_key" | "credential" | "data_component" | "artifact_component" | "external_agent" | "context_config" | "team", better_auth_plugins0.Statements>[key];
849
+ authorize<K_1 extends "project" | "organization" | "team" | "member" | "ac" | "invitation">(request: K_1 extends infer T extends K ? { [key in T]?: better_auth_plugins20.Subset<"project" | "organization" | "team" | "member" | "ac" | "invitation", better_auth_plugins20.Statements>[key] | {
850
+ actions: better_auth_plugins20.Subset<"project" | "organization" | "team" | "member" | "ac" | "invitation", better_auth_plugins20.Statements>[key];
851
851
  connector: "OR" | "AND";
852
- } | undefined } : never, connector?: "OR" | "AND"): better_auth_plugins0.AuthorizeResponse;
853
- statements: better_auth_plugins0.Subset<"function" | "agent" | "organization" | "member" | "invitation" | "ac" | "project" | "sub_agent" | "tool" | "api_key" | "credential" | "data_component" | "artifact_component" | "external_agent" | "context_config" | "team", better_auth_plugins0.Statements>;
852
+ } | undefined } : never, connector?: "OR" | "AND"): better_auth_plugins20.AuthorizeResponse;
853
+ statements: better_auth_plugins20.Subset<"project" | "organization" | "team" | "member" | "ac" | "invitation", better_auth_plugins20.Statements>;
854
854
  };
855
855
  admin: {
856
- authorize<K_1 extends "function" | "agent" | "organization" | "member" | "invitation" | "ac" | "project" | "sub_agent" | "tool" | "api_key" | "credential" | "data_component" | "artifact_component" | "external_agent" | "context_config" | "team">(request: K_1 extends infer T extends K ? { [key in T]?: better_auth_plugins0.Subset<"function" | "agent" | "organization" | "member" | "invitation" | "ac" | "project" | "sub_agent" | "tool" | "api_key" | "credential" | "data_component" | "artifact_component" | "external_agent" | "context_config" | "team", better_auth_plugins0.Statements>[key] | {
857
- actions: better_auth_plugins0.Subset<"function" | "agent" | "organization" | "member" | "invitation" | "ac" | "project" | "sub_agent" | "tool" | "api_key" | "credential" | "data_component" | "artifact_component" | "external_agent" | "context_config" | "team", better_auth_plugins0.Statements>[key];
856
+ authorize<K_1 extends "project" | "organization" | "team" | "member" | "ac" | "invitation">(request: K_1 extends infer T extends K ? { [key in T]?: better_auth_plugins20.Subset<"project" | "organization" | "team" | "member" | "ac" | "invitation", better_auth_plugins20.Statements>[key] | {
857
+ actions: better_auth_plugins20.Subset<"project" | "organization" | "team" | "member" | "ac" | "invitation", better_auth_plugins20.Statements>[key];
858
858
  connector: "OR" | "AND";
859
- } | undefined } : never, connector?: "OR" | "AND"): better_auth_plugins0.AuthorizeResponse;
860
- statements: better_auth_plugins0.Subset<"function" | "agent" | "organization" | "member" | "invitation" | "ac" | "project" | "sub_agent" | "tool" | "api_key" | "credential" | "data_component" | "artifact_component" | "external_agent" | "context_config" | "team", better_auth_plugins0.Statements>;
859
+ } | undefined } : never, connector?: "OR" | "AND"): better_auth_plugins20.AuthorizeResponse;
860
+ statements: better_auth_plugins20.Subset<"project" | "organization" | "team" | "member" | "ac" | "invitation", better_auth_plugins20.Statements>;
861
861
  };
862
862
  owner: {
863
- authorize<K_1 extends "function" | "agent" | "organization" | "member" | "invitation" | "ac" | "project" | "sub_agent" | "tool" | "api_key" | "credential" | "data_component" | "artifact_component" | "external_agent" | "context_config" | "team">(request: K_1 extends infer T extends K ? { [key in T]?: better_auth_plugins0.Subset<"function" | "agent" | "organization" | "member" | "invitation" | "ac" | "project" | "sub_agent" | "tool" | "api_key" | "credential" | "data_component" | "artifact_component" | "external_agent" | "context_config" | "team", better_auth_plugins0.Statements>[key] | {
864
- actions: better_auth_plugins0.Subset<"function" | "agent" | "organization" | "member" | "invitation" | "ac" | "project" | "sub_agent" | "tool" | "api_key" | "credential" | "data_component" | "artifact_component" | "external_agent" | "context_config" | "team", better_auth_plugins0.Statements>[key];
863
+ authorize<K_1 extends "project" | "organization" | "team" | "member" | "ac" | "invitation">(request: K_1 extends infer T extends K ? { [key in T]?: better_auth_plugins20.Subset<"project" | "organization" | "team" | "member" | "ac" | "invitation", better_auth_plugins20.Statements>[key] | {
864
+ actions: better_auth_plugins20.Subset<"project" | "organization" | "team" | "member" | "ac" | "invitation", better_auth_plugins20.Statements>[key];
865
865
  connector: "OR" | "AND";
866
- } | undefined } : never, connector?: "OR" | "AND"): better_auth_plugins0.AuthorizeResponse;
867
- statements: better_auth_plugins0.Subset<"function" | "agent" | "organization" | "member" | "invitation" | "ac" | "project" | "sub_agent" | "tool" | "api_key" | "credential" | "data_component" | "artifact_component" | "external_agent" | "context_config" | "team", better_auth_plugins0.Statements>;
866
+ } | undefined } : never, connector?: "OR" | "AND"): better_auth_plugins20.AuthorizeResponse;
867
+ statements: better_auth_plugins20.Subset<"project" | "organization" | "team" | "member" | "ac" | "invitation", better_auth_plugins20.Statements>;
868
868
  };
869
869
  };
870
870
  membershipLimit: number;
@@ -874,12 +874,42 @@ declare function createAuth(config: BetterAuthConfig): better_auth0.Auth<{
874
874
  id: string;
875
875
  role: string;
876
876
  email: string;
877
- organization: better_auth_plugins0.Organization;
878
- invitation: better_auth_plugins0.Invitation;
879
- inviter: better_auth_plugins0.Member & {
877
+ organization: better_auth_plugins20.Organization;
878
+ invitation: better_auth_plugins20.Invitation;
879
+ inviter: better_auth_plugins20.Member & {
880
880
  user: better_auth0.User;
881
881
  };
882
882
  }): Promise<void>;
883
+ organizationHooks: {
884
+ afterAcceptInvitation: ({
885
+ member,
886
+ user,
887
+ organization: org
888
+ }: {
889
+ invitation: better_auth_plugins20.Invitation & Record<string, any>;
890
+ member: better_auth_plugins20.Member & Record<string, any>;
891
+ user: better_auth0.User & Record<string, any>;
892
+ organization: better_auth_plugins20.Organization & Record<string, any>;
893
+ }) => Promise<void>;
894
+ afterUpdateMemberRole: ({
895
+ member,
896
+ organization: org,
897
+ previousRole
898
+ }: {
899
+ member: better_auth_plugins20.Member & Record<string, any>;
900
+ previousRole: string;
901
+ user: better_auth0.User & Record<string, any>;
902
+ organization: better_auth_plugins20.Organization & Record<string, any>;
903
+ }) => Promise<void>;
904
+ afterRemoveMember: ({
905
+ member,
906
+ organization: org
907
+ }: {
908
+ member: better_auth_plugins20.Member & Record<string, any>;
909
+ user: better_auth0.User & Record<string, any>;
910
+ organization: better_auth_plugins20.Organization & Record<string, any>;
911
+ }) => Promise<void>;
912
+ };
883
913
  }>;
884
914
  schema: {
885
915
  organization: {
@@ -1008,8 +1038,8 @@ declare function createAuth(config: BetterAuthConfig): better_auth0.Auth<{
1008
1038
  id: string;
1009
1039
  organizationId: string;
1010
1040
  email: string;
1011
- role: "member" | "admin" | "owner";
1012
- status: better_auth_plugins0.InvitationStatus;
1041
+ role: "member" | "owner" | "admin";
1042
+ status: better_auth_plugins20.InvitationStatus;
1013
1043
  inviterId: string;
1014
1044
  expiresAt: Date;
1015
1045
  createdAt: Date;
@@ -1017,7 +1047,7 @@ declare function createAuth(config: BetterAuthConfig): better_auth0.Auth<{
1017
1047
  Member: {
1018
1048
  id: string;
1019
1049
  organizationId: string;
1020
- role: "member" | "admin" | "owner";
1050
+ role: "member" | "owner" | "admin";
1021
1051
  createdAt: Date;
1022
1052
  userId: string;
1023
1053
  user: {
@@ -1033,7 +1063,7 @@ declare function createAuth(config: BetterAuthConfig): better_auth0.Auth<{
1033
1063
  members: {
1034
1064
  id: string;
1035
1065
  organizationId: string;
1036
- role: "member" | "admin" | "owner";
1066
+ role: "member" | "owner" | "admin";
1037
1067
  createdAt: Date;
1038
1068
  userId: string;
1039
1069
  user: {
@@ -1047,8 +1077,8 @@ declare function createAuth(config: BetterAuthConfig): better_auth0.Auth<{
1047
1077
  id: string;
1048
1078
  organizationId: string;
1049
1079
  email: string;
1050
- role: "member" | "admin" | "owner";
1051
- status: better_auth_plugins0.InvitationStatus;
1080
+ role: "member" | "owner" | "admin";
1081
+ status: better_auth_plugins20.InvitationStatus;
1052
1082
  inviterId: string;
1053
1083
  expiresAt: Date;
1054
1084
  createdAt: Date;
@@ -1122,28 +1152,28 @@ declare function createAuth(config: BetterAuthConfig): better_auth0.Auth<{
1122
1152
  };
1123
1153
  options: NoInfer<{
1124
1154
  allowUserToCreateOrganization: true;
1125
- ac: better_auth_plugins0.AccessControl;
1155
+ ac: better_auth_plugins20.AccessControl;
1126
1156
  roles: {
1127
1157
  member: {
1128
- authorize<K_1 extends "function" | "agent" | "organization" | "member" | "invitation" | "ac" | "project" | "sub_agent" | "tool" | "api_key" | "credential" | "data_component" | "artifact_component" | "external_agent" | "context_config" | "team">(request: K_1 extends infer T extends K ? { [key in T]?: better_auth_plugins0.Subset<"function" | "agent" | "organization" | "member" | "invitation" | "ac" | "project" | "sub_agent" | "tool" | "api_key" | "credential" | "data_component" | "artifact_component" | "external_agent" | "context_config" | "team", better_auth_plugins0.Statements>[key] | {
1129
- actions: better_auth_plugins0.Subset<"function" | "agent" | "organization" | "member" | "invitation" | "ac" | "project" | "sub_agent" | "tool" | "api_key" | "credential" | "data_component" | "artifact_component" | "external_agent" | "context_config" | "team", better_auth_plugins0.Statements>[key];
1158
+ authorize<K_1 extends "project" | "organization" | "team" | "member" | "ac" | "invitation">(request: K_1 extends infer T extends K ? { [key in T]?: better_auth_plugins20.Subset<"project" | "organization" | "team" | "member" | "ac" | "invitation", better_auth_plugins20.Statements>[key] | {
1159
+ actions: better_auth_plugins20.Subset<"project" | "organization" | "team" | "member" | "ac" | "invitation", better_auth_plugins20.Statements>[key];
1130
1160
  connector: "OR" | "AND";
1131
- } | undefined } : never, connector?: "OR" | "AND"): better_auth_plugins0.AuthorizeResponse;
1132
- statements: better_auth_plugins0.Subset<"function" | "agent" | "organization" | "member" | "invitation" | "ac" | "project" | "sub_agent" | "tool" | "api_key" | "credential" | "data_component" | "artifact_component" | "external_agent" | "context_config" | "team", better_auth_plugins0.Statements>;
1161
+ } | undefined } : never, connector?: "OR" | "AND"): better_auth_plugins20.AuthorizeResponse;
1162
+ statements: better_auth_plugins20.Subset<"project" | "organization" | "team" | "member" | "ac" | "invitation", better_auth_plugins20.Statements>;
1133
1163
  };
1134
1164
  admin: {
1135
- authorize<K_1 extends "function" | "agent" | "organization" | "member" | "invitation" | "ac" | "project" | "sub_agent" | "tool" | "api_key" | "credential" | "data_component" | "artifact_component" | "external_agent" | "context_config" | "team">(request: K_1 extends infer T extends K ? { [key in T]?: better_auth_plugins0.Subset<"function" | "agent" | "organization" | "member" | "invitation" | "ac" | "project" | "sub_agent" | "tool" | "api_key" | "credential" | "data_component" | "artifact_component" | "external_agent" | "context_config" | "team", better_auth_plugins0.Statements>[key] | {
1136
- actions: better_auth_plugins0.Subset<"function" | "agent" | "organization" | "member" | "invitation" | "ac" | "project" | "sub_agent" | "tool" | "api_key" | "credential" | "data_component" | "artifact_component" | "external_agent" | "context_config" | "team", better_auth_plugins0.Statements>[key];
1165
+ authorize<K_1 extends "project" | "organization" | "team" | "member" | "ac" | "invitation">(request: K_1 extends infer T extends K ? { [key in T]?: better_auth_plugins20.Subset<"project" | "organization" | "team" | "member" | "ac" | "invitation", better_auth_plugins20.Statements>[key] | {
1166
+ actions: better_auth_plugins20.Subset<"project" | "organization" | "team" | "member" | "ac" | "invitation", better_auth_plugins20.Statements>[key];
1137
1167
  connector: "OR" | "AND";
1138
- } | undefined } : never, connector?: "OR" | "AND"): better_auth_plugins0.AuthorizeResponse;
1139
- statements: better_auth_plugins0.Subset<"function" | "agent" | "organization" | "member" | "invitation" | "ac" | "project" | "sub_agent" | "tool" | "api_key" | "credential" | "data_component" | "artifact_component" | "external_agent" | "context_config" | "team", better_auth_plugins0.Statements>;
1168
+ } | undefined } : never, connector?: "OR" | "AND"): better_auth_plugins20.AuthorizeResponse;
1169
+ statements: better_auth_plugins20.Subset<"project" | "organization" | "team" | "member" | "ac" | "invitation", better_auth_plugins20.Statements>;
1140
1170
  };
1141
1171
  owner: {
1142
- authorize<K_1 extends "function" | "agent" | "organization" | "member" | "invitation" | "ac" | "project" | "sub_agent" | "tool" | "api_key" | "credential" | "data_component" | "artifact_component" | "external_agent" | "context_config" | "team">(request: K_1 extends infer T extends K ? { [key in T]?: better_auth_plugins0.Subset<"function" | "agent" | "organization" | "member" | "invitation" | "ac" | "project" | "sub_agent" | "tool" | "api_key" | "credential" | "data_component" | "artifact_component" | "external_agent" | "context_config" | "team", better_auth_plugins0.Statements>[key] | {
1143
- actions: better_auth_plugins0.Subset<"function" | "agent" | "organization" | "member" | "invitation" | "ac" | "project" | "sub_agent" | "tool" | "api_key" | "credential" | "data_component" | "artifact_component" | "external_agent" | "context_config" | "team", better_auth_plugins0.Statements>[key];
1172
+ authorize<K_1 extends "project" | "organization" | "team" | "member" | "ac" | "invitation">(request: K_1 extends infer T extends K ? { [key in T]?: better_auth_plugins20.Subset<"project" | "organization" | "team" | "member" | "ac" | "invitation", better_auth_plugins20.Statements>[key] | {
1173
+ actions: better_auth_plugins20.Subset<"project" | "organization" | "team" | "member" | "ac" | "invitation", better_auth_plugins20.Statements>[key];
1144
1174
  connector: "OR" | "AND";
1145
- } | undefined } : never, connector?: "OR" | "AND"): better_auth_plugins0.AuthorizeResponse;
1146
- statements: better_auth_plugins0.Subset<"function" | "agent" | "organization" | "member" | "invitation" | "ac" | "project" | "sub_agent" | "tool" | "api_key" | "credential" | "data_component" | "artifact_component" | "external_agent" | "context_config" | "team", better_auth_plugins0.Statements>;
1175
+ } | undefined } : never, connector?: "OR" | "AND"): better_auth_plugins20.AuthorizeResponse;
1176
+ statements: better_auth_plugins20.Subset<"project" | "organization" | "team" | "member" | "ac" | "invitation", better_auth_plugins20.Statements>;
1147
1177
  };
1148
1178
  };
1149
1179
  membershipLimit: number;
@@ -1153,12 +1183,42 @@ declare function createAuth(config: BetterAuthConfig): better_auth0.Auth<{
1153
1183
  id: string;
1154
1184
  role: string;
1155
1185
  email: string;
1156
- organization: better_auth_plugins0.Organization;
1157
- invitation: better_auth_plugins0.Invitation;
1158
- inviter: better_auth_plugins0.Member & {
1186
+ organization: better_auth_plugins20.Organization;
1187
+ invitation: better_auth_plugins20.Invitation;
1188
+ inviter: better_auth_plugins20.Member & {
1159
1189
  user: better_auth0.User;
1160
1190
  };
1161
1191
  }): Promise<void>;
1192
+ organizationHooks: {
1193
+ afterAcceptInvitation: ({
1194
+ member,
1195
+ user,
1196
+ organization: org
1197
+ }: {
1198
+ invitation: better_auth_plugins20.Invitation & Record<string, any>;
1199
+ member: better_auth_plugins20.Member & Record<string, any>;
1200
+ user: better_auth0.User & Record<string, any>;
1201
+ organization: better_auth_plugins20.Organization & Record<string, any>;
1202
+ }) => Promise<void>;
1203
+ afterUpdateMemberRole: ({
1204
+ member,
1205
+ organization: org,
1206
+ previousRole
1207
+ }: {
1208
+ member: better_auth_plugins20.Member & Record<string, any>;
1209
+ previousRole: string;
1210
+ user: better_auth0.User & Record<string, any>;
1211
+ organization: better_auth_plugins20.Organization & Record<string, any>;
1212
+ }) => Promise<void>;
1213
+ afterRemoveMember: ({
1214
+ member,
1215
+ organization: org
1216
+ }: {
1217
+ member: better_auth_plugins20.Member & Record<string, any>;
1218
+ user: better_auth0.User & Record<string, any>;
1219
+ organization: better_auth_plugins20.Organization & Record<string, any>;
1220
+ }) => Promise<void>;
1221
+ };
1162
1222
  }>;
1163
1223
  }, {
1164
1224
  id: "device-authorization";
@@ -1493,8 +1553,8 @@ declare function createAuth(config: BetterAuthConfig): better_auth0.Auth<{
1493
1553
  readonly AUTHENTICATION_REQUIRED: "Authentication required";
1494
1554
  };
1495
1555
  options: Partial<{
1496
- expiresIn: better_auth_plugins0.TimeString;
1497
- interval: better_auth_plugins0.TimeString;
1556
+ expiresIn: better_auth_plugins20.TimeString;
1557
+ interval: better_auth_plugins20.TimeString;
1498
1558
  deviceCodeLength: number;
1499
1559
  userCodeLength: number;
1500
1560
  schema: {
package/dist/auth/auth.js CHANGED
@@ -139,6 +139,52 @@ function createAuth(config) {
139
139
  organization: data.organization.name,
140
140
  invitationId: data.id
141
141
  });
142
+ },
143
+ organizationHooks: {
144
+ afterAcceptInvitation: async ({ member: member$1, user, organization: org }) => {
145
+ try {
146
+ const { syncOrgMemberToSpiceDb } = await import("./authz/sync.js");
147
+ await syncOrgMemberToSpiceDb({
148
+ tenantId: org.id,
149
+ userId: user.id,
150
+ role: member$1.role,
151
+ action: "add"
152
+ });
153
+ console.log(`🔐 SpiceDB: Synced member ${user.email} as ${member$1.role} to org ${org.name}`);
154
+ } catch (error) {
155
+ console.error("❌ SpiceDB sync failed for new member:", error);
156
+ }
157
+ },
158
+ afterUpdateMemberRole: async ({ member: member$1, organization: org, previousRole }) => {
159
+ try {
160
+ const { changeOrgRole } = await import("./authz/sync.js");
161
+ const oldRole = previousRole;
162
+ const newRole = member$1.role;
163
+ await changeOrgRole({
164
+ tenantId: org.id,
165
+ userId: member$1.userId,
166
+ oldRole,
167
+ newRole
168
+ });
169
+ console.log(`🔐 SpiceDB: Updated member ${member$1.userId} role from ${oldRole} to ${newRole} in org ${org.name}`);
170
+ } catch (error) {
171
+ console.error("❌ SpiceDB sync failed for role update:", error);
172
+ }
173
+ },
174
+ afterRemoveMember: async ({ member: member$1, organization: org }) => {
175
+ try {
176
+ const { syncOrgMemberToSpiceDb } = await import("./authz/sync.js");
177
+ await syncOrgMemberToSpiceDb({
178
+ tenantId: org.id,
179
+ userId: member$1.userId,
180
+ role: member$1.role,
181
+ action: "remove"
182
+ });
183
+ console.log(`🔐 SpiceDB: Removed member ${member$1.userId} from org ${org.name}`);
184
+ } catch (error) {
185
+ console.error("❌ SpiceDB sync failed for member removal:", error);
186
+ }
187
+ }
142
188
  }
143
189
  }),
144
190
  deviceAuthorization({
@@ -0,0 +1,81 @@
1
+ import { v1 } from "@authzed/authzed-node";
2
+
3
+ //#region src/auth/authz/client.d.ts
4
+
5
+ type ZedClientInterface = ReturnType<typeof v1.NewClient>;
6
+ /**
7
+ * Get the SpiceDB client singleton.
8
+ * Creates a new client on first call.
9
+ */
10
+ declare function getSpiceClient(): ZedClientInterface;
11
+ /**
12
+ * Reset the client (useful for testing)
13
+ */
14
+ declare function resetSpiceClient(): void;
15
+ /**
16
+ * Check if a subject has a permission on a resource.
17
+ * Note: Caller must verify isAuthzEnabled(tenantId) before calling.
18
+ */
19
+ declare function checkPermission(params: {
20
+ resourceType: string;
21
+ resourceId: string;
22
+ permission: string;
23
+ subjectType: string;
24
+ subjectId: string;
25
+ }): Promise<boolean>;
26
+ /**
27
+ * Check multiple permissions on a resource in a single request.
28
+ * More efficient than multiple checkPermission calls.
29
+ *
30
+ * @returns Record mapping permission names to boolean results
31
+ */
32
+ declare function checkBulkPermissions(params: {
33
+ resourceType: string;
34
+ resourceId: string;
35
+ permissions: string[];
36
+ subjectType: string;
37
+ subjectId: string;
38
+ }): Promise<Record<string, boolean>>;
39
+ /**
40
+ * Find all resources of a type that a subject has a permission on.
41
+ */
42
+ declare function lookupResources(params: {
43
+ resourceType: string;
44
+ permission: string;
45
+ subjectType: string;
46
+ subjectId: string;
47
+ }): Promise<string[]>;
48
+ /**
49
+ * Write a relationship to SpiceDB.
50
+ */
51
+ declare function writeRelationship(params: {
52
+ resourceType: string;
53
+ resourceId: string;
54
+ relation: string;
55
+ subjectType: string;
56
+ subjectId: string;
57
+ }): Promise<void>;
58
+ /**
59
+ * Delete a relationship from SpiceDB.
60
+ */
61
+ declare function deleteRelationship(params: {
62
+ resourceType: string;
63
+ resourceId: string;
64
+ relation: string;
65
+ subjectType: string;
66
+ subjectId: string;
67
+ }): Promise<void>;
68
+ /**
69
+ * Read relationships for a resource to list subjects with access.
70
+ */
71
+ declare function readRelationships(params: {
72
+ resourceType: string;
73
+ resourceId: string;
74
+ relation?: string;
75
+ }): Promise<Array<{
76
+ subjectType: string;
77
+ subjectId: string;
78
+ relation: string;
79
+ }>>;
80
+ //#endregion
81
+ export { checkBulkPermissions, checkPermission, deleteRelationship, getSpiceClient, lookupResources, readRelationships, resetSpiceClient, v1, writeRelationship };
@@ -0,0 +1,189 @@
1
+ import { getSpiceDbConfig } from "./config.js";
2
+ import { v1 } from "@authzed/authzed-node";
3
+
4
+ //#region src/auth/authz/client.ts
5
+ /**
6
+ * SpiceDB Client Wrapper
7
+ *
8
+ * Provides a singleton SpiceDB client and helper functions for common operations.
9
+ */
10
+ let client = null;
11
+ /**
12
+ * Get the SpiceDB client singleton.
13
+ * Creates a new client on first call.
14
+ */
15
+ function getSpiceClient() {
16
+ if (!client) {
17
+ const config = getSpiceDbConfig();
18
+ client = v1.NewClient(config.token, config.endpoint, config.tlsEnabled ? v1.ClientSecurity.SECURE : v1.ClientSecurity.INSECURE_LOCALHOST_ALLOWED);
19
+ }
20
+ return client;
21
+ }
22
+ /**
23
+ * Reset the client (useful for testing)
24
+ */
25
+ function resetSpiceClient() {
26
+ client = null;
27
+ }
28
+ const PERMISSIONSHIP_HAS_PERMISSION = 2;
29
+ const RELATIONSHIP_OPERATION_CREATE = 1;
30
+ /**
31
+ * Check if a subject has a permission on a resource.
32
+ * Note: Caller must verify isAuthzEnabled(tenantId) before calling.
33
+ */
34
+ async function checkPermission(params) {
35
+ return (await getSpiceClient().promises.checkPermission({
36
+ resource: {
37
+ objectType: params.resourceType,
38
+ objectId: params.resourceId
39
+ },
40
+ permission: params.permission,
41
+ subject: {
42
+ object: {
43
+ objectType: params.subjectType,
44
+ objectId: params.subjectId
45
+ },
46
+ optionalRelation: ""
47
+ },
48
+ consistency: { requirement: {
49
+ oneofKind: "minimizeLatency",
50
+ minimizeLatency: true
51
+ } },
52
+ context: void 0,
53
+ withTracing: false
54
+ })).permissionship === PERMISSIONSHIP_HAS_PERMISSION;
55
+ }
56
+ /**
57
+ * Check multiple permissions on a resource in a single request.
58
+ * More efficient than multiple checkPermission calls.
59
+ *
60
+ * @returns Record mapping permission names to boolean results
61
+ */
62
+ async function checkBulkPermissions(params) {
63
+ const spice = getSpiceClient();
64
+ const items = params.permissions.map((permission) => v1.CheckBulkPermissionsRequestItem.create({
65
+ resource: v1.ObjectReference.create({
66
+ objectType: params.resourceType,
67
+ objectId: params.resourceId
68
+ }),
69
+ permission,
70
+ subject: v1.SubjectReference.create({ object: v1.ObjectReference.create({
71
+ objectType: params.subjectType,
72
+ objectId: params.subjectId
73
+ }) })
74
+ }));
75
+ const response = await spice.promises.checkBulkPermissions(v1.CheckBulkPermissionsRequest.create({
76
+ items,
77
+ consistency: { requirement: {
78
+ oneofKind: "minimizeLatency",
79
+ minimizeLatency: true
80
+ } }
81
+ }));
82
+ const result = {};
83
+ for (let i = 0; i < params.permissions.length; i++) {
84
+ const permission = params.permissions[i];
85
+ const pair = response.pairs[i];
86
+ if (pair.response.oneofKind === "item") result[permission] = pair.response.item.permissionship === PERMISSIONSHIP_HAS_PERMISSION;
87
+ else result[permission] = false;
88
+ }
89
+ return result;
90
+ }
91
+ /**
92
+ * Find all resources of a type that a subject has a permission on.
93
+ */
94
+ async function lookupResources(params) {
95
+ return (await getSpiceClient().promises.lookupResources({
96
+ resourceObjectType: params.resourceType,
97
+ permission: params.permission,
98
+ subject: {
99
+ object: {
100
+ objectType: params.subjectType,
101
+ objectId: params.subjectId
102
+ },
103
+ optionalRelation: ""
104
+ },
105
+ consistency: { requirement: {
106
+ oneofKind: "minimizeLatency",
107
+ minimizeLatency: true
108
+ } },
109
+ context: void 0,
110
+ optionalLimit: 0,
111
+ optionalCursor: void 0
112
+ })).map((item) => item.resourceObjectId);
113
+ }
114
+ /**
115
+ * Write a relationship to SpiceDB.
116
+ */
117
+ async function writeRelationship(params) {
118
+ await getSpiceClient().promises.writeRelationships({
119
+ updates: [{
120
+ operation: RELATIONSHIP_OPERATION_CREATE,
121
+ relationship: {
122
+ resource: {
123
+ objectType: params.resourceType,
124
+ objectId: params.resourceId
125
+ },
126
+ relation: params.relation,
127
+ subject: {
128
+ object: {
129
+ objectType: params.subjectType,
130
+ objectId: params.subjectId
131
+ },
132
+ optionalRelation: ""
133
+ },
134
+ optionalCaveat: void 0
135
+ }
136
+ }],
137
+ optionalPreconditions: [],
138
+ optionalTransactionMetadata: void 0
139
+ });
140
+ }
141
+ /**
142
+ * Delete a relationship from SpiceDB.
143
+ */
144
+ async function deleteRelationship(params) {
145
+ await getSpiceClient().promises.deleteRelationships({
146
+ relationshipFilter: {
147
+ resourceType: params.resourceType,
148
+ optionalResourceId: params.resourceId,
149
+ optionalResourceIdPrefix: "",
150
+ optionalRelation: params.relation,
151
+ optionalSubjectFilter: {
152
+ subjectType: params.subjectType,
153
+ optionalSubjectId: params.subjectId,
154
+ optionalRelation: void 0
155
+ }
156
+ },
157
+ optionalPreconditions: [],
158
+ optionalLimit: 0,
159
+ optionalAllowPartialDeletions: false,
160
+ optionalTransactionMetadata: void 0
161
+ });
162
+ }
163
+ /**
164
+ * Read relationships for a resource to list subjects with access.
165
+ */
166
+ async function readRelationships(params) {
167
+ return (await getSpiceClient().promises.readRelationships({
168
+ relationshipFilter: {
169
+ resourceType: params.resourceType,
170
+ optionalResourceId: params.resourceId,
171
+ optionalResourceIdPrefix: "",
172
+ optionalRelation: params.relation || "",
173
+ optionalSubjectFilter: void 0
174
+ },
175
+ consistency: { requirement: {
176
+ oneofKind: "minimizeLatency",
177
+ minimizeLatency: true
178
+ } },
179
+ optionalLimit: 0,
180
+ optionalCursor: void 0
181
+ })).map((item) => ({
182
+ subjectType: item.relationship?.subject?.object?.objectType || "",
183
+ subjectId: item.relationship?.subject?.object?.objectId || "",
184
+ relation: item.relationship?.relation || ""
185
+ }));
186
+ }
187
+
188
+ //#endregion
189
+ export { checkBulkPermissions, checkPermission, deleteRelationship, getSpiceClient, lookupResources, readRelationships, resetSpiceClient, v1, writeRelationship };
@@ -0,0 +1,76 @@
1
+ //#region src/auth/authz/config.d.ts
2
+ /**
3
+ * SpiceDB Authorization Configuration
4
+ *
5
+ * Feature flag and configuration for the SpiceDB authorization system.
6
+ */
7
+ /**
8
+ * Check if authorization is enabled.
9
+ *
10
+ * When called without tenantId:
11
+ * - Returns true if ENABLE_AUTHZ=true
12
+ *
13
+ * When called with tenantId:
14
+ * - If ENABLE_AUTHZ=false → returns false
15
+ * - If ENABLE_AUTHZ=true and TENANT_ID is not set → returns true (all tenants)
16
+ * - If ENABLE_AUTHZ=true and TENANT_ID is set → returns true only if tenantId matches
17
+ */
18
+ declare function isAuthzEnabled(tenantId: string): boolean;
19
+ /**
20
+ * Get SpiceDB connection configuration from environment variables.
21
+ */
22
+ declare function getSpiceDbConfig(): {
23
+ endpoint: string;
24
+ token: string;
25
+ tlsEnabled: boolean;
26
+ };
27
+ /**
28
+ * SpiceDB resource types used in the schema
29
+ */
30
+ declare const SpiceDbResourceTypes: {
31
+ readonly USER: "user";
32
+ readonly ORGANIZATION: "organization";
33
+ readonly PROJECT: "project";
34
+ };
35
+ /**
36
+ * SpiceDB relations used in the schema
37
+ *
38
+ * Relations are named as nouns (roles) per SpiceDB best practices.
39
+ * Project roles are prefixed for clarity when debugging/grepping.
40
+ */
41
+ declare const SpiceDbRelations: {
42
+ readonly OWNER: "owner";
43
+ readonly ADMIN: "admin";
44
+ readonly MEMBER: "member";
45
+ readonly ORGANIZATION: "organization";
46
+ readonly PROJECT_ADMIN: "project_admin";
47
+ readonly PROJECT_MEMBER: "project_member";
48
+ readonly PROJECT_VIEWER: "project_viewer";
49
+ };
50
+ /**
51
+ * SpiceDB permissions used in the schema
52
+ *
53
+ * Permissions are named as verbs (actions) per SpiceDB best practices.
54
+ */
55
+ /**
56
+ * SpiceDB permissions used in permission checks.
57
+ *
58
+ * Note: Organization-level permissions (manage) are handled via
59
+ * orgRole bypass in permission functions, not direct SpiceDB checks.
60
+ */
61
+ declare const SpiceDbPermissions: {
62
+ readonly VIEW: "view";
63
+ readonly USE: "use";
64
+ readonly EDIT: "edit";
65
+ readonly DELETE: "delete";
66
+ };
67
+ type OrgRole = 'owner' | 'admin' | 'member';
68
+ /**
69
+ * Project roles hierarchy:
70
+ * - project_admin: Full access (view + use + edit + manage members + delete)
71
+ * - project_member: Operator access (view + use: invoke agents, create API keys)
72
+ * - project_viewer: Read-only access (view only)
73
+ */
74
+ type ProjectRole = 'project_admin' | 'project_member' | 'project_viewer';
75
+ //#endregion
76
+ export { OrgRole, ProjectRole, SpiceDbPermissions, SpiceDbRelations, SpiceDbResourceTypes, getSpiceDbConfig, isAuthzEnabled };