@ever-works/activepieces-plugin 1.0.12 → 1.0.14

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 +954 -26
  2. package/dist/index.js +954 -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,9 +1154,106 @@ 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
+ });
1239
+ var FLEET_JOB_MAX_QUEUED_MAX_AGE_SEC = 7 * 24 * 60 * 60;
1240
+ var FLEET_AGENT_EXECUTION_MAX_INSTRUCTIONS_BYTES = 160 * 1024;
1241
+ var FLEET_AGENT_TASK_TIMELINE_MAX_BYTES = 48 * 1024;
1242
+ var FLEET_AGENT_TASK_TRANSCRIPT_MAX_BYTES = 64 * 1024;
1243
+ var FLEET_AGENT_TASK_QUESTION_MAX_FILE_BYTES = 64 * 1024;
1244
+ var FLEET_AGENT_TASK_QUESTION_MAX_CONTEXT_BYTES = 6 * 1024;
1166
1245
  var CONTROL_TYPES = new Set(FLEET_LINK_CONTROL_TYPES);
1167
1246
  var KIND_JSON = FLEET_LINK_FRAME_KINDS.JSON;
1168
1247
  var utf8Encoder = new TextEncoder();
1248
+ var FLEET_LINK_VIEWER_SLOW_BUFFER_BYTES = 8 * 1024 * 1024;
1249
+ var FLEET_LINK_VIEWER_MAX_BUFFER_BYTES = 32 * 1024 * 1024;
1250
+ var FLEET_LINK_VIEWER_FRAME_KINDS = [FLEET_LINK_FRAME_KINDS.ACK];
1251
+ var FLEET_MACHINE_OPERATION_MAX_MS = 60 * 6e4;
1252
+ var FLEET_LOGS_FOLLOW_BYTES_PER_SEC = 1024 * 1024;
1253
+ var FLEET_LOGS_PENDING_MAX_BYTES = 1024 * 1024;
1254
+ var FLEET_LOGS_MAX_FRAME_BYTES = 64 * 1024;
1255
+ var FLEET_LOGS_MAX_LINE_CHARS = 16 * 1024;
1256
+ var FLEET_LOGS_FILE_SCAN_MAX_BYTES = 8 * 1024 * 1024;
1169
1257
  var FLEET_MODEL_USAGE_LIMIT_FALLBACK_MS = 60 * 60 * 1e3;
1170
1258
  var FLEET_MODEL_USAGE_LIMIT_MIN_MS = 60 * 1e3;
1171
1259
  var FLEET_MODEL_USAGE_LIMIT_MAX_MS = 8 * 24 * 60 * 60 * 1e3;
@@ -1184,6 +1272,51 @@ var FLEET_HEALTH_DISK_CRITICAL_MARGIN_BYTES = 1024 ** 3;
1184
1272
  var FLEET_HEALTH_MAX_MIB = 2 ** 40;
1185
1273
  var FLEET_HEALTH_MAX_UPTIME_SEC = 100 * 365 * 24 * 60 * 60;
1186
1274
  var FLEET_HEALTH_BYTES_PER_MIB = 1024 * 1024;
