Implement two-tier agent and skill change grants

Add suggest/change permission keys for agent and skill configuration, route protected mutations through authorization.decide, repair default root and reflection-coach grants, and carry agent permission grants through company portability.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-07-09 20:50:34 +00:00
1 parent e786d53087
commit fcbf2ede0d
21 files changed
+935 -275

No files matched your search

+3
View File
@@ -849,7 +849,10 @@ export type JoinRequestStatus = (typeof JOIN_REQUEST_STATUSES)[number];
export const PERMISSION_KEYS = [
"agents:create",
"agents:configure",
"agents:suggest-changes",
"skills:create",
"skills:suggest-changes",
"environments:manage",
"users:invite",
"users:manage_permissions",
@@ -1,6 +1,6 @@
import type { AgentEnvConfig } from "./secrets.js";
import type { RoutineVariable } from "./routine.js";
import type { IssueCommentAuthorType } from "../constants.js";
import type { IssueCommentAuthorType, PermissionKey } from "../constants.js";
import type { IssueCommentMetadata, IssueCommentPresentation } from "./issue.js";
export interface CompanyPortabilityInclude {
@@ -145,6 +145,10 @@ export interface CompanyPortabilityAgentManifestEntry {
adapterConfig: Record<string, unknown>;
runtimeConfig: Record<string, unknown>;
permissions: Record<string, unknown>;
permissionGrants: Array<{
permissionKey: PermissionKey;
scope: Record<string, unknown> | null;
}>;
budgetMonthlyCents: number;
metadata: Record<string, unknown> | null;
}
@@ -1,4 +1,5 @@
import { z } from "zod";
import { PERMISSION_KEYS } from "../constants.js";
import { MAX_COMPANY_ATTACHMENT_MAX_BYTES } from "../constants.js";
import {
issueCommentAuthorTypeSchema,
@@ -70,6 +71,10 @@ export const portabilityAgentManifestEntrySchema = z.object({
adapterConfig: z.record(z.string(), z.unknown()),
runtimeConfig: z.record(z.string(), z.unknown()),
permissions: z.record(z.string(), z.unknown()),
permissionGrants: z.array(z.object({
permissionKey: z.enum(PERMISSION_KEYS),
scope: z.record(z.string(), z.unknown()).nullable().default(null),
})).default([]),
budgetMonthlyCents: z.number().int().nonnegative(),
metadata: z.record(z.string(), z.unknown()).nullable(),
});