@ever-works/activepieces-plugin 1.0.13 → 1.0.15

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 (3) hide show
  1. package/dist/index.cjs +995 -26
  2. package/dist/index.js +995 -26
  3. package/package.json +6 -6
package/dist/index.js CHANGED
@@ -458,6 +458,13 @@ var TASK_BOARD_STATUS_COLUMNS = TASK_BOARD_STATUSES.map((status) => ({
458
458
  terminal: TASK_BOARD_TERMINAL_STATUSES.includes(status),
459
459
  toggleOnly: false
460
460
  }));
461
+ var TASK_RESERVED_LABELS = Object.freeze([
462
+ "awaiting-owner",
463
+ "app-provision",
464
+ "release:promotion",
465
+ "release:revert"
466
+ ]);
467
+ var TASK_RESERVED_LABEL_PREFIXES = Object.freeze(["release:", "provision-attempt-", "fleet:"]);
461
468
  var PLATFORM_DEFAULT_MERGE_POLICY = Object.freeze({
462
469
  allowAgentMerge: false,
463
470
  requireGreenGate: true,
@@ -1088,26 +1095,10 @@ var FLEET_AGENT_CREDENTIAL_FAMILIES = [
1088
1095
  var FLEET_AGENT_CREDENTIAL_ENV_NAMES = FLEET_AGENT_CREDENTIAL_FAMILIES.flatMap(
1089
1096
  (family) => family.envNames
1090
1097
  );
1091
- var FLEET_RUN_ENV_FILE_MAX_CONTENT_BYTES = 32 * 1024;
1092
- var FLEET_RUN_ENV_FILES_MAX_TOTAL_BYTES = 256 * 1024;
1093
- var FLEET_JOB_MAX_PAYLOAD_BYTES = 256 * 1024;
1094
- var FLEET_JOB_MAX_RESULT_BYTES = 256 * 1024;
1095
- var FLEET_JOB_DEFAULT_QUEUED_MAX_AGE_SEC = Object.freeze({
1096
- "agent-task": 24 * 60 * 60,
1097
- "acceptance-checks": 2 * 60 * 60,
1098
- "browser-check": 2 * 60 * 60,
1099
- // A live view nobody claimed is abandoned by the session service after
1100
- // 40 seconds, which cancels its job there and then. The queue SLA is only
1101
- // the backstop behind that, so it deliberately does not undercut the
1102
- // shortest existing default (the fallback an unknown kind fails closed to).
1103
- "computer-session": 2 * 60 * 60
1104
- });
1105
- var FLEET_JOB_MAX_QUEUED_MAX_AGE_SEC = 7 * 24 * 60 * 60;
1106
- var FLEET_AGENT_EXECUTION_MAX_INSTRUCTIONS_BYTES = 160 * 1024;
1107
- var FLEET_AGENT_TASK_TIMELINE_MAX_BYTES = 48 * 1024;
1108
- var FLEET_AGENT_TASK_TRANSCRIPT_MAX_BYTES = 64 * 1024;
1109
- var FLEET_AGENT_TASK_QUESTION_MAX_FILE_BYTES = 64 * 1024;
1110
- var FLEET_AGENT_TASK_QUESTION_MAX_CONTEXT_BYTES = 6 * 1024;
1098
+ var FLEET_CHECKOUT_LISTED_REFRESH_MS = 5 * 6e4;
1099
+ var FLEET_CHECKOUT_RECONCILE_MS = 10 * 6e4;
1100
+ var FLEET_CHECKOUT_CREATING_STALE_MS = 10 * 6e4;
1101
+ var FLEET_CHECKOUT_BIN_PURGE_AFTER_MS = 30 * 24 * 60 * 6e4;
1111
1102
  var FLEET_LINK_MAX_FRAME_BYTES = 16 * 1024 * 1024;
1112
1103
  var FLEET_LINK_FRAME_HEADER_BYTES = 9;
1113
1104
  var FLEET_LINK_MAX_PAYLOAD_BYTES = FLEET_LINK_MAX_FRAME_BYTES - FLEET_LINK_FRAME_HEADER_BYTES;
@@ -1163,12 +1154,117 @@ var FLEET_LINK_CONTROL_TYPES = [
1163
1154
  "operation.done",
1164
1155
  "operation.cancel"
1165
1156
  ];
1157
+ var FLEET_FILES_LIMITS = {
1158
+ /** Largest `DATA` frame of a files stream. */
1159
+ chunkBytes: 64 * 1024,
1160
+ /** Unacknowledged bytes a sender may have in flight (the link's credit window). */
1161
+ windowBytes: 8 * 1024 * 1024,
1162
+ /** Bytes one operation may move. */
1163
+ maxOpBytes: 2 * 1024 * 1024 * 1024,
1164
+ /** Entries one operation may carry, and one listing may show. */
1165
+ maxEntries: 5e3,
1166
+ /** Transfers running at once on one computer. */
1167
+ maxConcurrentPerNode: 2,
1168
+ /** Transfers one person runs at once. */
1169
+ maxConcurrentPerUser: 4
1170
+ };
1171
+ var FLEET_FILES_MAX_BYTES_RECORD = FLEET_FILES_LIMITS.chunkBytes - 5;
1172
+ var FLEET_FILES_TRANSFER_RETENTION_MS = 10 * 6e4;
1173
+ var FLEET_FILES_LIST_AUDIT_WINDOW_MS = 15 * 6e4;
1174
+ var FLEET_CREDENTIAL_FILE_PATTERNS = [
1175
+ ".env",
1176
+ ".env.*",
1177
+ "*.pem",
1178
+ "*.key",
1179
+ "*.p12",
1180
+ "*.pfx",
1181
+ "*.jks",
1182
+ "*.keystore",
1183
+ "*.kdbx",
1184
+ "id_rsa*",
1185
+ "id_dsa*",
1186
+ "id_ecdsa*",
1187
+ "id_ed25519*",
1188
+ "*.ppk",
1189
+ ".netrc",
1190
+ ".npmrc",
1191
+ ".pypirc",
1192
+ "credentials",
1193
+ "credentials.json",
1194
+ "service-account*.json",
1195
+ ".aws/credentials",
1196
+ "*.gpg",
1197
+ "*.asc",
1198
+ ".docker/config.json",
1199
+ "kubeconfig",
1200
+ ".kube/config"
1201
+ ];
1202
+ function globToRegExp(glob) {
1203
+ const escaped = glob.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
1204
+ return new RegExp(`^${escaped}$`, "i");
1205
+ }
1206
+ var CREDENTIAL_NAME_MATCHERS = FLEET_CREDENTIAL_FILE_PATTERNS.filter((pattern) => !pattern.includes("/")).map(
1207
+ globToRegExp
1208
+ );
1209
+ var CREDENTIAL_PATH_MATCHERS = FLEET_CREDENTIAL_FILE_PATTERNS.filter((pattern) => pattern.includes("/")).map(
1210
+ (pattern) => ({ segments: pattern.split("/").length, matcher: globToRegExp(pattern) })
1211
+ );
1212
+ var MAX_HEADER_JSON_BYTES = 16 * 1024;
1213
+ var FLEET_RUN_ENV_FILE_MAX_CONTENT_BYTES = 32 * 1024;
1214
+ var FLEET_RUN_ENV_FILES_MAX_TOTAL_BYTES = 256 * 1024;
1215
+ var FLEET_JOB_MAX_PAYLOAD_BYTES = 256 * 1024;
1216
+ var FLEET_JOB_MAX_RESULT_BYTES = 256 * 1024;
1217
+ var FLEET_JOB_DEFAULT_QUEUED_MAX_AGE_SEC = Object.freeze({
1218
+ "agent-task": 24 * 60 * 60,
1219
+ "acceptance-checks": 2 * 60 * 60,
1220
+ "browser-check": 2 * 60 * 60,
1221
+ // A live view nobody claimed is abandoned by the session service after
1222
+ // 40 seconds, which cancels its job there and then. The queue SLA is only
1223
+ // the backstop behind that, so it deliberately does not undercut the
1224
+ // shortest existing default (the fallback an unknown kind fails closed to).
1225
+ "computer-session": 2 * 60 * 60,
1226
+ // An Agent session (FL-04 P2). Like the live view it does not undercut the
1227
+ // shortest existing default (the fallback an unknown kind fails closed to):
1228
+ // the session sweeper ends one still waiting after ten minutes, and this
1229
+ // queue SLA is only the backstop behind it.
1230
+ "agent-session": 2 * 60 * 60,
1231
+ // Virtual computers (FL-16). The plan proposed an hour for a create and ten
1232
+ // minutes for a control; like the live view and the Agent session they do
1233
+ // NOT undercut the shortest existing default (the fallback an unknown kind
1234
+ // fails closed to), so an older reader's "unknown kind" answer is unchanged.
1235
+ // A control the owner no longer wants is cancelled with its child's row.
1236
+ "vm-create": 2 * 60 * 60,
1237
+ "vm-control": 2 * 60 * 60,
1238
+ // Usage scan (FL-20). The plan proposed 15 minutes (one scan interval); like
1239
+ // the kinds above it does NOT undercut the shortest existing default (the
1240
+ // fallback an unknown kind fails closed to). A scan nobody leased is simply
1241
+ // superseded: the dispatcher never enqueues a second while one is queued.
1242
+ "usage-scan": 2 * 60 * 60,
1243
+ // Actions runners on computers (FL-18). The plan proposed an hour for an
1244
+ // install and ten minutes for a control; like FL-16's kinds they do NOT
1245
+ // undercut the shortest existing default (the fallback an unknown kind fails
1246
+ // closed to), so an older reader's answer for an unknown kind is unchanged.
1247
+ "runner-install": 2 * 60 * 60,
1248
+ "runner-control": 2 * 60 * 60
1249
+ });
1250
+ var FLEET_JOB_MAX_QUEUED_MAX_AGE_SEC = 7 * 24 * 60 * 60;
1251
+ var FLEET_AGENT_EXECUTION_MAX_INSTRUCTIONS_BYTES = 160 * 1024;
1252
+ var FLEET_AGENT_TASK_TIMELINE_MAX_BYTES = 48 * 1024;
1253
+ var FLEET_AGENT_TASK_TRANSCRIPT_MAX_BYTES = 64 * 1024;
1254
+ var FLEET_AGENT_TASK_QUESTION_MAX_FILE_BYTES = 64 * 1024;
1255
+ var FLEET_AGENT_TASK_QUESTION_MAX_CONTEXT_BYTES = 6 * 1024;
1166
1256
  var CONTROL_TYPES = new Set(FLEET_LINK_CONTROL_TYPES);
1167
1257
  var KIND_JSON = FLEET_LINK_FRAME_KINDS.JSON;
1168
1258
  var utf8Encoder = new TextEncoder();
1169
1259
  var FLEET_LINK_VIEWER_SLOW_BUFFER_BYTES = 8 * 1024 * 1024;
1170
1260
  var FLEET_LINK_VIEWER_MAX_BUFFER_BYTES = 32 * 1024 * 1024;
1171
1261
  var FLEET_LINK_VIEWER_FRAME_KINDS = [FLEET_LINK_FRAME_KINDS.ACK];
1262
+ var FLEET_MACHINE_OPERATION_MAX_MS = 60 * 6e4;
1263
+ var FLEET_LOGS_FOLLOW_BYTES_PER_SEC = 1024 * 1024;
1264
+ var FLEET_LOGS_PENDING_MAX_BYTES = 1024 * 1024;
1265
+ var FLEET_LOGS_MAX_FRAME_BYTES = 64 * 1024;
1266
+ var FLEET_LOGS_MAX_LINE_CHARS = 16 * 1024;
1267
+ var FLEET_LOGS_FILE_SCAN_MAX_BYTES = 8 * 1024 * 1024;
1172
1268
  var FLEET_MODEL_USAGE_LIMIT_FALLBACK_MS = 60 * 60 * 1e3;
1173
1269
  var FLEET_MODEL_USAGE_LIMIT_MIN_MS = 60 * 1e3;
1174
1270
  var FLEET_MODEL_USAGE_LIMIT_MAX_MS = 8 * 24 * 60 * 60 * 1e3;
@@ -1187,6 +1283,51 @@ var FLEET_HEALTH_DISK_CRITICAL_MARGIN_BYTES = 1024 ** 3;
1187
1283
  var FLEET_HEALTH_MAX_MIB = 2 ** 40;
1188
1284
  var FLEET_HEALTH_MAX_UPTIME_SEC = 100 * 365 * 24 * 60 * 60;
1189
1285
  var FLEET_HEALTH_BYTES_PER_MIB = 1024 * 1024;
1286
+ var MINUTE_MS = 6e4;
1287
+ var HOUR_MS = 60 * MINUTE_MS;
1288
+ var DAY_MS2 = 24 * HOUR_MS;
1289
+ var FLEET_HEALTH_RANGE_MS = {
1290
+ "1h": HOUR_MS,
1291
+ "24h": DAY_MS2,
1292
+ "7d": 7 * DAY_MS2,
1293
+ "90d": 90 * DAY_MS2
1294
+ };
1295
+ var FLEET_WAKE_RATE_WINDOW_MS = 5 * 6e4;
1296
+ var FLEET_PORT_PROBE_BODY_CAP = 64 * 1024;
1297
+ var FLEET_PORT_PREVIEW_MAX_MS = 60 * 6e4;
1298
+ var FLEET_PORT_TUNNEL_IDLE_MS = 10 * 6e4;
1299
+ var FLEET_PORT_TUNNEL_HARD_MS = 60 * 6e4;
1300
+ var FLEET_PORT_TUNNEL_CHUNK_BYTES = 64 * 1024;
1301
+ var FLEET_PORT_TUNNEL_MAX_HEADER_BYTES = 64 * 1024;
1302
+ var FLEET_WELL_KNOWN_PORTS = Object.freeze({
1303
+ 21: "ftp",
1304
+ 22: "ssh",
1305
+ 25: "smtp",
1306
+ 53: "dns",
1307
+ 110: "pop3",
1308
+ 143: "imap",
1309
+ 389: "ldap",
1310
+ 1433: "mssql",
1311
+ 1521: "oracle",
1312
+ 2375: "docker",
1313
+ 2376: "docker",
1314
+ 2379: "etcd",
1315
+ 3306: "mysql",
1316
+ 3389: "rdp",
1317
+ 4222: "nats",
1318
+ 5432: "postgres",
1319
+ 5672: "amqp",
1320
+ 5900: "vnc",
1321
+ 6379: "redis",
1322
+ 6443: "kubernetes",
1323
+ 7687: "neo4j",
1324
+ 9042: "cassandra",
1325
+ 9092: "kafka",
1326
+ 9200: "elasticsearch",
1327
+ 11211: "memcached",
1328
+ 15672: "rabbitmq",
1329
+ 27017: "mongo"
1330
+ });
1190
1331
  var FLEET_RUN_TOKEN_ROUTES = Object.freeze([
1191
1332
  // Works — reads, plus the settings update (its merge / check / command
1192
1333
  // fields are refused for run tokens by the Works controller).
@@ -1270,6 +1411,12 @@ var FLEET_RUN_TOKEN_ROUTES = Object.freeze([
1270
1411
  { method: "GET", pathPattern: "/api/fleet/runner-status" },
1271
1412
  { method: "GET", pathPattern: "/api/fleet/execution-preferences" },
1272
1413
  { method: "GET", pathPattern: "/api/fleet/agents/{agentId}/node-affinity" },
1414
+ // Session git & actions (FL-06 FR-18): an Agent session asks the platform to
1415
+ // open or update the pull request of ITS OWN checkout. The route refuses a
1416
+ // checkout that is not the token's session's, and the Agent's "may open pull
1417
+ // requests" permission applies; it never merges anything.
1418
+ { method: "GET", pathPattern: "/api/fleet/checkouts/{id}/pull-request" },
1419
+ { method: "POST", pathPattern: "/api/fleet/checkouts/{id}/pull-request" },
1273
1420
  // Agents — reads, plus cancel and pause (the safe direction).
1274
1421
  { method: "GET", pathPattern: "/api/agents" },
1275
1422
  { method: "GET", pathPattern: "/api/agents/{id}" },
@@ -1292,6 +1439,809 @@ var FLEET_RUN_TOKEN_ROUTE_SHAPES = FLEET_RUN_TOKEN_ROUTES.map((route) => ({
1292
1439
  method: route.method.toUpperCase(),
1293
1440
  shape: splitSegments(route.pathPattern).map((part) => /^\{[^}]+\}$/.test(part) ? "*" : part.toLowerCase())
1294
1441
  }));
1442
+ var FLEET_SESSION_STATES = ["starting", "working", "needs_you", "done", "idle", "ended"];
1443
+ var FLEET_SESSION_LIVE_STATES = FLEET_SESSION_STATES.filter(
1444
+ (state) => state !== "ended"
1445
+ );
1446
+ var FLEET_SESSION_SLOW_VIEWER_BYTES = 1024 * 1024;
1447
+ var FLEET_SESSION_DAEMON_IDLE_EXIT_MS = 5 * 6e4;
1448
+ var FLEET_SESSION_LAST_SCREEN_MAX_CHARS = 256 * 1024;
1449
+ var FLEET_AGENT_SESSION_QUEUED_TIMEOUT_MS = 10 * 6e4;
1450
+ var FLEET_PR_ENRICHMENT_RECENT_MS = 7 * 24 * 60 * 6e4;
1451
+ var FLEET_GIT_LINE_STALE_MS = 5 * 6e4;
1452
+ var FLEET_SESSION_IDLE_AFTER_MS = 30 * 6e4;
1453
+ var FLEET_SESSION_DECISION_STALE_MS = 24 * 60 * 6e4;
1454
+ var FLEET_SESSION_HOOK_BODY_MAX_BYTES = 64 * 1024;
1455
+ var FLEET_SESSION_HOOK_SPOOL_MAX_BYTES = 5 * 1024 * 1024;
1456
+ var FLEET_SESSION_HOOK_SPOOL_MAX_AGE_MS = 7 * 24 * 60 * 6e4;
1457
+ var FLEET_COMMAND_MAX_OUTPUT_BYTES = 10 * 1024 * 1024;
1458
+ var FLEET_COMMAND_STORED_EDGE_BYTES = 64 * 1024;
1459
+ var FLEET_COMMAND_DATA_CHUNK_BYTES = 64 * 1024;
1460
+ var FLEET_COMMAND_MAX_LENGTH = 8 * 1024;
1461
+ var FLEET_SCHEDULE_PROMPT_MAX_BYTES = 16 * 1024;
1462
+ var FLEET_SCHEDULE_BREAKER_UNDO_MS = 15 * 6e4;
1463
+ var MAX_SEARCH_DAYS = 366 * 8 + 1;
1464
+ function row(input) {
1465
+ const rest = input.name.slice("fleet_".length);
1466
+ const cut = rest.indexOf("_");
1467
+ const family = cut === -1 ? rest : rest.slice(0, cut);
1468
+ const verb = cut === -1 ? "" : rest.slice(cut + 1);
1469
+ return Object.freeze({ ...input, family, verb });
1470
+ }
1471
+ function read(name, permissionFamily, owner, flag, status, extra = {}) {
1472
+ return row({
1473
+ name,
1474
+ readOnly: true,
1475
+ category: "read.internal",
1476
+ permissionFamily,
1477
+ owner,
1478
+ phase: "P1",
1479
+ flag,
1480
+ status,
1481
+ ...extra
1482
+ });
1483
+ }
1484
+ function act(name, permissionFamily, owner, flag, status, annotation, extra = {}) {
1485
+ return row({ name, permissionFamily, owner, phase: "P2", flag, status, ...annotation, ...extra });
1486
+ }
1487
+ var plain = (category, destructive = false) => ({
1488
+ destructive,
1489
+ confirmationClass: "plain",
1490
+ category
1491
+ });
1492
+ var confirm = (category, destructive = true) => ({
1493
+ destructive,
1494
+ confirmationClass: "confirm",
1495
+ category
1496
+ });
1497
+ var typed = (category) => ({
1498
+ destructive: true,
1499
+ confirmationClass: "confirm-destructive",
1500
+ category
1501
+ });
1502
+ var GET = (path) => ({ method: "GET", path });
1503
+ var POST = (path) => ({ method: "POST", path });
1504
+ var PATCH = (path) => ({ method: "PATCH", path });
1505
+ var DELETE = (path) => ({ method: "DELETE", path });
1506
+ var FLEET_TOOL_CATALOGUE = Object.freeze([
1507
+ // ── status (FL-19) ──
1508
+ read("fleet_status", "view", "FL-19", "FLEET_ENABLED", "live", {
1509
+ route: GET("/api/fleet/status"),
1510
+ cli: "fleet status"
1511
+ }),
1512
+ // ── nodes (FL-19, FL-03, FL-15) ──
1513
+ read("fleet_nodes_list", "view", "FL-19", "FLEET_ENABLED", "live", {
1514
+ route: GET("/api/fleet/nodes"),
1515
+ cli: "fleet nodes list"
1516
+ }),
1517
+ read("fleet_nodes_get", "view", "FL-19", "FLEET_ENABLED", "live", {
1518
+ route: GET("/api/fleet/nodes/{id}"),
1519
+ cli: "fleet nodes get"
1520
+ }),
1521
+ read("fleet_nodes_health", "view", "FL-03", "FLEET_ENABLED", "live", {
1522
+ route: GET("/api/fleet/nodes/{id}/health"),
1523
+ cli: "fleet nodes health"
1524
+ }),
1525
+ read("fleet_nodes_needs_a_look", "view", "FL-03", "FLEET_ENABLED", "live", {
1526
+ route: GET("/api/fleet/nodes/{id}/needs-a-look"),
1527
+ cli: "fleet nodes needs-a-look"
1528
+ }),
1529
+ read("fleet_nodes_git_identity_get", "view", "FL-15", "FLEET_CHECKOUTS_ENABLED", "live", {
1530
+ route: GET("/api/fleet/nodes/{id}/git/identity"),
1531
+ cli: "fleet nodes git-identity"
1532
+ }),
1533
+ act("fleet_nodes_wake", "machines", "FL-03", "FLEET_ENABLED", "live", plain("machine.admin"), {
1534
+ route: POST("/api/fleet/nodes/{id}/wake"),
1535
+ cli: "fleet nodes wake"
1536
+ }),
1537
+ act(
1538
+ "fleet_nodes_git_identity_set",
1539
+ "commands",
1540
+ "FL-15",
1541
+ "FLEET_CHECKOUTS_ENABLED",
1542
+ "live",
1543
+ confirm("machine.admin", false),
1544
+ { route: POST("/api/fleet/nodes/{id}/git/identity"), cli: "fleet nodes git-identity --set" }
1545
+ ),
1546
+ // ── sessions (FL-04, FL-05, FL-06) ──
1547
+ read("fleet_sessions_list", "sessions", "FL-04", "FLEET_SESSIONS_ENABLED", "live", {
1548
+ route: GET("/api/fleet/sessions"),
1549
+ cli: "fleet sessions list"
1550
+ }),
1551
+ read("fleet_sessions_read", "sessions", "FL-04", "FLEET_SESSIONS_ENABLED", "live", {
1552
+ route: GET("/api/fleet/sessions/{id}"),
1553
+ cli: "fleet sessions read"
1554
+ }),
1555
+ read("fleet_sessions_question", "sessions", "FL-05", "FLEET_SESSIONS_ENABLED", "live", {
1556
+ route: GET("/api/fleet/sessions/{id}"),
1557
+ cli: "fleet sessions question"
1558
+ }),
1559
+ read("fleet_sessions_actions_list", "sessions", "FL-06", "FLEET_SESSIONS_ENABLED", "planned", {
1560
+ route: GET("/api/fleet/sessions/{id}/actions"),
1561
+ cli: "fleet sessions actions"
1562
+ }),
1563
+ act("fleet_sessions_start", "sessions", "FL-04", "FLEET_SESSIONS_ENABLED", "live", plain("machine.run"), {
1564
+ route: POST("/api/fleet/nodes/{id}/sessions"),
1565
+ cli: "fleet sessions start"
1566
+ }),
1567
+ act("fleet_sessions_send", "sessions", "FL-04", "FLEET_SESSIONS_ENABLED", "live", plain("machine.run")),
1568
+ act("fleet_sessions_answer", "sessions", "FL-05", "FLEET_SESSIONS_ENABLED", "live", confirm("machine.run", false), {
1569
+ route: POST("/api/fleet/sessions/{id}/answer"),
1570
+ cli: "fleet sessions answer",
1571
+ confirmationNote: "questions only; a permission prompt is answered by a person (CONTRACTS R-32)"
1572
+ }),
1573
+ act("fleet_sessions_rename", "sessions", "FL-04", "FLEET_SESSIONS_ENABLED", "live", plain("write.internal"), {
1574
+ route: PATCH("/api/fleet/sessions/{id}"),
1575
+ cli: "fleet sessions rename"
1576
+ }),
1577
+ act("fleet_sessions_end", "sessions", "FL-04", "FLEET_SESSIONS_ENABLED", "live", confirm("machine.run"), {
1578
+ route: POST("/api/fleet/sessions/{id}/end"),
1579
+ cli: "fleet sessions end"
1580
+ }),
1581
+ act("fleet_sessions_action", "sessions", "FL-06", "FLEET_SESSIONS_ENABLED", "planned", plain("machine.run"), {
1582
+ route: POST("/api/fleet/sessions/{id}/actions"),
1583
+ cli: "fleet sessions action"
1584
+ }),
1585
+ // ── desktop (FL-07, FL-11 paste) ──
1586
+ read("fleet_desktop_screenshot", "desktop", "FL-07", "FLEET_DESKTOP_ENABLED", "planned", {
1587
+ route: GET("/api/fleet/nodes/{id}/desktop/screenshot"),
1588
+ cli: "fleet desktop screenshot"
1589
+ }),
1590
+ read("fleet_desktop_displays", "desktop", "FL-07", "FLEET_DESKTOP_ENABLED", "planned", {
1591
+ route: GET("/api/fleet/nodes/{id}/desktop/displays"),
1592
+ cli: "fleet desktop displays"
1593
+ }),
1594
+ read("fleet_desktop_recordings_list", "desktop", "FL-07", "FLEET_DESKTOP_ENABLED", "planned", {
1595
+ route: GET("/api/fleet/nodes/{id}/desktop/recordings"),
1596
+ cli: "fleet desktop recordings"
1597
+ }),
1598
+ act("fleet_desktop_input", "desktop", "FL-07", "FLEET_DESKTOP_ENABLED", "planned", plain("machine.admin", true), {
1599
+ route: POST("/api/fleet/nodes/{id}/desktop/input"),
1600
+ cli: "fleet desktop input"
1601
+ }),
1602
+ act("fleet_desktop_set_display", "desktop", "FL-07", "FLEET_DESKTOP_ENABLED", "planned", plain("machine.admin"), {
1603
+ route: POST("/api/fleet/nodes/{id}/desktop/displays"),
1604
+ cli: "fleet desktop set-display"
1605
+ }),
1606
+ act("fleet_desktop_display_add", "desktop", "FL-07", "FLEET_DESKTOP_ENABLED", "planned", confirm("machine.admin"), {
1607
+ phase: "P3",
1608
+ route: POST("/api/fleet/nodes/{id}/desktop/displays/virtual"),
1609
+ cli: "fleet desktop display-add"
1610
+ }),
1611
+ act(
1612
+ "fleet_desktop_display_remove",
1613
+ "desktop",
1614
+ "FL-07",
1615
+ "FLEET_DESKTOP_ENABLED",
1616
+ "planned",
1617
+ confirm("machine.admin"),
1618
+ {
1619
+ phase: "P3",
1620
+ route: DELETE("/api/fleet/nodes/{id}/desktop/displays/virtual/{displayId}"),
1621
+ cli: "fleet desktop display-remove"
1622
+ }
1623
+ ),
1624
+ act(
1625
+ "fleet_desktop_paste",
1626
+ "desktop",
1627
+ "FL-11",
1628
+ "FLEET_MACHINE_FACTS_ENABLED",
1629
+ "planned",
1630
+ plain("machine.admin", true),
1631
+ {
1632
+ route: POST("/api/fleet/nodes/{id}/desktop/paste"),
1633
+ cli: "fleet desktop paste",
1634
+ confirmationNote: "denied unless a tool grant allows it (AW-15)"
1635
+ }
1636
+ ),
1637
+ // ── logs (FL-08) ──
1638
+ read("fleet_logs_sources", "logs", "FL-08", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1639
+ route: GET("/api/fleet/nodes/{id}/logs/sources"),
1640
+ cli: "fleet logs sources"
1641
+ }),
1642
+ read("fleet_logs_read", "logs", "FL-08", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1643
+ route: POST("/api/fleet/nodes/{id}/logs/read"),
1644
+ cli: "fleet logs read"
1645
+ }),
1646
+ // ── services (FL-09) ──
1647
+ read("fleet_services_list", "services", "FL-09", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1648
+ route: GET("/api/fleet/nodes/{id}/services"),
1649
+ cli: "fleet services list"
1650
+ }),
1651
+ act("fleet_services_action", "services", "FL-09", "FLEET_MACHINE_FACTS_ENABLED", "live", confirm("machine.admin"), {
1652
+ route: POST("/api/fleet/nodes/{id}/services/{name}/{action}"),
1653
+ cli: "fleet services action",
1654
+ waitable: true,
1655
+ confirmationNote: "confirm; blast-radius when the node warns it could cut the machine off"
1656
+ }),
1657
+ // ── processes (FL-09) ──
1658
+ read("fleet_processes_list", "processes", "FL-09", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1659
+ route: GET("/api/fleet/nodes/{id}/processes"),
1660
+ cli: "fleet processes list"
1661
+ }),
1662
+ act(
1663
+ "fleet_processes_signal",
1664
+ "processes",
1665
+ "FL-09",
1666
+ "FLEET_MACHINE_FACTS_ENABLED",
1667
+ "live",
1668
+ confirm("machine.admin"),
1669
+ { route: POST("/api/fleet/nodes/{id}/processes/{pid}/signal"), cli: "fleet processes signal" }
1670
+ ),
1671
+ // ── docker (FL-09) ──
1672
+ read("fleet_docker_containers_list", "docker", "FL-09", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1673
+ route: GET("/api/fleet/nodes/{id}/docker/containers"),
1674
+ cli: "fleet docker containers"
1675
+ }),
1676
+ read("fleet_docker_images_list", "docker", "FL-09", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1677
+ route: GET("/api/fleet/nodes/{id}/docker/images"),
1678
+ cli: "fleet docker images"
1679
+ }),
1680
+ read("fleet_docker_compose_list", "docker", "FL-09", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1681
+ route: GET("/api/fleet/nodes/{id}/docker/compose"),
1682
+ cli: "fleet docker compose"
1683
+ }),
1684
+ read("fleet_docker_compose_describe", "docker", "FL-09", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1685
+ cli: "fleet docker compose-describe"
1686
+ }),
1687
+ act(
1688
+ "fleet_docker_container_action",
1689
+ "docker",
1690
+ "FL-09",
1691
+ "FLEET_MACHINE_FACTS_ENABLED",
1692
+ "live",
1693
+ confirm("machine.admin"),
1694
+ {
1695
+ route: POST("/api/fleet/nodes/{id}/docker/containers/{cid}/{action}"),
1696
+ cli: "fleet docker container",
1697
+ waitable: true,
1698
+ confirmationNote: "confirm; remove is confirm-destructive"
1699
+ }
1700
+ ),
1701
+ act("fleet_docker_run", "docker", "FL-09", "FLEET_MACHINE_FACTS_ENABLED", "live", confirm("machine.admin", false), {
1702
+ route: POST("/api/fleet/nodes/{id}/docker/containers"),
1703
+ cli: "fleet docker run",
1704
+ waitable: true,
1705
+ alwaysHeld: true,
1706
+ confirmationNote: "an Agent proposes a run; a person types any secret values"
1707
+ }),
1708
+ act(
1709
+ "fleet_docker_image_action",
1710
+ "docker",
1711
+ "FL-09",
1712
+ "FLEET_MACHINE_FACTS_ENABLED",
1713
+ "live",
1714
+ confirm("machine.admin"),
1715
+ {
1716
+ route: POST("/api/fleet/nodes/{id}/docker/images/{iid}/{action}"),
1717
+ cli: "fleet docker image",
1718
+ waitable: true,
1719
+ confirmationNote: "pull is plain and not destructive; remove and prune confirm"
1720
+ }
1721
+ ),
1722
+ act(
1723
+ "fleet_docker_compose_action",
1724
+ "docker",
1725
+ "FL-09",
1726
+ "FLEET_MACHINE_FACTS_ENABLED",
1727
+ "live",
1728
+ confirm("machine.admin"),
1729
+ {
1730
+ route: POST("/api/fleet/nodes/{id}/docker/compose/{project}/{action}"),
1731
+ cli: "fleet docker compose-action",
1732
+ waitable: true,
1733
+ confirmationNote: "destructive for down"
1734
+ }
1735
+ ),
1736
+ act("fleet_docker_exec", "docker", "FL-09", "FLEET_MACHINE_FACTS_ENABLED", "planned", plain("machine.run"), {
1737
+ phase: "P3",
1738
+ cli: "fleet docker exec"
1739
+ }),
1740
+ // ── ports (FL-10) ──
1741
+ read("fleet_ports_list", "view", "FL-10", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1742
+ route: GET("/api/fleet/nodes/{id}/ports"),
1743
+ cli: "fleet ports list"
1744
+ }),
1745
+ act("fleet_ports_open", "ports", "FL-10", "FLEET_MACHINE_FACTS_ENABLED", "live", plain("machine.run"), {
1746
+ route: POST("/api/fleet/nodes/{id}/ports/{port}/open"),
1747
+ cli: "fleet ports open"
1748
+ }),
1749
+ act("fleet_ports_preview_open", "ports", "FL-10", "FLEET_PORT_TUNNEL_ENABLED", "live", plain("machine.run"), {
1750
+ route: POST("/api/fleet/nodes/{id}/ports/{port}/preview"),
1751
+ cli: "fleet ports preview"
1752
+ }),
1753
+ act("fleet_ports_preview_close", "ports", "FL-10", "FLEET_PORT_TUNNEL_ENABLED", "live", plain("machine.run"), {
1754
+ route: DELETE("/api/fleet/nodes/{id}/ports/{port}/preview"),
1755
+ cli: "fleet ports preview-close"
1756
+ }),
1757
+ // ── files (FL-11) ──
1758
+ // P1 (FL-11 lane log decision 15): the roots read joins the family, and the list's route is the
1759
+ // one FL-11 built (`…/files/list` — `…/files` is the family's prefix, not a route).
1760
+ read("fleet_files_roots", "files", "FL-11", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1761
+ route: GET("/api/fleet/nodes/{id}/files/roots"),
1762
+ cli: "fleet files roots"
1763
+ }),
1764
+ read("fleet_files_list", "files", "FL-11", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1765
+ route: GET("/api/fleet/nodes/{id}/files/list"),
1766
+ cli: "fleet files list"
1767
+ }),
1768
+ read("fleet_files_stat", "files", "FL-11", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1769
+ route: GET("/api/fleet/nodes/{id}/files/stat"),
1770
+ cli: "fleet files stat"
1771
+ }),
1772
+ read("fleet_files_read", "files", "FL-11", "FLEET_MACHINE_FACTS_ENABLED", "planned", {
1773
+ route: GET("/api/fleet/nodes/{id}/files/download"),
1774
+ cli: "fleet files get"
1775
+ }),
1776
+ act("fleet_files_write", "files", "FL-11", "FLEET_MACHINE_FACTS_ENABLED", "planned", confirm("machine.admin"), {
1777
+ route: POST("/api/fleet/nodes/{id}/files/upload"),
1778
+ cli: "fleet files put"
1779
+ }),
1780
+ act("fleet_files_copy", "files", "FL-11", "FLEET_MACHINE_FACTS_ENABLED", "live", confirm("machine.admin"), {
1781
+ route: POST("/api/fleet/nodes/{id}/files/copy"),
1782
+ cli: "fleet files cp",
1783
+ // FL-11 P2 (lane log decision 18): an Agent's copy is held for a person, like its delete.
1784
+ alwaysHeld: true
1785
+ }),
1786
+ act("fleet_files_delete", "files", "FL-11", "FLEET_MACHINE_FACTS_ENABLED", "live", typed("write.destructive"), {
1787
+ route: POST("/api/fleet/nodes/{id}/files/delete"),
1788
+ cli: "fleet files rm",
1789
+ alwaysHeld: true
1790
+ }),
1791
+ // ── commands (FL-12) ──
1792
+ read("fleet_commands_list", "commands", "FL-12", "FLEET_COMMANDS_ENABLED", "live", {
1793
+ route: GET("/api/fleet/commands"),
1794
+ cli: "fleet commands list"
1795
+ }),
1796
+ read("fleet_commands_get", "commands", "FL-12", "FLEET_COMMANDS_ENABLED", "live", {
1797
+ route: GET("/api/fleet/commands/{id}"),
1798
+ cli: "fleet commands get"
1799
+ }),
1800
+ act("fleet_commands_run", "commands", "FL-12", "FLEET_COMMANDS_ENABLED", "live", confirm("machine.run"), {
1801
+ route: POST("/api/fleet/commands"),
1802
+ cli: "fleet commands run",
1803
+ alwaysHeld: true
1804
+ }),
1805
+ act("fleet_commands_cancel", "commands", "FL-12", "FLEET_COMMANDS_ENABLED", "live", plain("machine.run"), {
1806
+ route: POST("/api/fleet/commands/{id}/cancel"),
1807
+ cli: "fleet commands cancel"
1808
+ }),
1809
+ // ── schedules (FL-13 P2: live — `apps/api/src/fleet/schedules/fleet-schedules.controller.ts`) ──
1810
+ read("fleet_schedules_list", "schedules", "FL-13", "FLEET_COMMANDS_ENABLED", "live", {
1811
+ route: GET("/api/fleet/schedules"),
1812
+ cli: "fleet schedules list"
1813
+ }),
1814
+ read("fleet_schedules_get", "schedules", "FL-13", "FLEET_COMMANDS_ENABLED", "live", {
1815
+ route: GET("/api/fleet/schedules/{id}"),
1816
+ cli: "fleet schedules get"
1817
+ }),
1818
+ read("fleet_schedules_runs", "schedules", "FL-13", "FLEET_COMMANDS_ENABLED", "live", {
1819
+ route: GET("/api/fleet/schedules/{id}/runs"),
1820
+ cli: "fleet schedules runs"
1821
+ }),
1822
+ act("fleet_schedules_create", "schedules", "FL-13", "FLEET_COMMANDS_ENABLED", "live", confirm("agent.fanout"), {
1823
+ route: POST("/api/fleet/schedules"),
1824
+ cli: "fleet schedules create"
1825
+ }),
1826
+ act("fleet_schedules_update", "schedules", "FL-13", "FLEET_COMMANDS_ENABLED", "live", confirm("agent.fanout"), {
1827
+ route: PATCH("/api/fleet/schedules/{id}"),
1828
+ cli: "fleet schedules update"
1829
+ }),
1830
+ act(
1831
+ "fleet_schedules_delete",
1832
+ "schedules",
1833
+ "FL-13",
1834
+ "FLEET_COMMANDS_ENABLED",
1835
+ "live",
1836
+ confirm("write.destructive"),
1837
+ { route: DELETE("/api/fleet/schedules/{id}"), cli: "fleet schedules delete" }
1838
+ ),
1839
+ act("fleet_schedules_run", "schedules", "FL-13", "FLEET_COMMANDS_ENABLED", "live", confirm("machine.run"), {
1840
+ route: POST("/api/fleet/schedules/{id}/run"),
1841
+ cli: "fleet schedules run"
1842
+ }),
1843
+ act("fleet_schedules_pause", "schedules", "FL-13", "FLEET_COMMANDS_ENABLED", "live", plain("agent.fanout"), {
1844
+ route: POST("/api/fleet/schedules/{id}/pause"),
1845
+ cli: "fleet schedules pause"
1846
+ }),
1847
+ act("fleet_schedules_resume", "schedules", "FL-13", "FLEET_COMMANDS_ENABLED", "live", plain("agent.fanout"), {
1848
+ route: POST("/api/fleet/schedules/{id}/resume"),
1849
+ cli: "fleet schedules resume"
1850
+ }),
1851
+ // ── checkouts (FL-14, FL-06) ──
1852
+ read("fleet_checkouts_list", "checkouts", "FL-14", "FLEET_CHECKOUTS_ENABLED", "live", {
1853
+ route: GET("/api/fleet/checkouts"),
1854
+ cli: "fleet checkouts list"
1855
+ }),
1856
+ read("fleet_checkouts_get", "checkouts", "FL-14", "FLEET_CHECKOUTS_ENABLED", "live", {
1857
+ route: GET("/api/fleet/checkouts/{id}"),
1858
+ cli: "fleet checkouts get"
1859
+ }),
1860
+ read("fleet_checkouts_changes", "checkouts", "FL-06", "FLEET_CHECKOUTS_ENABLED", "planned", {
1861
+ route: GET("/api/fleet/checkouts/{id}/changes"),
1862
+ cli: "fleet checkouts changes"
1863
+ }),
1864
+ act("fleet_checkouts_create", "checkouts", "FL-14", "FLEET_CHECKOUTS_ENABLED", "live", plain("machine.run"), {
1865
+ route: POST("/api/fleet/checkouts"),
1866
+ cli: "fleet checkouts create",
1867
+ waitable: true
1868
+ }),
1869
+ act("fleet_checkouts_sync", "checkouts", "FL-14", "FLEET_CHECKOUTS_ENABLED", "live", plain("machine.run"), {
1870
+ route: POST("/api/fleet/checkouts/{id}/sync"),
1871
+ cli: "fleet checkouts sync",
1872
+ waitable: true,
1873
+ confirmationNote: "plain for fetch; confirm for pull and push"
1874
+ }),
1875
+ act(
1876
+ "fleet_checkouts_archive",
1877
+ "checkouts",
1878
+ "FL-14",
1879
+ "FLEET_CHECKOUTS_ENABLED",
1880
+ "live",
1881
+ confirm("machine.run", false),
1882
+ { route: POST("/api/fleet/checkouts/{id}/archive"), cli: "fleet checkouts archive" }
1883
+ ),
1884
+ act(
1885
+ "fleet_checkouts_delete",
1886
+ "checkouts",
1887
+ "FL-14",
1888
+ "FLEET_CHECKOUTS_ENABLED",
1889
+ "live",
1890
+ confirm("write.destructive"),
1891
+ {
1892
+ route: DELETE("/api/fleet/checkouts/{id}"),
1893
+ cli: "fleet checkouts delete",
1894
+ confirmationNote: "confirm; confirm-destructive when it has uncommitted changes"
1895
+ }
1896
+ ),
1897
+ act(
1898
+ "fleet_checkouts_open_pull_request",
1899
+ "checkouts",
1900
+ "FL-06",
1901
+ "FLEET_CHECKOUTS_ENABLED",
1902
+ "planned",
1903
+ plain("publish.external"),
1904
+ { route: POST("/api/fleet/checkouts/{id}/pull-request"), cli: "fleet checkouts pull-request" }
1905
+ ),
1906
+ // ── tasks (FL-15) ── the hand-off itself is `fleet_sessions_start` with `taskId`
1907
+ read("fleet_tasks_handoff_options", "sessions", "FL-15", "FLEET_CHECKOUTS_ENABLED", "live", {
1908
+ route: GET("/api/fleet/tasks/{taskId}/handoff-options"),
1909
+ cli: "fleet tasks handoff-options"
1910
+ }),
1911
+ // ── virtual (FL-16) ── P1 shipped: Containers. A create, a stop and a destroy are held for
1912
+ // the owner's approval by the Agent tools (`agent-fleet-virtual-tools.ts`).
1913
+ read("fleet_virtual_list", "view", "FL-16", "FLEET_VIRTUAL_ENABLED", "live", {
1914
+ phase: "P3",
1915
+ route: GET("/api/fleet/nodes/{id}/virtual"),
1916
+ cli: "fleet virtual list"
1917
+ }),
1918
+ read("fleet_virtual_options", "view", "FL-16", "FLEET_VIRTUAL_ENABLED", "live", {
1919
+ phase: "P3",
1920
+ route: GET("/api/fleet/nodes/{id}/virtual/options"),
1921
+ cli: "fleet virtual options"
1922
+ }),
1923
+ act("fleet_virtual_create", "machines", "FL-16", "FLEET_VIRTUAL_ENABLED", "live", confirm("machine.admin"), {
1924
+ phase: "P3",
1925
+ route: POST("/api/fleet/nodes/{id}/virtual"),
1926
+ cli: "fleet virtual create",
1927
+ waitable: true,
1928
+ alwaysHeld: true
1929
+ }),
1930
+ act("fleet_virtual_power", "machines", "FL-16", "FLEET_VIRTUAL_ENABLED", "live", confirm("machine.admin"), {
1931
+ phase: "P3",
1932
+ route: POST("/api/fleet/nodes/{id}/virtual/{childId}/power"),
1933
+ cli: "fleet virtual power",
1934
+ waitable: true,
1935
+ confirmationNote: "plain to start; confirm to stop (an Agent's stop is held for the owner)"
1936
+ }),
1937
+ act("fleet_virtual_destroy", "machines", "FL-16", "FLEET_VIRTUAL_ENABLED", "live", typed("write.destructive"), {
1938
+ phase: "P3",
1939
+ route: POST("/api/fleet/nodes/{id}/virtual/{childId}/destroy"),
1940
+ cli: "fleet virtual destroy",
1941
+ waitable: true,
1942
+ alwaysHeld: true
1943
+ }),
1944
+ // ── cloud (FL-17) ── P1 shipped providers, create, power, destroy, usage; P2 the idle policy
1945
+ // (`PUT` answers the same as `PATCH`). A create, a power change and a destroy are held for the
1946
+ // owner's approval by the Agent tools (`agent-fleet-cloud-tools.ts`).
1947
+ read("fleet_cloud_list", "view", "FL-17", "FLEET_CLOUD_ENABLED", "live", {
1948
+ phase: "P3",
1949
+ route: GET("/api/fleet/cloud"),
1950
+ cli: "fleet cloud list"
1951
+ }),
1952
+ read("fleet_cloud_options", "view", "FL-17", "FLEET_CLOUD_ENABLED", "live", {
1953
+ phase: "P3",
1954
+ route: GET("/api/fleet/providers/{plugin}/options"),
1955
+ cli: "fleet cloud options"
1956
+ }),
1957
+ read("fleet_cloud_usage", "view", "FL-17", "FLEET_CLOUD_ENABLED", "live", {
1958
+ phase: "P3",
1959
+ route: GET("/api/fleet/cloud/usage"),
1960
+ cli: "fleet cloud usage"
1961
+ }),
1962
+ act("fleet_cloud_create", "machines", "FL-17", "FLEET_CLOUD_ENABLED", "live", confirm("spend.metered"), {
1963
+ phase: "P3",
1964
+ route: POST("/api/fleet/cloud"),
1965
+ cli: "fleet cloud create",
1966
+ waitable: true,
1967
+ alwaysHeld: true,
1968
+ confirmationNote: "confirm with the price (acknowledgedPriceCents); also machine.admin"
1969
+ }),
1970
+ act("fleet_cloud_power", "machines", "FL-17", "FLEET_CLOUD_ENABLED", "live", confirm("machine.admin"), {
1971
+ phase: "P3",
1972
+ route: POST("/api/fleet/cloud/{id}/power"),
1973
+ cli: "fleet cloud power",
1974
+ waitable: true,
1975
+ alwaysHeld: true
1976
+ }),
1977
+ act("fleet_cloud_destroy", "machines", "FL-17", "FLEET_CLOUD_ENABLED", "live", typed("write.destructive"), {
1978
+ phase: "P3",
1979
+ // FL-17 plan §5 — `DELETE /api/fleet/cloud/{id}` answers the same (an alias).
1980
+ route: POST("/api/fleet/cloud/{id}/destroy"),
1981
+ cli: "fleet cloud destroy",
1982
+ waitable: true,
1983
+ alwaysHeld: true
1984
+ }),
1985
+ act("fleet_cloud_idle_policy", "machines", "FL-17", "FLEET_CLOUD_ENABLED", "live", plain("machine.admin"), {
1986
+ phase: "P3",
1987
+ route: PATCH("/api/fleet/cloud/{id}/idle-policy"),
1988
+ cli: "fleet cloud idle-policy"
1989
+ }),
1990
+ // ── runners (FL-18) ── P1 shipped: list, install, start / stop / restart, remove. An install, a
1991
+ // stop, a restart and a remove asked by an Agent are held for the owner's approval
1992
+ // (`agent-fleet-runners-tools.ts`). The Actions jobs read and Cancel workflow run arrive with P2.
1993
+ read("fleet_runners_list", "view", "FL-18", "FLEET_ACTIONS_RUNNERS_ENABLED", "live", {
1994
+ phase: "P3",
1995
+ route: GET("/api/fleet/nodes/{id}/runners"),
1996
+ cli: "fleet runners list"
1997
+ }),
1998
+ read("fleet_runners_jobs", "view", "FL-18", "FLEET_ACTIONS_RUNNERS_ENABLED", "planned", {
1999
+ phase: "P3",
2000
+ route: GET("/api/fleet/runners/jobs"),
2001
+ cli: "fleet runners jobs"
2002
+ }),
2003
+ act(
2004
+ "fleet_runners_install",
2005
+ "machines",
2006
+ "FL-18",
2007
+ "FLEET_ACTIONS_RUNNERS_ENABLED",
2008
+ "live",
2009
+ confirm("machine.admin"),
2010
+ {
2011
+ phase: "P3",
2012
+ route: POST("/api/fleet/nodes/{id}/runners"),
2013
+ cli: "fleet runners install",
2014
+ waitable: true,
2015
+ alwaysHeld: true
2016
+ }
2017
+ ),
2018
+ act(
2019
+ "fleet_runners_action",
2020
+ "machines",
2021
+ "FL-18",
2022
+ "FLEET_ACTIONS_RUNNERS_ENABLED",
2023
+ "live",
2024
+ confirm("machine.admin"),
2025
+ {
2026
+ phase: "P3",
2027
+ route: POST("/api/fleet/nodes/{id}/runners/{runnerId}/{action}"),
2028
+ cli: "fleet runners action",
2029
+ waitable: true,
2030
+ confirmationNote: "plain to start; confirm to stop and restart (an Agent's stop or restart is held for the owner)"
2031
+ }
2032
+ ),
2033
+ act(
2034
+ "fleet_runners_remove",
2035
+ "machines",
2036
+ "FL-18",
2037
+ "FLEET_ACTIONS_RUNNERS_ENABLED",
2038
+ "live",
2039
+ typed("write.destructive"),
2040
+ {
2041
+ phase: "P3",
2042
+ route: POST("/api/fleet/nodes/{id}/runners/{runnerId}/remove"),
2043
+ cli: "fleet runners remove",
2044
+ waitable: true,
2045
+ alwaysHeld: true
2046
+ }
2047
+ ),
2048
+ act(
2049
+ "fleet_runners_cancel_run",
2050
+ "machines",
2051
+ "FL-18",
2052
+ "FLEET_ACTIONS_RUNNERS_ENABLED",
2053
+ "planned",
2054
+ confirm("machine.admin"),
2055
+ { phase: "P3", route: POST("/api/fleet/runners/jobs/cancel"), cli: "fleet runners cancel-run" }
2056
+ ),
2057
+ // ── usage (FL-20) ── P1 shipped: the Usage object (totals, by model, by computer, busiest
2058
+ // checkouts, sessions) every surface renders, read-only, with the payer sentence in `note`.
2059
+ read("fleet_usage_get", "view", "FL-20", "FLEET_USAGE_SCAN_ENABLED", "live", {
2060
+ phase: "P3",
2061
+ route: GET("/api/fleet/usage"),
2062
+ cli: "fleet usage"
2063
+ }),
2064
+ // ── operations (FL-02, FL-19) ──
2065
+ read("fleet_operations_get", "view", "FL-02", "FLEET_NODE_LINK_ENABLED", "live", {
2066
+ route: GET("/api/fleet/operations/{id}"),
2067
+ cli: "fleet operations get"
2068
+ }),
2069
+ read("fleet_operations_list", "view", "FL-19", "FLEET_NODE_LINK_ENABLED", "live", {
2070
+ route: GET("/api/fleet/operations"),
2071
+ cli: "fleet operations list"
2072
+ }),
2073
+ act("fleet_operations_cancel", "view", "FL-02", "FLEET_NODE_LINK_ENABLED", "live", plain("machine.run"), {
2074
+ route: DELETE("/api/fleet/operations/{id}"),
2075
+ cli: "fleet operations cancel"
2076
+ })
2077
+ ]);
2078
+ var BY_NAME = new Map(
2079
+ FLEET_TOOL_CATALOGUE.map((entry) => [entry.name, entry])
2080
+ );
2081
+ var FLEET_TOOL_COPY = Object.freeze({
2082
+ noCredential: (agent) => `Tools never carry a credential. ${agent} acts through the platform; the platform asks the computer.`,
2083
+ rungOff: (category, agent) => `'${category}' is Off for ${agent} \u2014 raise it on ${agent}'s Safety tab`,
2084
+ grantDenied: (tool, scope) => `${tool} is denied by a tool grant at ${scope} scope`,
2085
+ audience: (computer, audience, family) => `ask the owner of ${computer} to allow ${audience}: ${family}`,
2086
+ confirm: () => "call again with confirm: true",
2087
+ confirmName: (name) => `type the exact name: ${name}`,
2088
+ acknowledge: () => "call again with confirm: true and acknowledgeBlastRadius: true",
2089
+ killSwitch: () => "clear it under Settings \u2192 Fleet",
2090
+ permissionPromptHuman: () => "permission prompts are answered by people"
2091
+ });
2092
+ var FLEET_TOOL_CATEGORY_LABELS = Object.freeze({
2093
+ "read.internal": "Read inside the workspace",
2094
+ "write.internal": "Change things inside the workspace",
2095
+ "write.destructive": "Delete things",
2096
+ "publish.external": "Publish outside the workspace",
2097
+ "spend.metered": "Spend credits",
2098
+ "machine.run": "Run commands on a computer",
2099
+ "machine.admin": "Change a computer",
2100
+ "agent.fanout": "Hire agents and set schedules"
2101
+ });
2102
+ var FLEET_HELD_ACTION_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
2103
+ var FLEET_TOOL_FAMILY_CONSENT = Object.freeze({
2104
+ view: null,
2105
+ sessions: "work",
2106
+ desktop: "attend",
2107
+ logs: "manage",
2108
+ services: "manage",
2109
+ docker: "manage",
2110
+ processes: "manage",
2111
+ ports: "manage",
2112
+ files: "manage",
2113
+ commands: "manage",
2114
+ schedules: "manage",
2115
+ checkouts: "manage",
2116
+ machines: "manage"
2117
+ });
2118
+ var FLEET_CLI_EXIT = Object.freeze({ ok: 0, failed: 1, usage: 2, timeout: 124 });
2119
+ var FLEET_TOOL_FORBIDDEN_PATH_PREFIXES = Object.freeze([
2120
+ "/api/fleet/enroll",
2121
+ "/api/fleet/heartbeat",
2122
+ "/api/fleet/jobs",
2123
+ "/api/fleet/rotate-credential",
2124
+ "/api/fleet/link-token",
2125
+ "/api/fleet/nodes/enrollment-token",
2126
+ "/api/fleet/enrollment-tokens",
2127
+ "/api/internal/fleet"
2128
+ ]);
2129
+ var FLEET_TOOL_FORBIDDEN_PATH_FRAGMENTS = Object.freeze([
2130
+ "/attach-token",
2131
+ "/credential",
2132
+ "/rotate-credential"
2133
+ ]);
2134
+ var FLEET_VIRTUAL_SYSTEMS = [
2135
+ {
2136
+ id: "windows-11",
2137
+ kind: "vm",
2138
+ label: "Windows 11",
2139
+ family: "windows",
2140
+ arch: ["x64"],
2141
+ windowsEdition: "11",
2142
+ approxDiskGiB: 64,
2143
+ approxDownloadGiB: 6
2144
+ },
2145
+ {
2146
+ id: "windows-10",
2147
+ kind: "vm",
2148
+ label: "Windows 10",
2149
+ family: "windows",
2150
+ arch: ["x64"],
2151
+ windowsEdition: "10",
2152
+ approxDiskGiB: 64,
2153
+ approxDownloadGiB: 6
2154
+ },
2155
+ {
2156
+ id: "windows-server-2025",
2157
+ kind: "vm",
2158
+ label: "Windows Server 2025",
2159
+ family: "windows",
2160
+ arch: ["x64"],
2161
+ windowsEdition: "2025",
2162
+ approxDiskGiB: 64,
2163
+ approxDownloadGiB: 6
2164
+ },
2165
+ {
2166
+ id: "windows-server-2022",
2167
+ kind: "vm",
2168
+ label: "Windows Server 2022",
2169
+ family: "windows",
2170
+ arch: ["x64"],
2171
+ windowsEdition: "2022",
2172
+ approxDiskGiB: 64,
2173
+ approxDownloadGiB: 6
2174
+ },
2175
+ {
2176
+ id: "ubuntu-26.04",
2177
+ kind: "container",
2178
+ label: "Ubuntu 26.04",
2179
+ family: "ubuntu",
2180
+ arch: ["x64", "arm64"],
2181
+ approxDiskGiB: 3,
2182
+ approxDownloadGiB: 0.5
2183
+ },
2184
+ {
2185
+ id: "ubuntu-24.04",
2186
+ kind: "container",
2187
+ label: "Ubuntu 24.04",
2188
+ family: "ubuntu",
2189
+ arch: ["x64", "arm64"],
2190
+ approxDiskGiB: 3,
2191
+ approxDownloadGiB: 0.5
2192
+ },
2193
+ {
2194
+ id: "debian-13",
2195
+ kind: "container",
2196
+ label: "Debian 13",
2197
+ family: "debian",
2198
+ arch: ["x64", "arm64"],
2199
+ approxDiskGiB: 3,
2200
+ approxDownloadGiB: 0.5
2201
+ },
2202
+ {
2203
+ id: "fedora",
2204
+ kind: "container",
2205
+ label: "Fedora",
2206
+ family: "fedora",
2207
+ arch: ["x64", "arm64"],
2208
+ approxDiskGiB: 3,
2209
+ approxDownloadGiB: 0.6
2210
+ },
2211
+ {
2212
+ id: "alpine",
2213
+ kind: "container",
2214
+ label: "Alpine",
2215
+ family: "alpine",
2216
+ arch: ["x64", "arm64"],
2217
+ approxDiskGiB: 1,
2218
+ approxDownloadGiB: 0.2
2219
+ },
2220
+ {
2221
+ // Arch Linux publishes no official arm64 image (FR-6).
2222
+ id: "arch",
2223
+ kind: "container",
2224
+ label: "Arch Linux",
2225
+ family: "arch",
2226
+ arch: ["x64"],
2227
+ approxDiskGiB: 3,
2228
+ approxDownloadGiB: 0.7
2229
+ }
2230
+ ];
2231
+ var FLEET_VIRTUAL_SYSTEM_IDS = FLEET_VIRTUAL_SYSTEMS.map((system) => system.id);
2232
+ var FLEET_VIRTUAL_ENROLL_TIMEOUT_MS = 20 * 60 * 1e3;
2233
+ var FLEET_CLOUD_OPTIONS_CACHE_MS = 10 * 60 * 1e3;
2234
+ var HOUR_MS2 = 60 * 60 * 1e3;
2235
+ var FLEET_CLOUD_USAGE_FRESH_MS = 5 * 60 * 1e3;
2236
+ var FLEET_USAGE_SCAN_INTERVAL_MS = 15 * 60 * 1e3;
2237
+ var FLEET_USAGE_REPORT_MAX_BYTES = 192 * 1024;
2238
+ var FLEET_USAGE_ZERO_TOKENS = Object.freeze({
2239
+ in: 0,
2240
+ out: 0,
2241
+ cacheRead: 0,
2242
+ cacheWrite: 0
2243
+ });
2244
+ var FLEET_ACTIONS_RUNNERS_CLOSED_REFRESH_MS = 5 * 6e4;
1295
2245
  var EMAIL_INBOX_DEFAULT_DAILY_CAP = 100;