1275
+ var MINUTE_MS = 6e4;
1276
+ var HOUR_MS = 60 * MINUTE_MS;
1277
+ var DAY_MS2 = 24 * HOUR_MS;
1278
+ var FLEET_HEALTH_RANGE_MS = {
1279
+ "1h": HOUR_MS,
1280
+ "24h": DAY_MS2,
1281
+ "7d": 7 * DAY_MS2,
1282
+ "90d": 90 * DAY_MS2
1283
+ };
1284
+ var FLEET_WAKE_RATE_WINDOW_MS = 5 * 6e4;
1285
+ var FLEET_PORT_PROBE_BODY_CAP = 64 * 1024;
1286
+ var FLEET_PORT_PREVIEW_MAX_MS = 60 * 6e4;
1287
+ var FLEET_PORT_TUNNEL_IDLE_MS = 10 * 6e4;
1288
+ var FLEET_PORT_TUNNEL_HARD_MS = 60 * 6e4;
1289
+ var FLEET_PORT_TUNNEL_CHUNK_BYTES = 64 * 1024;
1290
+ var FLEET_PORT_TUNNEL_MAX_HEADER_BYTES = 64 * 1024;
1291
+ var FLEET_WELL_KNOWN_PORTS = Object.freeze({
1292
+ 21: "ftp",
1293
+ 22: "ssh",
1294
+ 25: "smtp",
1295
+ 53: "dns",
1296
+ 110: "pop3",
1297
+ 143: "imap",
1298
+ 389: "ldap",
1299
+ 1433: "mssql",
1300
+ 1521: "oracle",
1301
+ 2375: "docker",
1302
+ 2376: "docker",
1303
+ 2379: "etcd",
1304
+ 3306: "mysql",
1305
+ 3389: "rdp",
1306
+ 4222: "nats",
1307
+ 5432: "postgres",
1308
+ 5672: "amqp",
1309
+ 5900: "vnc",
1310
+ 6379: "redis",
1311
+ 6443: "kubernetes",
1312
+ 7687: "neo4j",
1313
+ 9042: "cassandra",
1314
+ 9092: "kafka",
1315
+ 9200: "elasticsearch",
1316
+ 11211: "memcached",
1317
+ 15672: "rabbitmq",
1318
+ 27017: "mongo"
1319
+ });
1187
1320
  var FLEET_RUN_TOKEN_ROUTES = Object.freeze([
1188
1321
  // Works — reads, plus the settings update (its merge / check / command
1189
1322
  // fields are refused for run tokens by the Works controller).
@@ -1267,6 +1400,12 @@ var FLEET_RUN_TOKEN_ROUTES = Object.freeze([
1267
1400
  { method: "GET", pathPattern: "/api/fleet/runner-status" },
1268
1401
  { method: "GET", pathPattern: "/api/fleet/execution-preferences" },
1269
1402
  { method: "GET", pathPattern: "/api/fleet/agents/{agentId}/node-affinity" },
1403
+ // Session git & actions (FL-06 FR-18): an Agent session asks the platform to
1404
+ // open or update the pull request of ITS OWN checkout. The route refuses a
1405
+ // checkout that is not the token's session's, and the Agent's "may open pull
1406
+ // requests" permission applies; it never merges anything.
1407
+ { method: "GET", pathPattern: "/api/fleet/checkouts/{id}/pull-request" },
1408
+ { method: "POST", pathPattern: "/api/fleet/checkouts/{id}/pull-request" },
1270
1409
  // Agents — reads, plus cancel and pause (the safe direction).
1271
1410
  { method: "GET", pathPattern: "/api/agents" },
1272
1411
  { method: "GET", pathPattern: "/api/agents/{id}" },
@@ -1289,6 +1428,783 @@ var FLEET_RUN_TOKEN_ROUTE_SHAPES = FLEET_RUN_TOKEN_ROUTES.map((route) => ({
1289
1428
  method: route.method.toUpperCase(),
1290
1429
  shape: splitSegments(route.pathPattern).map((part) => /^\{[^}]+\}$/.test(part) ? "*" : part.toLowerCase())
1291
1430
  }));
1431
+ var FLEET_SESSION_STATES = ["starting", "working", "needs_you", "done", "idle", "ended"];
1432
+ var FLEET_SESSION_LIVE_STATES = FLEET_SESSION_STATES.filter(
1433
+ (state) => state !== "ended"
1434
+ );
1435
+ var FLEET_SESSION_SLOW_VIEWER_BYTES = 1024 * 1024;
1436
+ var FLEET_SESSION_DAEMON_IDLE_EXIT_MS = 5 * 6e4;
1437
+ var FLEET_SESSION_LAST_SCREEN_MAX_CHARS = 256 * 1024;
1438
+ var FLEET_AGENT_SESSION_QUEUED_TIMEOUT_MS = 10 * 6e4;
1439
+ var FLEET_PR_ENRICHMENT_RECENT_MS = 7 * 24 * 60 * 6e4;
1440
+ var FLEET_GIT_LINE_STALE_MS = 5 * 6e4;
1441
+ var FLEET_SESSION_IDLE_AFTER_MS = 30 * 6e4;
1442
+ var FLEET_SESSION_DECISION_STALE_MS = 24 * 60 * 6e4;
1443
+ var FLEET_SESSION_HOOK_BODY_MAX_BYTES = 64 * 1024;
1444
+ var FLEET_SESSION_HOOK_SPOOL_MAX_BYTES = 5 * 1024 * 1024;
1445
+ var FLEET_SESSION_HOOK_SPOOL_MAX_AGE_MS = 7 * 24 * 60 * 6e4;
1446
+ var FLEET_COMMAND_MAX_OUTPUT_BYTES = 10 * 1024 * 1024;
1447
+ var FLEET_COMMAND_STORED_EDGE_BYTES = 64 * 1024;
1448
+ var FLEET_COMMAND_DATA_CHUNK_BYTES = 64 * 1024;
1449
+ var FLEET_COMMAND_MAX_LENGTH = 8 * 1024;
1450
+ var FLEET_SCHEDULE_PROMPT_MAX_BYTES = 16 * 1024;
1451
+ var FLEET_SCHEDULE_BREAKER_UNDO_MS = 15 * 6e4;
1452
+ var MAX_SEARCH_DAYS = 366 * 8 + 1;
1453
+ function row(input) {
1454
+ const rest = input.name.slice("fleet_".length);
1455
+ const cut = rest.indexOf("_");
1456
+ const family = cut === -1 ? rest : rest.slice(0, cut);
1457
+ const verb = cut === -1 ? "" : rest.slice(cut + 1);
1458
+ return Object.freeze({ ...input, family, verb });
1459
+ }
1460
+ function read(name, permissionFamily, owner, flag, status, extra = {}) {
1461
+ return row({
1462
+ name,
1463
+ readOnly: true,
1464
+ category: "read.internal",
1465
+ permissionFamily,
1466
+ owner,
1467
+ phase: "P1",
1468
+ flag,
1469
+ status,
1470
+ ...extra
1471
+ });
1472
+ }
1473
+ function act(name, permissionFamily, owner, flag, status, annotation, extra = {}) {
1474
+ return row({ name, permissionFamily, owner, phase: "P2", flag, status, ...annotation, ...extra });
1475
+ }
1476
+ var plain = (category, destructive = false) => ({
1477
+ destructive,
1478
+ confirmationClass: "plain",
1479
+ category
1480
+ });
1481
+ var confirm = (category, destructive = true) => ({
1482
+ destructive,
1483
+ confirmationClass: "confirm",
1484
+ category
1485
+ });
1486
+ var typed = (category) => ({
1487
+ destructive: true,
1488
+ confirmationClass: "confirm-destructive",
1489
+ category
1490
+ });
1491
+ var GET = (path) => ({ method: "GET", path });
1492
+ var POST = (path) => ({ method: "POST", path });
1493
+ var PATCH = (path) => ({ method: "PATCH", path });
1494
+ var DELETE = (path) => ({ method: "DELETE", path });
1495
+ var FLEET_TOOL_CATALOGUE = Object.freeze([
1496
+ // ── status (FL-19) ──
1497
+ read("fleet_status", "view", "FL-19", "FLEET_ENABLED", "live", {
1498
+ route: GET("/api/fleet/status"),
1499
+ cli: "fleet status"
1500
+ }),
1501
+ // ── nodes (FL-19, FL-03, FL-15) ──
1502
+ read("fleet_nodes_list", "view", "FL-19", "FLEET_ENABLED", "live", {
1503
+ route: GET("/api/fleet/nodes"),
1504
+ cli: "fleet nodes list"
1505
+ }),
1506
+ read("fleet_nodes_get", "view", "FL-19", "FLEET_ENABLED", "live", {
1507
+ route: GET("/api/fleet/nodes/{id}"),
1508
+ cli: "fleet nodes get"
1509
+ }),
1510
+ read("fleet_nodes_health", "view", "FL-03", "FLEET_ENABLED", "live", {
1511
+ route: GET("/api/fleet/nodes/{id}/health"),
1512
+ cli: "fleet nodes health"
1513
+ }),
1514
+ read("fleet_nodes_needs_a_look", "view", "FL-03", "FLEET_ENABLED", "live", {
1515
+ route: GET("/api/fleet/nodes/{id}/needs-a-look"),
1516
+ cli: "fleet nodes needs-a-look"
1517
+ }),
1518
+ read("fleet_nodes_git_identity_get", "view", "FL-15", "FLEET_CHECKOUTS_ENABLED", "live", {
1519
+ route: GET("/api/fleet/nodes/{id}/git/identity"),
1520
+ cli: "fleet nodes git-identity"
1521
+ }),
1522
+ act("fleet_nodes_wake", "machines", "FL-03", "FLEET_ENABLED", "live", plain("machine.admin"), {
1523
+ route: POST("/api/fleet/nodes/{id}/wake"),
1524
+ cli: "fleet nodes wake"
1525
+ }),
1526
+ act(
1527
+ "fleet_nodes_git_identity_set",
1528
+ "commands",
1529
+ "FL-15",
1530
+ "FLEET_CHECKOUTS_ENABLED",
1531
+ "live",
1532
+ confirm("machine.admin", false),
1533
+ { route: POST("/api/fleet/nodes/{id}/git/identity"), cli: "fleet nodes git-identity --set" }
1534
+ ),
1535
+ // ── sessions (FL-04, FL-05, FL-06) ──
1536
+ read("fleet_sessions_list", "sessions", "FL-04", "FLEET_SESSIONS_ENABLED", "live", {
1537
+ route: GET("/api/fleet/sessions"),
1538
+ cli: "fleet sessions list"
1539
+ }),
1540
+ read("fleet_sessions_read", "sessions", "FL-04", "FLEET_SESSIONS_ENABLED", "live", {
1541
+ route: GET("/api/fleet/sessions/{id}"),
1542
+ cli: "fleet sessions read"
1543
+ }),
1544
+ read("fleet_sessions_question", "sessions", "FL-05", "FLEET_SESSIONS_ENABLED", "live", {
1545
+ route: GET("/api/fleet/sessions/{id}"),
1546
+ cli: "fleet sessions question"
1547
+ }),
1548
+ read("fleet_sessions_actions_list", "sessions", "FL-06", "FLEET_SESSIONS_ENABLED", "planned", {
1549
+ route: GET("/api/fleet/sessions/{id}/actions"),
1550
+ cli: "fleet sessions actions"
1551
+ }),
1552
+ act("fleet_sessions_start", "sessions", "FL-04", "FLEET_SESSIONS_ENABLED", "live", plain("machine.run"), {
1553
+ route: POST("/api/fleet/nodes/{id}/sessions"),
1554
+ cli: "fleet sessions start"
1555
+ }),
1556
+ act("fleet_sessions_send", "sessions", "FL-04", "FLEET_SESSIONS_ENABLED", "live", plain("machine.run")),
1557
+ act("fleet_sessions_answer", "sessions", "FL-05", "FLEET_SESSIONS_ENABLED", "live", confirm("machine.run", false), {
1558
+ route: POST("/api/fleet/sessions/{id}/answer"),
1559
+ cli: "fleet sessions answer",
1560
+ confirmationNote: "questions only; a permission prompt is answered by a person (CONTRACTS R-32)"
1561
+ }),
1562
+ act("fleet_sessions_rename", "sessions", "FL-04", "FLEET_SESSIONS_ENABLED", "live", plain("write.internal"), {
1563
+ route: PATCH("/api/fleet/sessions/{id}"),
1564
+ cli: "fleet sessions rename"
1565
+ }),
1566
+ act("fleet_sessions_end", "sessions", "FL-04", "FLEET_SESSIONS_ENABLED", "live", confirm("machine.run"), {
1567
+ route: POST("/api/fleet/sessions/{id}/end"),
1568
+ cli: "fleet sessions end"
1569
+ }),
1570
+ act("fleet_sessions_action", "sessions", "FL-06", "FLEET_SESSIONS_ENABLED", "planned", plain("machine.run"), {
1571
+ route: POST("/api/fleet/sessions/{id}/actions"),
1572
+ cli: "fleet sessions action"
1573
+ }),
1574
+ // ── desktop (FL-07, FL-11 paste) ──
1575
+ read("fleet_desktop_screenshot", "desktop", "FL-07", "FLEET_DESKTOP_ENABLED", "planned", {
1576
+ route: GET("/api/fleet/nodes/{id}/desktop/screenshot"),
1577
+ cli: "fleet desktop screenshot"
1578
+ }),
1579
+ read("fleet_desktop_displays", "desktop", "FL-07", "FLEET_DESKTOP_ENABLED", "planned", {
1580
+ route: GET("/api/fleet/nodes/{id}/desktop/displays"),
1581
+ cli: "fleet desktop displays"
1582
+ }),
1583
+ read("fleet_desktop_recordings_list", "desktop", "FL-07", "FLEET_DESKTOP_ENABLED", "planned", {
1584
+ route: GET("/api/fleet/nodes/{id}/desktop/recordings"),
1585
+ cli: "fleet desktop recordings"
1586
+ }),
1587
+ act("fleet_desktop_input", "desktop", "FL-07", "FLEET_DESKTOP_ENABLED", "planned", plain("machine.admin", true), {
1588
+ route: POST("/api/fleet/nodes/{id}/desktop/input"),
1589
+ cli: "fleet desktop input"
1590
+ }),
1591
+ act("fleet_desktop_set_display", "desktop", "FL-07", "FLEET_DESKTOP_ENABLED", "planned", plain("machine.admin"), {
1592
+ route: POST("/api/fleet/nodes/{id}/desktop/displays"),
1593
+ cli: "fleet desktop set-display"
1594
+ }),
1595
+ act("fleet_desktop_display_add", "desktop", "FL-07", "FLEET_DESKTOP_ENABLED", "planned", confirm("machine.admin"), {
1596
+ phase: "P3",
1597
+ route: POST("/api/fleet/nodes/{id}/desktop/displays/virtual"),
1598
+ cli: "fleet desktop display-add"
1599
+ }),
1600
+ act(
1601
+ "fleet_desktop_display_remove",
1602
+ "desktop",
1603
+ "FL-07",
1604
+ "FLEET_DESKTOP_ENABLED",
1605
+ "planned",
1606
+ confirm("machine.admin"),
1607
+ {
1608
+ phase: "P3",
1609
+ route: DELETE("/api/fleet/nodes/{id}/desktop/displays/virtual/{displayId}"),
1610
+ cli: "fleet desktop display-remove"
1611
+ }
1612
+ ),
1613
+ act(
1614
+ "fleet_desktop_paste",
1615
+ "desktop",
1616
+ "FL-11",
1617
+ "FLEET_MACHINE_FACTS_ENABLED",
1618
+ "planned",
1619
+ plain("machine.admin", true),
1620
+ {
1621
+ route: POST("/api/fleet/nodes/{id}/desktop/paste"),
1622
+ cli: "fleet desktop paste",
1623
+ confirmationNote: "denied unless a tool grant allows it (AW-15)"
1624
+ }
1625
+ ),
1626
+ // ── logs (FL-08) ──
1627
+ read("fleet_logs_sources", "logs", "FL-08", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1628
+ route: GET("/api/fleet/nodes/{id}/logs/sources"),
1629
+ cli: "fleet logs sources"
1630
+ }),
1631
+ read("fleet_logs_read", "logs", "FL-08", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1632
+ route: POST("/api/fleet/nodes/{id}/logs/read"),
1633
+ cli: "fleet logs read"
1634
+ }),
1635
+ // ── services (FL-09) ──
1636
+ read("fleet_services_list", "services", "FL-09", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1637
+ route: GET("/api/fleet/nodes/{id}/services"),
1638
+ cli: "fleet services list"
1639
+ }),
1640
+ act("fleet_services_action", "services", "FL-09", "FLEET_MACHINE_FACTS_ENABLED", "live", confirm("machine.admin"), {
1641
+ route: POST("/api/fleet/nodes/{id}/services/{name}/{action}"),
1642
+ cli: "fleet services action",
1643
+ waitable: true,
1644
+ confirmationNote: "confirm; blast-radius when the node warns it could cut the machine off"
1645
+ }),
1646
+ // ── processes (FL-09) ──
1647
+ read("fleet_processes_list", "processes", "FL-09", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1648
+ route: GET("/api/fleet/nodes/{id}/processes"),
1649
+ cli: "fleet processes list"
1650
+ }),
1651
+ act(
1652
+ "fleet_processes_signal",
1653
+ "processes",
1654
+ "FL-09",
1655
+ "FLEET_MACHINE_FACTS_ENABLED",
1656
+ "live",
1657
+ confirm("machine.admin"),
1658
+ { route: POST("/api/fleet/nodes/{id}/processes/{pid}/signal"), cli: "fleet processes signal" }
1659
+ ),
1660
+ // ── docker (FL-09) ──
1661
+ read("fleet_docker_containers_list", "docker", "FL-09", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1662
+ route: GET("/api/fleet/nodes/{id}/docker/containers"),
1663
+ cli: "fleet docker containers"
1664
+ }),
1665
+ read("fleet_docker_images_list", "docker", "FL-09", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1666
+ route: GET("/api/fleet/nodes/{id}/docker/images"),
1667
+ cli: "fleet docker images"
1668
+ }),
1669
+ read("fleet_docker_compose_list", "docker", "FL-09", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1670
+ route: GET("/api/fleet/nodes/{id}/docker/compose"),
1671
+ cli: "fleet docker compose"
1672
+ }),
1673
+ read("fleet_docker_compose_describe", "docker", "FL-09", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1674
+ cli: "fleet docker compose-describe"
1675
+ }),
1676
+ act(
1677
+ "fleet_docker_container_action",
1678
+ "docker",
1679
+ "FL-09",
1680
+ "FLEET_MACHINE_FACTS_ENABLED",
1681
+ "live",
1682
+ confirm("machine.admin"),
1683
+ {
1684
+ route: POST("/api/fleet/nodes/{id}/docker/containers/{cid}/{action}"),
1685
+ cli: "fleet docker container",
1686
+ waitable: true,
1687
+ confirmationNote: "confirm; remove is confirm-destructive"
1688
+ }
1689
+ ),
1690
+ act("fleet_docker_run", "docker", "FL-09", "FLEET_MACHINE_FACTS_ENABLED", "live", confirm("machine.admin", false), {
1691
+ route: POST("/api/fleet/nodes/{id}/docker/containers"),
1692
+ cli: "fleet docker run",
1693
+ waitable: true,
1694
+ alwaysHeld: true,
1695
+ confirmationNote: "an Agent proposes a run; a person types any secret values"
1696
+ }),
1697
+ act(
1698
+ "fleet_docker_image_action",
1699
+ "docker",
1700
+ "FL-09",
1701
+ "FLEET_MACHINE_FACTS_ENABLED",
1702
+ "live",
1703
+ confirm("machine.admin"),
1704
+ {
1705
+ route: POST("/api/fleet/nodes/{id}/docker/images/{iid}/{action}"),
1706
+ cli: "fleet docker image",
1707
+ waitable: true,
1708
+ confirmationNote: "pull is plain and not destructive; remove and prune confirm"
1709
+ }
1710
+ ),
1711
+ act(
1712
+ "fleet_docker_compose_action",
1713
+ "docker",
1714
+ "FL-09",
1715
+ "FLEET_MACHINE_FACTS_ENABLED",
1716
+ "live",
1717
+ confirm("machine.admin"),
1718
+ {
1719
+ route: POST("/api/fleet/nodes/{id}/docker/compose/{project}/{action}"),
1720
+ cli: "fleet docker compose-action",
1721
+ waitable: true,
1722
+ confirmationNote: "destructive for down"
1723
+ }
1724
+ ),
1725
+ act("fleet_docker_exec", "docker", "FL-09", "FLEET_MACHINE_FACTS_ENABLED", "planned", plain("machine.run"), {
1726
+ phase: "P3",
1727
+ cli: "fleet docker exec"
1728
+ }),
1729
+ // ── ports (FL-10) ──
1730
+ read("fleet_ports_list", "view", "FL-10", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1731
+ route: GET("/api/fleet/nodes/{id}/ports"),
1732
+ cli: "fleet ports list"
1733
+ }),
1734
+ act("fleet_ports_open", "ports", "FL-10", "FLEET_MACHINE_FACTS_ENABLED", "live", plain("machine.run"), {
1735
+ route: POST("/api/fleet/nodes/{id}/ports/{port}/open"),
1736
+ cli: "fleet ports open"
1737
+ }),
1738
+ act("fleet_ports_preview_open", "ports", "FL-10", "FLEET_PORT_TUNNEL_ENABLED", "live", plain("machine.run"), {
1739
+ route: POST("/api/fleet/nodes/{id}/ports/{port}/preview"),
1740
+ cli: "fleet ports preview"
1741
+ }),
1742
+ act("fleet_ports_preview_close", "ports", "FL-10", "FLEET_PORT_TUNNEL_ENABLED", "live", plain("machine.run"), {
1743
+ route: DELETE("/api/fleet/nodes/{id}/ports/{port}/preview"),
1744
+ cli: "fleet ports preview-close"
1745
+ }),
1746
+ // ── files (FL-11) ──
1747
+ // P1 (FL-11 lane log decision 15): the roots read joins the family, and the list's route is the
1748
+ // one FL-11 built (`…/files/list` — `…/files` is the family's prefix, not a route).
1749
+ read("fleet_files_roots", "files", "FL-11", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1750
+ route: GET("/api/fleet/nodes/{id}/files/roots"),
1751
+ cli: "fleet files roots"
1752
+ }),
1753
+ read("fleet_files_list", "files", "FL-11", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1754
+ route: GET("/api/fleet/nodes/{id}/files/list"),
1755
+ cli: "fleet files list"
1756
+ }),
1757
+ read("fleet_files_stat", "files", "FL-11", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1758
+ route: GET("/api/fleet/nodes/{id}/files/stat"),
1759
+ cli: "fleet files stat"
1760
+ }),
1761
+ read("fleet_files_read", "files", "FL-11", "FLEET_MACHINE_FACTS_ENABLED", "planned", {
1762
+ route: GET("/api/fleet/nodes/{id}/files/download"),
1763
+ cli: "fleet files get"
1764
+ }),
1765
+ act("fleet_files_write", "files", "FL-11", "FLEET_MACHINE_FACTS_ENABLED", "planned", confirm("machine.admin"), {
1766
+ route: POST("/api/fleet/nodes/{id}/files/upload"),
1767
+ cli: "fleet files put"
1768
+ }),
1769
+ act("fleet_files_copy", "files", "FL-11", "FLEET_MACHINE_FACTS_ENABLED", "live", confirm("machine.admin"), {
1770
+ route: POST("/api/fleet/nodes/{id}/files/copy"),
1771
+ cli: "fleet files cp",
1772
+ // FL-11 P2 (lane log decision 18): an Agent's copy is held for a person, like its delete.
1773
+ alwaysHeld: true
1774
+ }),
1775
+ act("fleet_files_delete", "files", "FL-11", "FLEET_MACHINE_FACTS_ENABLED", "live", typed("write.destructive"), {
1776
+ route: POST("/api/fleet/nodes/{id}/files/delete"),
1777
+ cli: "fleet files rm",
1778
+ alwaysHeld: true
1779
+ }),
1780
+ // ── commands (FL-12) ──
1781
+ read("fleet_commands_list", "commands", "FL-12", "FLEET_COMMANDS_ENABLED", "live", {
1782
+ route: GET("/api/fleet/commands"),
1783
+ cli: "fleet commands list"
1784
+ }),
1785
+ read("fleet_commands_get", "commands", "FL-12", "FLEET_COMMANDS_ENABLED", "live", {
1786
+ route: GET("/api/fleet/commands/{id}"),
1787
+ cli: "fleet commands get"
1788
+ }),
1789
+ act("fleet_commands_run", "commands", "FL-12", "FLEET_COMMANDS_ENABLED", "live", confirm("machine.run"), {
1790
+ route: POST("/api/fleet/commands"),
1791
+ cli: "fleet commands run",
1792
+ alwaysHeld: true
1793
+ }),
1794
+ act("fleet_commands_cancel", "commands", "FL-12", "FLEET_COMMANDS_ENABLED", "live", plain("machine.run"), {
1795
+ route: POST("/api/fleet/commands/{id}/cancel"),
1796
+ cli: "fleet commands cancel"
1797
+ }),
1798
+ // ── schedules (FL-13 P2: live — `apps/api/src/fleet/schedules/fleet-schedules.controller.ts`) ──
1799
+ read("fleet_schedules_list", "schedules", "FL-13", "FLEET_COMMANDS_ENABLED", "live", {
1800
+ route: GET("/api/fleet/schedules"),
1801
+ cli: "fleet schedules list"
1802
+ }),
1803
+ read("fleet_schedules_get", "schedules", "FL-13", "FLEET_COMMANDS_ENABLED", "live", {
1804
+ route: GET("/api/fleet/schedules/{id}"),
1805
+ cli: "fleet schedules get"
1806
+ }),
1807
+ read("fleet_schedules_runs", "schedules", "FL-13", "FLEET_COMMANDS_ENABLED", "live", {
1808
+ route: GET("/api/fleet/schedules/{id}/runs"),
1809
+ cli: "fleet schedules runs"
1810
+ }),
1811
+ act("fleet_schedules_create", "schedules", "FL-13", "FLEET_COMMANDS_ENABLED", "live", confirm("agent.fanout"), {
1812
+ route: POST("/api/fleet/schedules"),
1813
+ cli: "fleet schedules create"
1814
+ }),
1815
+ act("fleet_schedules_update", "schedules", "FL-13", "FLEET_COMMANDS_ENABLED", "live", confirm("agent.fanout"), {
1816
+ route: PATCH("/api/fleet/schedules/{id}"),
1817
+ cli: "fleet schedules update"
1818
+ }),
1819
+ act(
1820
+ "fleet_schedules_delete",
1821
+ "schedules",
1822
+ "FL-13",
1823
+ "FLEET_COMMANDS_ENABLED",
1824
+ "live",
1825
+ confirm("write.destructive"),
1826
+ { route: DELETE("/api/fleet/schedules/{id}"), cli: "fleet schedules delete" }
1827
+ ),
1828
+ act("fleet_schedules_run", "schedules", "FL-13", "FLEET_COMMANDS_ENABLED", "live", confirm("machine.run"), {
1829
+ route: POST("/api/fleet/schedules/{id}/run"),
1830
+ cli: "fleet schedules run"
1831
+ }),
1832
+ act("fleet_schedules_pause", "schedules", "FL-13", "FLEET_COMMANDS_ENABLED", "live", plain("agent.fanout"), {
1833
+ route: POST("/api/fleet/schedules/{id}/pause"),
1834
+ cli: "fleet schedules pause"
1835
+ }),
1836
+ act("fleet_schedules_resume", "schedules", "FL-13", "FLEET_COMMANDS_ENABLED", "live", plain("agent.fanout"), {
1837
+ route: POST("/api/fleet/schedules/{id}/resume"),
1838
+ cli: "fleet schedules resume"
1839
+ }),
1840
+ // ── checkouts (FL-14, FL-06) ──
1841
+ read("fleet_checkouts_list", "checkouts", "FL-14", "FLEET_CHECKOUTS_ENABLED", "live", {
1842
+ route: GET("/api/fleet/checkouts"),
1843
+ cli: "fleet checkouts list"
1844
+ }),
1845
+ read("fleet_checkouts_get", "checkouts", "FL-14", "FLEET_CHECKOUTS_ENABLED", "live", {
1846
+ route: GET("/api/fleet/checkouts/{id}"),
1847
+ cli: "fleet checkouts get"
1848
+ }),
1849
+ read("fleet_checkouts_changes", "checkouts", "FL-06", "FLEET_CHECKOUTS_ENABLED", "planned", {
1850
+ route: GET("/api/fleet/checkouts/{id}/changes"),
1851
+ cli: "fleet checkouts changes"
1852
+ }),
1853
+ act("fleet_checkouts_create", "checkouts", "FL-14", "FLEET_CHECKOUTS_ENABLED", "live", plain("machine.run"), {
1854
+ route: POST("/api/fleet/checkouts"),
1855
+ cli: "fleet checkouts create",
1856
+ waitable: true
1857
+ }),
1858
+ act("fleet_checkouts_sync", "checkouts", "FL-14", "FLEET_CHECKOUTS_ENABLED", "live", plain("machine.run"), {
1859
+ route: POST("/api/fleet/checkouts/{id}/sync"),
1860
+ cli: "fleet checkouts sync",
1861
+ waitable: true,
1862
+ confirmationNote: "plain for fetch; confirm for pull and push"
1863
+ }),
1864
+ act(
1865
+ "fleet_checkouts_archive",
1866
+ "checkouts",
1867
+ "FL-14",
1868
+ "FLEET_CHECKOUTS_ENABLED",
1869
+ "live",
1870
+ confirm("machine.run", false),
1871
+ { route: POST("/api/fleet/checkouts/{id}/archive"), cli: "fleet checkouts archive" }
1872
+ ),
1873
+ act(
1874
+ "fleet_checkouts_delete",
1875
+ "checkouts",
1876
+ "FL-14",
1877
+ "FLEET_CHECKOUTS_ENABLED",
1878
+ "live",
1879
+ confirm("write.destructive"),
1880
+ {
1881
+ route: DELETE("/api/fleet/checkouts/{id}"),
1882
+ cli: "fleet checkouts delete",
1883
+ confirmationNote: "confirm; confirm-destructive when it has uncommitted changes"
1884
+ }
1885
+ ),
1886
+ act(
1887
+ "fleet_checkouts_open_pull_request",
1888
+ "checkouts",
1889
+ "FL-06",
1890
+ "FLEET_CHECKOUTS_ENABLED",
1891
+ "planned",
1892
+ plain("publish.external"),
1893
+ { route: POST("/api/fleet/checkouts/{id}/pull-request"), cli: "fleet checkouts pull-request" }
1894
+ ),
1895
+ // ── tasks (FL-15) ── the hand-off itself is `fleet_sessions_start` with `taskId`
1896
+ read("fleet_tasks_handoff_options", "sessions", "FL-15", "FLEET_CHECKOUTS_ENABLED", "live", {
1897
+ route: GET("/api/fleet/tasks/{taskId}/handoff-options"),
1898
+ cli: "fleet tasks handoff-options"
1899
+ }),
1900
+ // ── virtual (FL-16) ── P1 shipped: Containers. A create, a stop and a destroy are held for
1901
+ // the owner's approval by the Agent tools (`agent-fleet-virtual-tools.ts`).
1902
+ read("fleet_virtual_list", "view", "FL-16", "FLEET_VIRTUAL_ENABLED", "live", {
1903
+ phase: "P3",
1904
+ route: GET("/api/fleet/nodes/{id}/virtual"),
1905
+ cli: "fleet virtual list"
1906
+ }),
1907
+ read("fleet_virtual_options", "view", "FL-16", "FLEET_VIRTUAL_ENABLED", "live", {
1908
+ phase: "P3",
1909
+ route: GET("/api/fleet/nodes/{id}/virtual/options"),
1910
+ cli: "fleet virtual options"
1911
+ }),
1912
+ act("fleet_virtual_create", "machines", "FL-16", "FLEET_VIRTUAL_ENABLED", "live", confirm("machine.admin"), {
1913
+ phase: "P3",
1914
+ route: POST("/api/fleet/nodes/{id}/virtual"),
1915
+ cli: "fleet virtual create",
1916
+ waitable: true,
1917
+ alwaysHeld: true
1918
+ }),
1919
+ act("fleet_virtual_power", "machines", "FL-16", "FLEET_VIRTUAL_ENABLED", "live", confirm("machine.admin"), {
1920
+ phase: "P3",
1921
+ route: POST("/api/fleet/nodes/{id}/virtual/{childId}/power"),
1922
+ cli: "fleet virtual power",
1923
+ waitable: true,
1924
+ confirmationNote: "plain to start; confirm to stop (an Agent's stop is held for the owner)"
1925
+ }),
1926
+ act("fleet_virtual_destroy", "machines", "FL-16", "FLEET_VIRTUAL_ENABLED", "live", typed("write.destructive"), {
1927
+ phase: "P3",
1928
+ route: POST("/api/fleet/nodes/{id}/virtual/{childId}/destroy"),
1929
+ cli: "fleet virtual destroy",
1930
+ waitable: true,
1931
+ alwaysHeld: true
1932
+ }),
1933
+ // ── cloud (FL-17) ── P1 shipped: providers, create, power, destroy, usage. A create, a power
1934
+ // change and a destroy are held for the owner's approval by the Agent tools
1935
+ // (`agent-fleet-cloud-tools.ts`); the idle policy arrives with P2.
1936
+ read("fleet_cloud_list", "view", "FL-17", "FLEET_CLOUD_ENABLED", "live", {
1937
+ phase: "P3",
1938
+ route: GET("/api/fleet/cloud"),
1939
+ cli: "fleet cloud list"
1940
+ }),
1941
+ read("fleet_cloud_options", "view", "FL-17", "FLEET_CLOUD_ENABLED", "live", {
1942
+ phase: "P3",
1943
+ route: GET("/api/fleet/providers/{plugin}/options"),
1944
+ cli: "fleet cloud options"
1945
+ }),
1946
+ read("fleet_cloud_usage", "view", "FL-17", "FLEET_CLOUD_ENABLED", "live", {
1947
+ phase: "P3",
1948
+ route: GET("/api/fleet/cloud/usage"),
1949
+ cli: "fleet cloud usage"
1950
+ }),
1951
+ act("fleet_cloud_create", "machines", "FL-17", "FLEET_CLOUD_ENABLED", "live", confirm("spend.metered"), {
1952
+ phase: "P3",
1953
+ route: POST("/api/fleet/cloud"),
1954
+ cli: "fleet cloud create",
1955
+ waitable: true,
1956
+ alwaysHeld: true,
1957
+ confirmationNote: "confirm with the price (acknowledgedPriceCents); also machine.admin"
1958
+ }),
1959
+ act("fleet_cloud_power", "machines", "FL-17", "FLEET_CLOUD_ENABLED", "live", confirm("machine.admin"), {
1960
+ phase: "P3",
1961
+ route: POST("/api/fleet/cloud/{id}/power"),
1962
+ cli: "fleet cloud power",
1963
+ waitable: true,
1964
+ alwaysHeld: true
1965
+ }),
1966
+ act("fleet_cloud_destroy", "machines", "FL-17", "FLEET_CLOUD_ENABLED", "live", typed("write.destructive"), {
1967
+ phase: "P3",
1968
+ // FL-17 plan §5 — `DELETE /api/fleet/cloud/{id}` answers the same (an alias).
1969
+ route: POST("/api/fleet/cloud/{id}/destroy"),
1970
+ cli: "fleet cloud destroy",
1971
+ waitable: true,
1972
+ alwaysHeld: true
1973
+ }),
1974
+ act("fleet_cloud_idle_policy", "machines", "FL-17", "FLEET_CLOUD_ENABLED", "planned", plain("machine.admin"), {
1975
+ phase: "P3",
1976
+ route: PATCH("/api/fleet/cloud/{id}/idle-policy"),
1977
+ cli: "fleet cloud idle-policy"
1978
+ }),
1979
+ // ── runners (FL-18) ──
1980
+ read("fleet_runners_list", "view", "FL-18", "FLEET_ACTIONS_RUNNERS_ENABLED", "planned", {
1981
+ phase: "P3",
1982
+ route: GET("/api/fleet/nodes/{id}/runners"),
1983
+ cli: "fleet runners list"
1984
+ }),
1985
+ read("fleet_runners_jobs", "view", "FL-18", "FLEET_ACTIONS_RUNNERS_ENABLED", "planned", {
1986
+ phase: "P3",
1987
+ route: GET("/api/fleet/runners/jobs"),
1988
+ cli: "fleet runners jobs"
1989
+ }),
1990
+ act(
1991
+ "fleet_runners_install",
1992
+ "machines",
1993
+ "FL-18",
1994
+ "FLEET_ACTIONS_RUNNERS_ENABLED",
1995
+ "planned",
1996
+ confirm("machine.admin"),
1997
+ { phase: "P3", route: POST("/api/fleet/nodes/{id}/runners"), cli: "fleet runners install", waitable: true }
1998
+ ),
1999
+ act(
2000
+ "fleet_runners_action",
2001
+ "machines",
2002
+ "FL-18",
2003
+ "FLEET_ACTIONS_RUNNERS_ENABLED",
2004
+ "planned",
2005
+ confirm("machine.admin"),
2006
+ {
2007
+ phase: "P3",
2008
+ route: POST("/api/fleet/nodes/{id}/runners/{runnerId}/{action}"),
2009
+ cli: "fleet runners action",
2010
+ waitable: true,
2011
+ confirmationNote: "plain to start; confirm to stop and restart"
2012
+ }
2013
+ ),
2014
+ act(
2015
+ "fleet_runners_remove",
2016
+ "machines",
2017
+ "FL-18",
2018
+ "FLEET_ACTIONS_RUNNERS_ENABLED",
2019
+ "planned",
2020
+ typed("write.destructive"),
2021
+ { phase: "P3", route: DELETE("/api/fleet/nodes/{id}/runners/{runnerId}"), cli: "fleet runners remove" }
2022
+ ),
2023
+ act(
2024
+ "fleet_runners_cancel_run",
2025
+ "machines",
2026
+ "FL-18",
2027
+ "FLEET_ACTIONS_RUNNERS_ENABLED",
2028
+ "planned",
2029
+ confirm("machine.admin"),
2030
+ { phase: "P3", route: POST("/api/fleet/runners/jobs/{jobId}/cancel"), cli: "fleet runners cancel-run" }
2031
+ ),
2032
+ // ── usage (FL-20) ──
2033
+ read("fleet_usage_get", "view", "FL-20", "FLEET_USAGE_SCAN_ENABLED", "planned", {
2034
+ route: GET("/api/fleet/usage"),
2035
+ cli: "fleet usage"
2036
+ }),
2037
+ // ── operations (FL-02, FL-19) ──
2038
+ read("fleet_operations_get", "view", "FL-02", "FLEET_NODE_LINK_ENABLED", "live", {
2039
+ route: GET("/api/fleet/operations/{id}"),
2040
+ cli: "fleet operations get"
2041
+ }),
2042
+ read("fleet_operations_list", "view", "FL-19", "FLEET_NODE_LINK_ENABLED", "live", {
2043
+ route: GET("/api/fleet/operations"),
2044
+ cli: "fleet operations list"
2045
+ }),
2046
+ act("fleet_operations_cancel", "view", "FL-02", "FLEET_NODE_LINK_ENABLED", "live", plain("machine.run"), {
2047
+ route: DELETE("/api/fleet/operations/{id}"),
2048
+ cli: "fleet operations cancel"
2049
+ })
2050
+ ]);
2051
+ var BY_NAME = new Map(
2052
+ FLEET_TOOL_CATALOGUE.map((entry) => [entry.name, entry])
2053
+ );
2054
+ var FLEET_TOOL_COPY = Object.freeze({
2055
+ noCredential: (agent) => `Tools never carry a credential. ${agent} acts through the platform; the platform asks the computer.`,
2056
+ rungOff: (category, agent) => `'${category}' is Off for ${agent} \u2014 raise it on ${agent}'s Safety tab`,
2057
+ grantDenied: (tool, scope) => `${tool} is denied by a tool grant at ${scope} scope`,
2058
+ audience: (computer, audience, family) => `ask the owner of ${computer} to allow ${audience}: ${family}`,
2059
+ confirm: () => "call again with confirm: true",
2060
+ confirmName: (name) => `type the exact name: ${name}`,
2061
+ acknowledge: () => "call again with confirm: true and acknowledgeBlastRadius: true",
2062
+ killSwitch: () => "clear it under Settings \u2192 Fleet",
2063
+ permissionPromptHuman: () => "permission prompts are answered by people"
2064
+ });
2065
+ var FLEET_TOOL_CATEGORY_LABELS = Object.freeze({
2066
+ "read.internal": "Read inside the workspace",
2067
+ "write.internal": "Change things inside the workspace",
2068
+ "write.destructive": "Delete things",
2069
+ "publish.external": "Publish outside the workspace",
2070
+ "spend.metered": "Spend credits",
2071
+ "machine.run": "Run commands on a computer",
2072
+ "machine.admin": "Change a computer",
2073
+ "agent.fanout": "Hire agents and set schedules"
2074
+ });
2075
+ var FLEET_HELD_ACTION_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
2076
+ var FLEET_TOOL_FAMILY_CONSENT = Object.freeze({
2077
+ view: null,
2078
+ sessions: "work",
2079
+ desktop: "attend",
2080
+ logs: "manage",
2081
+ services: "manage",
2082
+ docker: "manage",
2083
+ processes: "manage",
2084
+ ports: "manage",
2085
+ files: "manage",
2086
+ commands: "manage",
2087
+ schedules: "manage",
2088
+ checkouts: "manage",
2089
+ machines: "manage"
2090
+ });
2091
+ var FLEET_CLI_EXIT = Object.freeze({ ok: 0, failed: 1, usage: 2, timeout: 124 });
2092
+ var FLEET_TOOL_FORBIDDEN_PATH_PREFIXES = Object.freeze([
2093
+ "/api/fleet/enroll",
2094
+ "/api/fleet/heartbeat",
2095
+ "/api/fleet/jobs",
2096
+ "/api/fleet/rotate-credential",
2097
+ "/api/fleet/link-token",
2098
+ "/api/fleet/nodes/enrollment-token",
2099
+ "/api/fleet/enrollment-tokens",
2100
+ "/api/internal/fleet"
2101
+ ]);
2102
+ var FLEET_TOOL_FORBIDDEN_PATH_FRAGMENTS = Object.freeze([
2103
+ "/attach-token",
2104
+ "/credential",
2105
+ "/rotate-credential"
2106
+ ]);
2107
+ var FLEET_VIRTUAL_SYSTEMS = [
2108
+ {
2109
+ id: "windows-11",
2110
+ kind: "vm",
2111
+ label: "Windows 11",
2112
+ family: "windows",
2113
+ arch: ["x64"],
2114
+ windowsEdition: "11",
2115
+ approxDiskGiB: 64,
2116
+ approxDownloadGiB: 6
2117
+ },
2118
+ {
2119
+ id: "windows-10",
2120
+ kind: "vm",
2121
+ label: "Windows 10",
2122
+ family: "windows",
2123
+ arch: ["x64"],
2124
+ windowsEdition: "10",
2125
+ approxDiskGiB: 64,
2126
+ approxDownloadGiB: 6
2127
+ },
2128
+ {
2129
+ id: "windows-server-2025",
2130
+ kind: "vm",
2131
+ label: "Windows Server 2025",
2132
+ family: "windows",
2133
+ arch: ["x64"],
2134
+ windowsEdition: "2025",
2135
+ approxDiskGiB: 64,
2136
+ approxDownloadGiB: 6
2137
+ },
2138
+ {
2139
+ id: "windows-server-2022",
2140
+ kind: "vm",
2141
+ label: "Windows Server 2022",
2142
+ family: "windows",
2143
+ arch: ["x64"],
2144
+ windowsEdition: "2022",
2145
+ approxDiskGiB: 64,
2146
+ approxDownloadGiB: 6
2147
+ },
2148
+ {
2149
+ id: "ubuntu-26.04",
2150
+ kind: "container",
2151
+ label: "Ubuntu 26.04",
2152
+ family: "ubuntu",
2153
+ arch: ["x64", "arm64"],
2154
+ approxDiskGiB: 3,
2155
+ approxDownloadGiB: 0.5
2156
+ },
2157
+ {
2158
+ id: "ubuntu-24.04",
2159
+ kind: "container",
2160
+ label: "Ubuntu 24.04",
2161
+ family: "ubuntu",
2162
+ arch: ["x64", "arm64"],
2163
+ approxDiskGiB: 3,
2164
+ approxDownloadGiB: 0.5
2165
+ },
2166
+ {
2167
+ id: "debian-13",
2168
+ kind: "container",
2169
+ label: "Debian 13",
2170
+ family: "debian",
2171
+ arch: ["x64", "arm64"],
2172
+ approxDiskGiB: 3,
2173
+ approxDownloadGiB: 0.5
2174
+ },
2175
+ {
2176
+ id: "fedora",
2177
+ kind: "container",
2178
+ label: "Fedora",
2179
+ family: "fedora",
2180
+ arch: ["x64", "arm64"],
2181
+ approxDiskGiB: 3,
2182
+ approxDownloadGiB: 0.6
2183
+ },
2184
+ {
2185
+ id: "alpine",
2186
+ kind: "container",
2187
+ label: "Alpine",
2188
+ family: "alpine",
2189
+ arch: ["x64", "arm64"],
2190
+ approxDiskGiB: 1,
2191
+ approxDownloadGiB: 0.2
2192
+ },
2193
+ {
2194
+ // Arch Linux publishes no official arm64 image (FR-6).
2195
+ id: "arch",
2196
+ kind: "container",
2197
+ label: "Arch Linux",
2198
+ family: "arch",
2199
+ arch: ["x64"],
2200
+ approxDiskGiB: 3,
2201
+ approxDownloadGiB: 0.7
2202
+ }
2203
+ ];
2204
+ var FLEET_VIRTUAL_SYSTEM_IDS = FLEET_VIRTUAL_SYSTEMS.map((system) => system.id);
2205
+ var FLEET_VIRTUAL_ENROLL_TIMEOUT_MS = 20 * 60 * 1e3;
2206
+ var FLEET_CLOUD_OPTIONS_CACHE_MS = 10 * 60 * 1e3;
2207
+ var HOUR_MS2 = 60 * 60 * 1e3;
1292
2208
  var EMAIL_INBOX_DEFAULT_DAILY_CAP = 100;
