@inkeep/agents-manage-api 0.0.0-dev-20260118170655 → 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.
Files changed (44) hide show
  1. package/dist/data/db/dbClient.d.ts +2 -2
  2. package/dist/data/db/runDbClient.d.ts +2 -2
  3. package/dist/factory.d.ts +2 -2
  4. package/dist/index.d.ts +82 -22
  5. package/dist/middleware/auth.d.ts +2 -2
  6. package/dist/middleware/project-access.d.ts +31 -0
  7. package/dist/middleware/project-access.js +118 -0
  8. package/dist/middleware/require-permission.d.ts +2 -2
  9. package/dist/middleware/session-auth.d.ts +2 -2
  10. package/dist/middleware/tenant-access.d.ts +2 -2
  11. package/dist/routes/agent.js +4 -4
  12. package/dist/routes/agentFull.js +4 -4
  13. package/dist/routes/agentToolRelations.js +4 -4
  14. package/dist/routes/apiKeys.js +4 -4
  15. package/dist/routes/artifactComponents.js +4 -4
  16. package/dist/routes/contextConfigs.js +4 -4
  17. package/dist/routes/conversations.d.ts +2 -2
  18. package/dist/routes/credentialStores.d.ts +2 -2
  19. package/dist/routes/credentialStores.js +5 -0
  20. package/dist/routes/credentials.js +4 -4
  21. package/dist/routes/dataComponents.js +4 -4
  22. package/dist/routes/evals/evaluationResults.d.ts +2 -2
  23. package/dist/routes/externalAgents.js +4 -4
  24. package/dist/routes/functionTools.js +4 -4
  25. package/dist/routes/functions.js +4 -4
  26. package/dist/routes/index.d.ts +2 -2
  27. package/dist/routes/index.js +6 -0
  28. package/dist/routes/playgroundToken.js +18 -3
  29. package/dist/routes/projectFull.js +3 -2
  30. package/dist/routes/projectMembers.d.ts +9 -0
  31. package/dist/routes/projectMembers.js +201 -0
  32. package/dist/routes/projectPermissions.d.ts +9 -0
  33. package/dist/routes/projectPermissions.js +64 -0
  34. package/dist/routes/projects.js +38 -7
  35. package/dist/routes/subAgentArtifactComponents.js +3 -3
  36. package/dist/routes/subAgentDataComponents.js +3 -3
  37. package/dist/routes/subAgentExternalAgentRelations.js +4 -4
  38. package/dist/routes/subAgentFunctionTools.js +3 -3
  39. package/dist/routes/subAgentRelations.js +4 -4
  40. package/dist/routes/subAgentTeamAgentRelations.js +4 -4
  41. package/dist/routes/subAgentToolRelations.js +4 -4
  42. package/dist/routes/subAgents.js +4 -4
  43. package/dist/routes/tools.js +4 -4
  44. package/package.json +3 -3
@@ -1,4 +1,4 @@
1
- import { requirePermission } from "../middleware/require-permission.js";
1
+ import { requireProjectPermission } from "../middleware/project-access.js";
2
2
  import { speakeasyOffsetLimitPagination } from "./shared.js";
3
3
  import { OpenAPIHono, createRoute } from "@hono/zod-openapi";
4
4
  import { CredentialReferenceApiInsertSchema, CredentialReferenceApiSelectSchema, CredentialReferenceApiUpdateSchema, CredentialReferenceListResponse, CredentialReferenceResponse, ErrorResponseSchema, ListResponseSchema, PaginationQueryParamsSchema, TenantProjectIdParamsSchema, TenantProjectParamsSchema, commonGetErrorResponses, createApiError, createCredentialReference, deleteCredentialReference, getCredentialReferenceById, getCredentialReferenceWithResources, getCredentialStoreLookupKeyFromRetrievalParams, listCredentialReferencesPaginated, updateCredentialReference } from "@inkeep/agents-core";