1296
2246
  var EMAIL_INBOX_BURST_SENDS = 10;
1297
2247
  var EMAIL_INBOX_BURST_RECIPIENTS = 20;
@@ -1320,7 +2270,7 @@ var EMAIL_SEND_CAP_FIELDS = [
1320
2270
  "workspaceMonthlySends"
1321
2271
  ];
1322
2272
  var INBOX_CAP_FIELD_SET = new Set(EMAIL_INBOX_CAP_FIELDS);
1323
- var DAY_MS2 = 24 * 60 * 60 * 1e3;
2273
+ var DAY_MS3 = 24 * 60 * 60 * 1e3;
1324
2274
  var PROMOTION_GATE_DECISION_GRACE_MS = 20 * 60 * 1e3;
1325
2275
  var RELEASE_VERIFY_ATTEMPT_INTERVAL_MS = 10 * 60 * 1e3;
1326
2276
  var RELEASE_VERIFY_BUDGET_MS = 8 * 60 * 60 * 1e3;
@@ -1526,8 +2476,8 @@ var BACKUP_DEFAULT_LIMITS = Object.freeze({
1526
2476
  /** Retries a storage write gets before the backup fails as `storage_unavailable`. */
1527
2477
  storageRetries: 3
1528
2478
  });
1529
- var HOUR_MS = 60 * 60 * 1e3;
1530
- var MINUTE_MS = 60 * 1e3;
2479
+ var HOUR_MS3 = 60 * 60 * 1e3;
2480
+ var MINUTE_MS2 = 60 * 1e3;
1531
2481
  var ACTION_CATEGORIES = Object.freeze([
1532
2482
  "read.internal",
1533
2483
  "read.external",
@@ -1834,13 +2784,16 @@ var INTEGRATION_SCOPES = [
1834
2784
  "events:read",
1835
2785
  "webhooks:manage",
1836
2786
  "links:write",
1837
- "merges:decide"
2787
+ "merges:decide",
2788
+ "decisions:individual"
1838
2789
  ];
1839
2790
  var INTEGRATION_MERGE_DECISION_SCOPE = "merges:decide";
2791
+ var INTEGRATION_INDIVIDUAL_DECISION_SCOPE = "decisions:individual";
1840
2792
  var INTEGRATION_OPT_IN_SCOPES = [
1841
2793
  "org:write",
1842
2794
  "email:write",
1843
- INTEGRATION_MERGE_DECISION_SCOPE
2795
+ INTEGRATION_MERGE_DECISION_SCOPE,
2796
+ INTEGRATION_INDIVIDUAL_DECISION_SCOPE
1844
2797
  ];
1845
2798
  var EVER_GAUZY_PRESET_SCOPES = INTEGRATION_SCOPES.filter(
1846
2799
  (scope) => !INTEGRATION_OPT_IN_SCOPES.includes(scope)
@@ -1998,7 +2951,23 @@ var PLUGIN_CAPABILITIES = {
1998
2951
  // `capabilities/domain-event-subscriber.interface.ts`. Appended last, so
1999
2952
  // every existing constant keeps its value and its position; no category is
2000
2953
  // added (a subscriber plugin keeps the category of what it otherwise is).
2001
- DOMAIN_EVENT_SUBSCRIBER: "domain-event-subscriber"
2954
+ DOMAIN_EVENT_SUBSCRIBER: "domain-event-subscriber",
2955
+ // Cloud computers (FL-17, CONTRACTS R-15) — plugins that create, power and
2956
+ // destroy machines at a cloud provider on the owner's own account and say
2957
+ // what they cost (`IMachineProviderPlugin`). The first plugin ships under
2958
+ // `packages/plugins/`. Consumed only through
2959
+ // `MachineProviderFacadeService`; see
2960
+ // `capabilities/machine-provider.interface.ts`. Appended **last**, so every
2961
+ // existing constant keeps its value and its position, and landed in the same
2962
+ // change as the `machine-provider` category in `plugin-manifest.types.ts`.
2963
+ MACHINE_PROVIDER: "machine-provider",
2964
+ // Actions runners on computers (FL-18, CONTRACTS R-14) — GitHub's self-hosted
2965
+ // runner API through the Ever Works GitHub App (`github-actions-runners`),
2966
+ // consumed only through `ActionsRunnersFacadeService`; see
2967
+ // `capabilities/actions-runners.interface.ts`. Appended last, so every
2968
+ // existing constant keeps its value and its position; no category is added
2969
+ // (the plugin is an `integration`, which exists).
2970
+ ACTIONS_RUNNERS: "actions-runners"
2002
2971
  };
2003
2972
  var ALL_PLUGIN_CAPABILITIES = Object.values(PLUGIN_CAPABILITIES);
2004
2973
  function initializePipelineState(stepDefinitions) {