1293
2209
  var EMAIL_INBOX_BURST_SENDS = 10;
1294
2210
  var EMAIL_INBOX_BURST_RECIPIENTS = 20;
@@ -1317,7 +2233,7 @@ var EMAIL_SEND_CAP_FIELDS = [
1317
2233
  "workspaceMonthlySends"
1318
2234
  ];
1319
2235
  var INBOX_CAP_FIELD_SET = new Set(EMAIL_INBOX_CAP_FIELDS);
1320
- var DAY_MS2 = 24 * 60 * 60 * 1e3;
2236
+ var DAY_MS3 = 24 * 60 * 60 * 1e3;
1321
2237
  var PROMOTION_GATE_DECISION_GRACE_MS = 20 * 60 * 1e3;
1322
2238
  var RELEASE_VERIFY_ATTEMPT_INTERVAL_MS = 10 * 60 * 1e3;
1323
2239
  var RELEASE_VERIFY_BUDGET_MS = 8 * 60 * 60 * 1e3;
@@ -1523,8 +2439,8 @@ var BACKUP_DEFAULT_LIMITS = Object.freeze({
1523
2439
  /** Retries a storage write gets before the backup fails as `storage_unavailable`. */
1524
2440
  storageRetries: 3
1525
2441
  });
1526
- var HOUR_MS = 60 * 60 * 1e3;
1527
- var MINUTE_MS = 60 * 1e3;
2442
+ var HOUR_MS3 = 60 * 60 * 1e3;
2443
+ var MINUTE_MS2 = 60 * 1e3;
1528
2444
  var ACTION_CATEGORIES = Object.freeze([
1529
2445
  "read.internal",
1530
2446
  "read.external",
@@ -1831,13 +2747,16 @@ var INTEGRATION_SCOPES = [
1831
2747
  "events:read",
1832
2748
  "webhooks:manage",
1833
2749
  "links:write",
1834
- "merges:decide"
2750
+ "merges:decide",
2751
+ "decisions:individual"
1835
2752
  ];
1836
2753
  var INTEGRATION_MERGE_DECISION_SCOPE = "merges:decide";
2754
+ var INTEGRATION_INDIVIDUAL_DECISION_SCOPE = "decisions:individual";
1837
2755
  var INTEGRATION_OPT_IN_SCOPES = [
1838
2756
  "org:write",
1839
2757
  "email:write",
1840
- INTEGRATION_MERGE_DECISION_SCOPE
2758
+ INTEGRATION_MERGE_DECISION_SCOPE,
2759
+ INTEGRATION_INDIVIDUAL_DECISION_SCOPE
1841
2760
  ];
1842
2761
  var EVER_GAUZY_PRESET_SCOPES = INTEGRATION_SCOPES.filter(
1843
2762
  (scope) => !INTEGRATION_OPT_IN_SCOPES.includes(scope)
@@ -1995,7 +2914,16 @@ var PLUGIN_CAPABILITIES = {
1995
2914
  // `capabilities/domain-event-subscriber.interface.ts`. Appended last, so
1996
2915
  // every existing constant keeps its value and its position; no category is
1997
2916
  // added (a subscriber plugin keeps the category of what it otherwise is).
1998
- DOMAIN_EVENT_SUBSCRIBER: "domain-event-subscriber"
2917
+ DOMAIN_EVENT_SUBSCRIBER: "domain-event-subscriber",
2918
+ // Cloud computers (FL-17, CONTRACTS R-15) — plugins that create, power and
2919
+ // destroy machines at a cloud provider on the owner's own account and say
2920
+ // what they cost (`IMachineProviderPlugin`). The first plugin ships under
2921
+ // `packages/plugins/`. Consumed only through
2922
+ // `MachineProviderFacadeService`; see
2923
+ // `capabilities/machine-provider.interface.ts`. Appended **last**, so every
2924
+ // existing constant keeps its value and its position, and landed in the same
2925
+ // change as the `machine-provider` category in `plugin-manifest.types.ts`.
2926
+ MACHINE_PROVIDER: "machine-provider"
1999
2927
  };
2000
2928
  var ALL_PLUGIN_CAPABILITIES = Object.values(PLUGIN_CAPABILITIES);
2001
2929
  function initializePipelineState(stepDefinitions) {