@@ -6,12 +6,12 @@ import { CredentialReferenceApiInsertSchema, CredentialReferenceApiSelectSchema,
6
6
  //#region src/routes/credentials.ts
7
7
  const app = new OpenAPIHono();
8
8
  app.use("/", async (c, next) => {
9
- if (c.req.method === "POST") return requirePermission({ credential: ["create"] })(c, next);
9
+ if (c.req.method === "POST") return requireProjectPermission("edit")(c, next);
10
10
  return next();
11
11
  });
12
12
  app.use("/:id", async (c, next) => {
13
- if (c.req.method === "PATCH") return requirePermission({ credential: ["update"] })(c, next);
14
- if (c.req.method === "DELETE") return requirePermission({ credential: ["delete"] })(c, next);
13
+ if (c.req.method === "PATCH") return requireProjectPermission("edit")(c, next);
14
+ if (c.req.method === "DELETE") return requireProjectPermission("edit")(c, next);
15
15
  return next();
16
16
  });
17
17
  app.openapi(createRoute({
@@ -1,4 +1,4 @@
1
- import { requirePermission } from "../middleware/require-permission.js";
1
+ import { requireProjectPermission } from "../middleware/project-access.js";
2
2
  import { speakeasyOffsetLimitPagination } from "./shared.js";
3
3
  import { OpenAPIHono, createRoute } from "@hono/zod-openapi";
4
4
  import { DataComponentApiInsertSchema, DataComponentApiUpdateSchema, DataComponentListResponse, DataComponentResponse, ErrorResponseSchema, PaginationQueryParamsSchema, TenantProjectIdParamsSchema, TenantProjectParamsSchema, commonGetErrorResponses, createApiError, createDataComponent, deleteDataComponent, getDataComponent, listDataComponentsPaginated, updateDataComponent, validatePropsAsJsonSchema } from "@inkeep/agents-core";
@@ -6,12 +6,12 @@ import { DataComponentApiInsertSchema, DataComponentApiUpdateSchema, DataCompone
6
6
  //#region src/routes/dataComponents.ts
7
7
  const app = new OpenAPIHono();
8
8
  app.use("/", async (c, next) => {
9
- if (c.req.method === "POST") return requirePermission({ data_component: ["create"] })(c, next);
9
+ if (c.req.method === "POST") return requireProjectPermission("edit")(c, next);
10
10
  return next();
11
11
  });
12
12
  app.use("/:id", async (c, next) => {
13
- if (c.req.method === "PATCH") return requirePermission({ data_component: ["update"] })(c, next);
14
- if (c.req.method === "DELETE") return requirePermission({ data_component: ["delete"] })(c, next);
13
+ if (c.req.method === "PATCH") return requireProjectPermission("edit")(c, next);
14
+ if (c.req.method === "DELETE") return requireProjectPermission("edit")(c, next);
15
15
  return next();
16
16
  });
17
17
  app.openapi(createRoute({
@@ -1,7 +1,7 @@
1
1
  import { OpenAPIHono } from "@hono/zod-openapi";
2
- import * as hono6 from "hono";
2
+ import * as hono7 from "hono";
3
3
 
4
4
  //#region src/routes/evals/evaluationResults.d.ts
5
- declare const app: OpenAPIHono<hono6.Env, {}, "/">;
5
+ declare const app: OpenAPIHono<hono7.Env, {}, "/">;
6
6
  //#endregion
7
7
  export { app as default };
@@ -1,4 +1,4 @@
1
- import { requirePermission } from "../middleware/require-permission.js";
1
+ import { requireProjectPermission } from "../middleware/project-access.js";
2
2
  import { speakeasyOffsetLimitPagination } from "./shared.js";
3
3
  import { OpenAPIHono, createRoute } from "@hono/zod-openapi";
4
4
  import { ErrorResponseSchema, ExternalAgentApiInsertSchema, ExternalAgentApiUpdateSchema, ExternalAgentListResponse, ExternalAgentResponse, PaginationQueryParamsSchema, TenantProjectIdParamsSchema, TenantProjectParamsSchema, commonGetErrorResponses, createApiError, createExternalAgent, deleteExternalAgent, generateId, getExternalAgent, listExternalAgentsPaginated, updateExternalAgent } from "@inkeep/agents-core";
@@ -6,12 +6,12 @@ import { ErrorResponseSchema, ExternalAgentApiInsertSchema, ExternalAgentApiUpda
6
6
  //#region src/routes/externalAgents.ts
7
7
  const app = new OpenAPIHono();
8
8
  app.use("/", async (c, next) => {
9
- if (c.req.method === "POST") return requirePermission({ external_agent: ["create"] })(c, next);
9
+ if (c.req.method === "POST") return requireProjectPermission("edit")(c, next);
10
10
  return next();
11
11
  });
12
12
  app.use("/:id", async (c, next) => {
13
- if (c.req.method === "PATCH") return requirePermission({ external_agent: ["update"] })(c, next);
14
- if (c.req.method === "DELETE") return requirePermission({ external_agent: ["delete"] })(c, next);
13
+ if (c.req.method === "PATCH") return requireProjectPermission("edit")(c, next);
14
+ if (c.req.method === "DELETE") return requireProjectPermission("edit")(c, next);
15
15
  return next();
16
16
  });
17
17
  app.openapi(createRoute({
@@ -1,5 +1,5 @@
1
1
  import { getLogger as getLogger$1 } from "../logger.js";
2
- import { requirePermission } from "../middleware/require-permission.js";
2
+ import { requireProjectPermission } from "../middleware/project-access.js";
3
3
  import { speakeasyOffsetLimitPagination } from "./shared.js";
4
4
  import { OpenAPIHono, createRoute } from "@hono/zod-openapi";
5
5
  import { FunctionToolApiInsertSchema, FunctionToolApiUpdateSchema, FunctionToolListResponse, FunctionToolResponse, PaginationQueryParamsSchema, TenantProjectAgentIdParamsSchema, TenantProjectAgentParamsSchema, commonGetErrorResponses, createApiError, createFunctionTool, deleteFunctionTool, generateId, getFunctionToolById, listFunctionTools, updateFunctionTool } from "@inkeep/agents-core";
@@ -8,12 +8,12 @@ import { FunctionToolApiInsertSchema, FunctionToolApiUpdateSchema, FunctionToolL
8
8
  const logger = getLogger$1("functionTools");
9
9
  const app = new OpenAPIHono();
10
10
  app.use("/", async (c, next) => {
11
- if (c.req.method === "POST") return requirePermission({ function: ["create"] })(c, next);
11
+ if (c.req.method === "POST") return requireProjectPermission("edit")(c, next);
12
12
  return next();
13
13
  });
14
14
  app.use("/:id", async (c, next) => {
15
- if (c.req.method === "PUT") return requirePermission({ function: ["update"] })(c, next);
16
- if (c.req.method === "DELETE") return requirePermission({ function: ["delete"] })(c, next);
15
+ if (c.req.method === "PUT") return requireProjectPermission("edit")(c, next);
16
+ if (c.req.method === "DELETE") return requireProjectPermission("edit")(c, next);
17
17
  return next();
18
18
  });
19
19
  app.openapi(createRoute({
@@ -1,5 +1,5 @@
1
1
  import { getLogger as getLogger$1 } from "../logger.js";
2
- import { requirePermission } from "../middleware/require-permission.js";
2
+ import { requireProjectPermission } from "../middleware/project-access.js";
3
3
  import { speakeasyOffsetLimitPagination } from "./shared.js";
4
4
  import { OpenAPIHono, createRoute } from "@hono/zod-openapi";
5
5
  import { FunctionApiInsertSchema, FunctionApiUpdateSchema, FunctionListResponse, FunctionResponse, PaginationQueryParamsSchema, TenantProjectIdParamsSchema, TenantProjectParamsSchema, commonGetErrorResponses, createApiError, deleteFunction, generateId, getFunction, listFunctionsPaginated, upsertFunction } from "@inkeep/agents-core";
@@ -8,12 +8,12 @@ import { FunctionApiInsertSchema, FunctionApiUpdateSchema, FunctionListResponse,
8
8
  const logger = getLogger$1("functions");
9
9
  const app = new OpenAPIHono();
10
10
  app.use("/", async (c, next) => {
11
- if (c.req.method === "POST") return requirePermission({ function: ["create"] })(c, next);
11
+ if (c.req.method === "POST") return requireProjectPermission("edit")(c, next);
12
12
  return next();
13
13
  });
14
14
  app.use("/:id", async (c, next) => {
15
- if (c.req.method === "PUT") return requirePermission({ function: ["update"] })(c, next);
16
- if (c.req.method === "DELETE") return requirePermission({ function: ["delete"] })(c, next);
15
+ if (c.req.method === "PUT") return requireProjectPermission("edit")(c, next);
16
+ if (c.req.method === "DELETE") return requireProjectPermission("edit")(c, next);
17
17
  return next();
18
18
  });
19
19
  app.openapi(createRoute({
@@ -1,7 +1,7 @@
1
1
  import { OpenAPIHono } from "@hono/zod-openapi";
2
- import * as hono4 from "hono";
2
+ import * as hono5 from "hono";
3
3
 
4
4
  //#region src/routes/index.d.ts
5
- declare const app: OpenAPIHono<hono4.Env, {}, "/">;
5
+ declare const app: OpenAPIHono<hono5.Env, {}, "/">;
6
6
  //#endregion
7
7
  export { app as default };
@@ -1,3 +1,4 @@
1
+ import { requireProjectPermission } from "../middleware/project-access.js";
1
2
  import agent_default from "./agent.js";
2
3
  import agentFull_default from "./agentFull.js";
3
4
  import apiKeys_default from "./apiKeys.js";
@@ -12,6 +13,8 @@ import externalAgents_default from "./externalAgents.js";
12
13
  import functions_default from "./functions.js";
13
14
  import functionTools_default from "./functionTools.js";
14
15
  import mcpCatalog_default from "./mcpCatalog.js";
16
+ import projectMembers_default from "./projectMembers.js";
17
+ import projectPermissions_default from "./projectPermissions.js";
15
18
  import projects_default from "./projects.js";
16
19
  import ref_default from "./ref.js";
17
20
  import subAgentArtifactComponents_default from "./subAgentArtifactComponents.js";
@@ -29,8 +32,11 @@ import { OpenAPIHono } from "@hono/zod-openapi";
29
32
  //#region src/routes/index.ts
30
33
  const app = new OpenAPIHono();
31
34
  app.route("/projects", projects_default);
35
+ app.use("/projects/:projectId/*", requireProjectPermission("view"));
32
36
  app.route("/projects/:projectId/branches", branches_default);
33
37
  app.route("/projects/:projectId/refs", ref_default);
38
+ app.route("/projects/:projectId/members", projectMembers_default);
39
+ app.route("/projects/:projectId/permissions", projectPermissions_default);
34
40
  app.route("/projects/:projectId/agents/:agentId/sub-agents", subAgents_default);
35
41
  app.route("/projects/:projectId/agents/:agentId/sub-agent-relations", subAgentRelations_default);
36
42
  app.route("/projects/:projectId/agents/:agentId/sub-agents/:subAgentId/external-agent-relations", subAgentExternalAgentRelations_default);
@@ -1,13 +1,11 @@
1
1
  import { env } from "../env.js";
2
2
  import { getLogger as getLogger$1 } from "../logger.js";
3
- import { requirePermission } from "../middleware/require-permission.js";
4
3
  import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
5
- import { ErrorResponseSchema, TenantParamsSchema, createApiError, getAgentById, projectExists, signTempToken } from "@inkeep/agents-core";
4
+ import { ErrorResponseSchema, TenantParamsSchema, canUseProject, createApiError, getAgentById, projectExists, signTempToken } from "@inkeep/agents-core";
6
5
 
7
6
  //#region src/routes/playgroundToken.ts
8
7
  const logger = getLogger$1("playgroundToken");
9
8
  const app = new OpenAPIHono();
10
- app.use("/", requirePermission({ agent: ["create"] }));
11
9
  const PlaygroundTokenRequestSchema = z.object({
12
10
  projectId: z.string(),
13
11
  agentId: z.string()
@@ -42,6 +40,7 @@ app.openapi(createRoute({
42
40
  const db = c.get("db");
43
41
  const userId = c.get("userId");
44
42
  const tenantId = c.get("tenantId");
43
+ const tenantRole = c.get("tenantRole") || "member";
45
44
  const { projectId, agentId } = c.req.valid("json");
46
45
  logger.info({
47
46
  userId,
@@ -49,6 +48,22 @@ app.openapi(createRoute({
49
48
  projectId,
50
49
  agentId
51
50
  }, "Generating temporary JWT token for playground");
51
+ if (!await canUseProject({
52
+ tenantId,
53
+ userId,
54
+ projectId,
55
+ orgRole: tenantRole
56
+ })) {
57
+ logger.warn({
58
+ userId,
59
+ tenantId,
60
+ projectId
61
+ }, "User does not have use permission on project");
62
+ throw createApiError({
63
+ code: "not_found",
64
+ message: "Project not found"
65
+ });
66
+ }
52
67
  if (!await projectExists(db)({
53
68
  tenantId,
54
69
  projectId
@@ -1,6 +1,7 @@
1
1
  import { getLogger as getLogger$1 } from "../logger.js";
2
2
  import runDbClient_default from "../data/db/runDbClient.js";
3
3
  import dbClient_default from "../data/db/dbClient.js";
4
+ import { requireProjectPermission } from "../middleware/project-access.js";
4
5
  import { requirePermission } from "../middleware/require-permission.js";
5
6
  import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
6
7
  import { ErrorResponseSchema, FullProjectDefinitionSchema, FullProjectSelectResponse, FullProjectSelectWithRelationIdsResponse, TenantParamsSchema, TenantProjectParamsSchema, cascadeDeleteByProject, checkoutBranch, commonGetErrorResponses, createApiError, createFullProjectServerSide, createProjectMetadataAndBranch, deleteFullProject, deleteProjectWithBranch, doltCheckout, getFullProject, getFullProjectWithRelationIds, getProjectMainBranchName, getProjectMetadata, updateFullProjectServerSide } from "@inkeep/agents-core";
@@ -13,8 +14,8 @@ app.use("/project-full", async (c, next) => {
13
14
  return next();
14
15
  });
15
16
  app.use("/project-full/:projectId", async (c, next) => {
16
- if (c.req.method === "PUT") return requirePermission({ project: ["update"] })(c, next);
17
- if (c.req.method === "DELETE") return requirePermission({ project: ["delete"] })(c, next);
17
+ if (c.req.method === "PUT") return requireProjectPermission("edit")(c, next);
18
+ if (c.req.method === "DELETE") return requireProjectPermission("edit")(c, next);
18
19
  return next();
19
20
  });
20
21
  app.openapi(createRoute({
@@ -0,0 +1,9 @@
1
+ import { BaseAppVariables } from "../types/app.js";
2
+ import { OpenAPIHono } from "@hono/zod-openapi";
3
+
4
+ //#region src/routes/projectMembers.d.ts
5
+ declare const app: OpenAPIHono<{
6
+ Variables: BaseAppVariables;
7
+ }, {}, "/">;
8
+ //#endregion
9
+ export { app as default };
@@ -0,0 +1,201 @@
1
+ import { requireProjectPermission } from "../middleware/project-access.js";
2
+ import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
3
+ import { changeProjectRole, commonGetErrorResponses, createApiError, grantProjectAccess, isAuthzEnabled, listProjectMembers, revokeProjectAccess } from "@inkeep/agents-core";
4
+
5
+ //#region src/routes/projectMembers.ts
6
+ const app = new OpenAPIHono();
7
+ const ProjectMemberSchema = z.object({
8
+ userId: z.string().min(1),
9
+ role: z.enum([
10
+ "project_admin",
11
+ "project_member",
12
+ "project_viewer"
13
+ ])
14
+ });
15
+ const ProjectMemberResponseSchema = z.object({ data: z.object({
16
+ userId: z.string(),
17
+ role: z.enum([
18
+ "project_admin",
19
+ "project_member",
20
+ "project_viewer"
21
+ ]),
22
+ projectId: z.string()
23
+ }) });
24
+ const ProjectMemberParamsSchema = z.object({
25
+ tenantId: z.string(),
26
+ projectId: z.string()
27
+ });
28
+ const ProjectMemberUserParamsSchema = z.object({
29
+ tenantId: z.string(),
30
+ projectId: z.string(),
31
+ userId: z.string()
32
+ });
33
+ const UpdateRoleSchema = z.object({
34
+ role: z.enum([
35
+ "project_admin",
36
+ "project_member",
37
+ "project_viewer"
38
+ ]),
39
+ previousRole: z.enum([
40
+ "project_admin",
41
+ "project_member",
42
+ "project_viewer"
43
+ ]).optional()
44
+ });
45
+ app.openapi(createRoute({
46
+ method: "get",
47
+ path: "/",
48
+ summary: "List Project Members",
49
+ description: "List all users with explicit project access. Requires authz to be enabled.",
50
+ operationId: "list-project-members",
51
+ tags: ["Project Members"],
52
+ request: { params: ProjectMemberParamsSchema },
53
+ responses: {
54
+ 200: {
55
+ description: "List of project members",
56
+ content: { "application/json": { schema: z.object({ data: z.array(z.object({
57
+ userId: z.string(),
58
+ role: z.enum([
59
+ "project_admin",
60
+ "project_member",
61
+ "project_viewer"
62
+ ])
63
+ })) }) } }
64
+ },
65
+ ...commonGetErrorResponses
66
+ }
67
+ }), async (c) => {
68
+ const { projectId, tenantId } = c.req.valid("param");
69
+ if (!isAuthzEnabled(tenantId)) return c.json({ data: [] });
70
+ const members = await listProjectMembers({
71
+ tenantId,
72
+ projectId
73
+ });
74
+ return c.json({ data: members });
75
+ });
76
+ app.use("/*", async (c, next) => {
77
+ if (c.req.method === "GET") return next();
78
+ return requireProjectPermission("edit")(c, next);
79
+ });
80
+ app.openapi(createRoute({
81
+ method: "post",
82
+ path: "/",
83
+ summary: "Add Project Member",
84
+ description: "Add a user to a project with a specified role. Requires authz to be enabled.",
85
+ operationId: "add-project-member",
86
+ tags: ["Project Members"],
87
+ request: {
88
+ params: ProjectMemberParamsSchema,
89
+ body: { content: { "application/json": { schema: ProjectMemberSchema } } }
90
+ },
91
+ responses: {
92
+ 201: {
93
+ description: "Member added successfully",
94
+ content: { "application/json": { schema: ProjectMemberResponseSchema } }
95
+ },
96
+ ...commonGetErrorResponses
97
+ }
98
+ }), async (c) => {
99
+ const { projectId, tenantId } = c.req.valid("param");
100
+ const { userId, role } = c.req.valid("json");
101
+ if (!isAuthzEnabled(tenantId)) throw createApiError({
102
+ code: "bad_request",
103
+ message: "Project member management requires authorization to be enabled (ENABLE_AUTHZ=true)"
104
+ });
105
+ await grantProjectAccess({
106
+ tenantId,
107
+ projectId,
108
+ userId,
109
+ role
110
+ });
111
+ return c.json({ data: {
112
+ userId,
113
+ role,
114
+ projectId
115
+ } }, 201);
116
+ });
117
+ app.openapi(createRoute({
118
+ method: "patch",
119
+ path: "/{userId}",
120
+ summary: "Update Project Member Role",
121
+ description: "Update a project member's role. Requires authz to be enabled. Include previousRole to specify which role to revoke.",
122
+ operationId: "update-project-member",
123
+ tags: ["Project Members"],
124
+ request: {
125
+ params: ProjectMemberUserParamsSchema,
126
+ body: { content: { "application/json": { schema: UpdateRoleSchema } } }
127
+ },
128
+ responses: {
129
+ 200: {
130
+ description: "Member role updated successfully",
131
+ content: { "application/json": { schema: ProjectMemberResponseSchema } }
132
+ },
133
+ ...commonGetErrorResponses
134
+ }
135
+ }), async (c) => {
136
+ const { projectId, userId, tenantId } = c.req.valid("param");
137
+ const { role: newRole, previousRole } = c.req.valid("json");
138
+ if (!isAuthzEnabled(tenantId)) throw createApiError({
139
+ code: "bad_request",
140
+ message: "Project member management requires authorization to be enabled (ENABLE_AUTHZ=true)"
141
+ });
142
+ if (!previousRole) throw createApiError({
143
+ code: "bad_request",
144
+ message: "previousRole is required to update a member role"
145
+ });
146
+ if (previousRole === newRole) return c.json({ data: {
147
+ userId,
148
+ role: newRole,
149
+ projectId
150
+ } });
151
+ await changeProjectRole({
152
+ tenantId,
153
+ projectId,
154
+ userId,
155
+ oldRole: previousRole,
156
+ newRole
157
+ });
158
+ return c.json({ data: {
159
+ userId,
160
+ role: newRole,
161
+ projectId
162
+ } });
163
+ });
164
+ app.openapi(createRoute({
165
+ method: "delete",
166
+ path: "/{userId}",
167
+ summary: "Remove Project Member",
168
+ description: "Remove a user from a project. Requires authz to be enabled. Pass role as query param to specify which role to revoke.",
169
+ operationId: "remove-project-member",
170
+ tags: ["Project Members"],
171
+ request: {
172
+ params: ProjectMemberUserParamsSchema,
173
+ query: z.object({ role: z.enum([
174
+ "project_admin",
175
+ "project_member",
176
+ "project_viewer"
177
+ ]) })
178
+ },
179
+ responses: {
180
+ 204: { description: "Member removed successfully" },
181
+ ...commonGetErrorResponses
182
+ }
183
+ }), async (c) => {
184
+ const { projectId, userId, tenantId } = c.req.valid("param");
185
+ const { role } = c.req.valid("query");
186
+ if (!isAuthzEnabled(tenantId)) throw createApiError({
187
+ code: "bad_request",
188
+ message: "Project member management requires authorization to be enabled (ENABLE_AUTHZ=true)"
189
+ });
190
+ await revokeProjectAccess({
191
+ tenantId,
192
+ projectId,
193
+ userId,
194
+ role
195
+ });
196
+ return c.body(null, 204);
197
+ });
198
+ var projectMembers_default = app;
199
+
200
+ //#endregion
201
+ export { projectMembers_default as default };
@@ -0,0 +1,9 @@
1
+ import { BaseAppVariables } from "../types/app.js";
2
+ import { OpenAPIHono } from "@hono/zod-openapi";
3
+
4
+ //#region src/routes/projectPermissions.d.ts
5
+ declare const app: OpenAPIHono<{
6
+ Variables: BaseAppVariables;
7
+ }, {}, "/">;
8
+ //#endregion
9
+ export { app as default };
@@ -0,0 +1,64 @@
1
+ import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
2
+ import { SpiceDbPermissions, SpiceDbResourceTypes, checkBulkPermissions, commonGetErrorResponses, isAuthzEnabled } from "@inkeep/agents-core";
3
+
4
+ //#region src/routes/projectPermissions.ts
5
+ const app = new OpenAPIHono();
6
+ const ProjectPermissionsParamsSchema = z.object({
7
+ tenantId: z.string(),
8
+ projectId: z.string()
9
+ });
10
+ const ProjectPermissionsResponseSchema = z.object({ data: z.object({
11
+ canView: z.boolean(),
12
+ canUse: z.boolean(),
13
+ canEdit: z.boolean()
14
+ }) });
15
+ app.openapi(createRoute({
16
+ method: "get",
17
+ path: "/",
18
+ summary: "Get Project Permissions",
19
+ description: "Get the current user's permissions for a project. Returns which actions the user can perform.",
20
+ operationId: "get-project-permissions",
21
+ tags: ["Project Permissions"],
22
+ request: { params: ProjectPermissionsParamsSchema },
23
+ responses: {
24
+ 200: {
25
+ description: "Project permissions for the current user",
26
+ content: { "application/json": { schema: ProjectPermissionsResponseSchema } }
27
+ },
28
+ ...commonGetErrorResponses
29
+ }
30
+ }), async (c) => {
31
+ const { projectId, tenantId } = c.req.valid("param");
32
+ const userId = c.get("userId");
33
+ const tenantRole = c.get("tenantRole");
34
+ if (tenantRole === "owner" || tenantRole === "admin") return c.json({ data: {
35
+ canView: true,
36
+ canUse: true,
37
+ canEdit: true
38
+ } });
39
+ if (!isAuthzEnabled(tenantId)) return c.json({ data: {
40
+ canView: true,
41
+ canUse: true,
42
+ canEdit: false
43
+ } });
44
+ const permissions = await checkBulkPermissions({
45
+ resourceType: SpiceDbResourceTypes.PROJECT,
46
+ resourceId: projectId,
47
+ permissions: [
48
+ SpiceDbPermissions.VIEW,
49
+ SpiceDbPermissions.USE,
50
+ SpiceDbPermissions.EDIT
51
+ ],
52
+ subjectType: SpiceDbResourceTypes.USER,
53
+ subjectId: userId
54
+ });
55
+ return c.json({ data: {
56
+ canView: permissions[SpiceDbPermissions.VIEW] ?? false,
57
+ canUse: permissions[SpiceDbPermissions.USE] ?? false,
58
+ canEdit: permissions[SpiceDbPermissions.EDIT] ?? false
59
+ } });
60
+ });
61
+ var projectPermissions_default = app;
62
+
63
+ //#endregion
64
+ export { projectPermissions_default as default };
@@ -1,9 +1,10 @@
1
1
  import runDbClient_default from "../data/db/runDbClient.js";
2
2
  import dbClient_default from "../data/db/dbClient.js";
3
- import { requirePermission } from "../middleware/require-permission.js";
3
+ import { requireProjectPermission } from "../middleware/project-access.js";
4
4
  import { speakeasyOffsetLimitPagination } from "./shared.js";
5
+ import { requirePermission } from "../middleware/require-permission.js";
5
6
  import { OpenAPIHono, createRoute } from "@hono/zod-openapi";
6
- import { ErrorResponseSchema, PaginationQueryParamsSchema, ProjectApiInsertSchema, ProjectApiUpdateSchema, ProjectListResponse, ProjectResponse, TenantIdParamsSchema, TenantParamsSchema, cascadeDeleteByProject, commonGetErrorResponses, createApiError, createProject, createProjectMetadataAndBranch, deleteProject, deleteProjectWithBranch, doltCheckout, getProject, getProjectMainBranchName, listProjectsWithMetadataPaginated, updateProject } from "@inkeep/agents-core";
7
+ import { ErrorResponseSchema, PaginationQueryParamsSchema, ProjectApiInsertSchema, ProjectApiUpdateSchema, ProjectListResponse, ProjectResponse, TenantIdParamsSchema, TenantParamsSchema, cascadeDeleteByProject, commonGetErrorResponses, createApiError, createProject, createProjectMetadataAndBranch, deleteProject, deleteProjectWithBranch, doltCheckout, getProject, getProjectMainBranchName, isAuthzEnabled, listAccessibleProjectIds, listProjectsWithMetadataPaginated, removeProjectFromSpiceDb, syncProjectToSpiceDb, updateProject } from "@inkeep/agents-core";
7
8
 
8
9
  //#region src/routes/projects.ts
9
10
  const app = new OpenAPIHono();
@@ -12,15 +13,16 @@ app.use("/", async (c, next) => {
12
13
  return next();
13
14
  });
14
15
  app.use("/:id", async (c, next) => {
15
- if (c.req.method === "PATCH") return requirePermission({ project: ["update"] })(c, next);
16
- if (c.req.method === "DELETE") return requirePermission({ project: ["delete"] })(c, next);
16
+ if (c.req.method === "GET") return requireProjectPermission("view")(c, next);
17
+ if (c.req.method === "PATCH") return requireProjectPermission("edit")(c, next);
18
+ if (c.req.method === "DELETE") return requireProjectPermission("edit")(c, next);
17
19
  return next();
18
20
  });
19
21
  app.openapi(createRoute({
20
22
  method: "get",
21
23
  path: "/",
22
24
  summary: "List Projects",
23
- description: "List all projects within a tenant with pagination",
25
+ description: "List all projects within a tenant with pagination. When authorization is enabled, only returns projects the user has access to.",
24
26
  operationId: "list-projects",
25
27
  tags: ["Projects"],
26
28
  request: {
@@ -38,14 +40,26 @@ app.openapi(createRoute({
38
40
  }), async (c) => {
39
41
  const configDb = c.get("db");
40
42
  const { tenantId } = c.req.valid("param");
43
+ const userId = c.get("userId");
44
+ const tenantRole = c.get("tenantRole") || "member";
41
45
  const page = Number(c.req.query("page")) || 1;
42
46
  const limit = Math.min(Number(c.req.query("limit")) || 10, 100);
47
+ let accessibleIds;
48
+ if (isAuthzEnabled(tenantId) && userId) {
49
+ const result$1 = await listAccessibleProjectIds({
50
+ tenantId,
51
+ userId,
52
+ orgRole: tenantRole
53
+ });
54
+ if (result$1 !== "all") accessibleIds = result$1;
55
+ }
43
56
  const result = await listProjectsWithMetadataPaginated(runDbClient_default, configDb)({
44
57
  tenantId,
45
58
  pagination: {
46
59
  page,
47
60
  limit
48
- }
61
+ },
62
+ projectIds: accessibleIds
49
63
  });
50
64
  const transformedData = result.data.map((project) => ({
51
65
  id: project.id,
@@ -94,7 +108,7 @@ app.openapi(createRoute({
94
108
  method: "post",
95
109
  path: "/",
96
110
  summary: "Create Project",
97
- description: "Create a new project",
111
+ description: "Create a new project. When authorization is enabled, the creator is automatically granted admin role.",
98
112
  operationId: "create-project",
99
113
  tags: ["Projects"],
100
114
  request: {
@@ -135,6 +149,15 @@ app.openapi(createRoute({
135
149
  tenantId,
136
150
  ...body
137
151
  });
152
+ if (isAuthzEnabled(tenantId)) try {
153
+ await syncProjectToSpiceDb({
154
+ tenantId,
155
+ projectId: body.id,
156
+ creatorUserId: userId
157
+ });
158
+ } catch (syncError) {
159
+ console.warn("Failed to sync project to SpiceDB:", syncError);
160
+ }
138
161
  return c.json({ data: {
139
162
  ...projectConfig,
140
163
  mainBranchName: runtimeProject.mainBranchName
@@ -227,6 +250,14 @@ app.openapi(createRoute({
227
250
  code: "not_found",
228
251
  message: "Project not found"
229
252
  });
253
+ if (isAuthzEnabled(tenantId)) try {
254
+ await removeProjectFromSpiceDb({
255
+ tenantId,
256
+ projectId: id
257
+ });
258
+ } catch (syncError) {
259
+ console.warn("Failed to remove project from SpiceDB:", syncError);
260
+ }
230
261
  return c.body(null, 204);
231
262
  } catch (error) {
232
263
  if (error.message?.includes("Cannot delete project with existing resources")) throw createApiError({
@@ -1,15 +1,15 @@
1
- import { requirePermission } from "../middleware/require-permission.js";
1
+ import { requireProjectPermission } from "../middleware/project-access.js";
2
2
  import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
3
3
  import { ArtifactComponentArrayResponse, ComponentAssociationListResponse, ErrorResponseSchema, ExistsResponseSchema, RemovedResponseSchema, SubAgentArtifactComponentApiInsertSchema, SubAgentArtifactComponentResponse, TenantProjectAgentParamsSchema, TenantProjectAgentSubAgentParamsSchema, associateArtifactComponentWithAgent, commonGetErrorResponses, createApiError, getAgentsUsingArtifactComponent, getArtifactComponentById, getArtifactComponentsForAgent, getSubAgentById, isArtifactComponentAssociatedWithAgent, removeArtifactComponentFromAgent } from "@inkeep/agents-core";
4
4
 
5
5
  //#region src/routes/subAgentArtifactComponents.ts
6
6
  const app = new OpenAPIHono();
7
7
  app.use("/", async (c, next) => {
8
- if (c.req.method === "POST") return requirePermission({ sub_agent: ["create"] })(c, next);
8
+ if (c.req.method === "POST") return requireProjectPermission("edit")(c, next);
9
9
  return next();
10
10
  });
11
11
  app.use("/agent/:subAgentId/component/:artifactComponentId", async (c, next) => {
12
- if (c.req.method === "DELETE") return requirePermission({ sub_agent: ["delete"] })(c, next);
12
+ if (c.req.method === "DELETE") return requireProjectPermission("edit")(c, next);
13
13
  return next();
14
14
  });
15
15
  app.openapi(createRoute({
@@ -1,15 +1,15 @@
1
- import { requirePermission } from "../middleware/require-permission.js";
1
+ import { requireProjectPermission } from "../middleware/project-access.js";
2
2
  import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
3
3
  import { ComponentAssociationListResponse, DataComponentArrayResponse, ErrorResponseSchema, ExistsResponseSchema, RemovedResponseSchema, SubAgentDataComponentApiInsertSchema, SubAgentDataComponentResponse, TenantProjectAgentParamsSchema, TenantProjectAgentSubAgentParamsSchema, associateDataComponentWithAgent, commonGetErrorResponses, createApiError, getAgentsUsingDataComponent, getDataComponent, getDataComponentsForAgent, getSubAgentById, isDataComponentAssociatedWithAgent, removeDataComponentFromAgent } from "@inkeep/agents-core";
4
4
 
5
5
  //#region src/routes/subAgentDataComponents.ts
6
6
  const app = new OpenAPIHono();
7
7
  app.use("/", async (c, next) => {
8
- if (c.req.method === "POST") return requirePermission({ sub_agent: ["create"] })(c, next);
8
+ if (c.req.method === "POST") return requireProjectPermission("edit")(c, next);
9
9
  return next();
10
10
  });
11
11
  app.use("/agent/:subAgentId/component/:dataComponentId", async (c, next) => {
12
- if (c.req.method === "DELETE") return requirePermission({ sub_agent: ["delete"] })(c, next);
12
+ if (c.req.method === "DELETE") return requireProjectPermission("edit")(c, next);
13
13
  return next();
14
14
  });
15
15
  app.openapi(createRoute({