@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.cjs CHANGED
@@ -485,6 +485,13 @@ var TASK_BOARD_STATUS_COLUMNS = TASK_BOARD_STATUSES.map((status) => ({
485
485
  terminal: TASK_BOARD_TERMINAL_STATUSES.includes(status),
486
486
  toggleOnly: false
487
487
  }));
488
+ var TASK_RESERVED_LABELS = Object.freeze([
489
+ "awaiting-owner",
490
+ "app-provision",
491
+ "release:promotion",
492
+ "release:revert"
493
+ ]);
494
+ var TASK_RESERVED_LABEL_PREFIXES = Object.freeze(["release:", "provision-attempt-", "fleet:"]);
488
495
  var PLATFORM_DEFAULT_MERGE_POLICY = Object.freeze({
489
496
  allowAgentMerge: false,
490
497
  requireGreenGate: true,
@@ -1115,26 +1122,10 @@ var FLEET_AGENT_CREDENTIAL_FAMILIES = [
1115
1122
  var FLEET_AGENT_CREDENTIAL_ENV_NAMES = FLEET_AGENT_CREDENTIAL_FAMILIES.flatMap(
1116
1123
  (family) => family.envNames
1117
1124
  );
1118
- var FLEET_RUN_ENV_FILE_MAX_CONTENT_BYTES = 32 * 1024;
1119
- var FLEET_RUN_ENV_FILES_MAX_TOTAL_BYTES = 256 * 1024;
1120
- var FLEET_JOB_MAX_PAYLOAD_BYTES = 256 * 1024;
1121
- var FLEET_JOB_MAX_RESULT_BYTES = 256 * 1024;
1122
- var FLEET_JOB_DEFAULT_QUEUED_MAX_AGE_SEC = Object.freeze({
1123
- "agent-task": 24 * 60 * 60,
1124
- "acceptance-checks": 2 * 60 * 60,
1125
- "browser-check": 2 * 60 * 60,
1126
- // A live view nobody claimed is abandoned by the session service after
1127
- // 40 seconds, which cancels its job there and then. The queue SLA is only
1128
- // the backstop behind that, so it deliberately does not undercut the
1129
- // shortest existing default (the fallback an unknown kind fails closed to).
1130
- "computer-session": 2 * 60 * 60
1131
- });
1132
- var FLEET_JOB_MAX_QUEUED_MAX_AGE_SEC = 7 * 24 * 60 * 60;
1133
- var FLEET_AGENT_EXECUTION_MAX_INSTRUCTIONS_BYTES = 160 * 1024;
1134
- var FLEET_AGENT_TASK_TIMELINE_MAX_BYTES = 48 * 1024;
1135
- var FLEET_AGENT_TASK_TRANSCRIPT_MAX_BYTES = 64 * 1024;
1136
- var FLEET_AGENT_TASK_QUESTION_MAX_FILE_BYTES = 64 * 1024;
1137
- var FLEET_AGENT_TASK_QUESTION_MAX_CONTEXT_BYTES = 6 * 1024;
1125
+ var FLEET_CHECKOUT_LISTED_REFRESH_MS = 5 * 6e4;
1126
+ var FLEET_CHECKOUT_RECONCILE_MS = 10 * 6e4;
1127
+ var FLEET_CHECKOUT_CREATING_STALE_MS = 10 * 6e4;
1128
+ var FLEET_CHECKOUT_BIN_PURGE_AFTER_MS = 30 * 24 * 60 * 6e4;
1138
1129
  var FLEET_LINK_MAX_FRAME_BYTES = 16 * 1024 * 1024;
1139
1130
  var FLEET_LINK_FRAME_HEADER_BYTES = 9;
1140
1131
  var FLEET_LINK_MAX_PAYLOAD_BYTES = FLEET_LINK_MAX_FRAME_BYTES - FLEET_LINK_FRAME_HEADER_BYTES;
@@ -1190,9 +1181,106 @@ var FLEET_LINK_CONTROL_TYPES = [
1190
1181
  "operation.done",
1191
1182
  "operation.cancel"
1192
1183
  ];
1184
+ var FLEET_FILES_LIMITS = {
1185
+ /** Largest `DATA` frame of a files stream. */
1186
+ chunkBytes: 64 * 1024,
1187
+ /** Unacknowledged bytes a sender may have in flight (the link's credit window). */
1188
+ windowBytes: 8 * 1024 * 1024,
1189
+ /** Bytes one operation may move. */
1190
+ maxOpBytes: 2 * 1024 * 1024 * 1024,
1191
+ /** Entries one operation may carry, and one listing may show. */
1192
+ maxEntries: 5e3,
1193
+ /** Transfers running at once on one computer. */
1194
+ maxConcurrentPerNode: 2,
1195
+ /** Transfers one person runs at once. */
1196
+ maxConcurrentPerUser: 4
1197
+ };
1198
+ var FLEET_FILES_MAX_BYTES_RECORD = FLEET_FILES_LIMITS.chunkBytes - 5;
1199
+ var FLEET_FILES_TRANSFER_RETENTION_MS = 10 * 6e4;
1200
+ var FLEET_FILES_LIST_AUDIT_WINDOW_MS = 15 * 6e4;
1201
+ var FLEET_CREDENTIAL_FILE_PATTERNS = [
1202
+ ".env",
1203
+ ".env.*",
1204
+ "*.pem",
1205
+ "*.key",
1206
+ "*.p12",
1207
+ "*.pfx",
1208
+ "*.jks",
1209
+ "*.keystore",
1210
+ "*.kdbx",
1211
+ "id_rsa*",
1212
+ "id_dsa*",
1213
+ "id_ecdsa*",
1214
+ "id_ed25519*",
1215
+ "*.ppk",
1216
+ ".netrc",
1217
+ ".npmrc",
1218
+ ".pypirc",
1219
+ "credentials",
1220
+ "credentials.json",
1221
+ "service-account*.json",
1222
+ ".aws/credentials",
1223
+ "*.gpg",
1224
+ "*.asc",
1225
+ ".docker/config.json",
1226
+ "kubeconfig",
1227
+ ".kube/config"
1228
+ ];
1229
+ function globToRegExp(glob) {
1230
+ const escaped = glob.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
1231
+ return new RegExp(`^${escaped}$`, "i");
1232
+ }
1233
+ var CREDENTIAL_NAME_MATCHERS = FLEET_CREDENTIAL_FILE_PATTERNS.filter((pattern) => !pattern.includes("/")).map(
1234
+ globToRegExp
1235
+ );
1236
+ var CREDENTIAL_PATH_MATCHERS = FLEET_CREDENTIAL_FILE_PATTERNS.filter((pattern) => pattern.includes("/")).map(
1237
+ (pattern) => ({ segments: pattern.split("/").length, matcher: globToRegExp(pattern) })
1238
+ );
1239
+ var MAX_HEADER_JSON_BYTES = 16 * 1024;
1240
+ var FLEET_RUN_ENV_FILE_MAX_CONTENT_BYTES = 32 * 1024;
1241
+ var FLEET_RUN_ENV_FILES_MAX_TOTAL_BYTES = 256 * 1024;
1242
+ var FLEET_JOB_MAX_PAYLOAD_BYTES = 256 * 1024;
1243
+ var FLEET_JOB_MAX_RESULT_BYTES = 256 * 1024;
1244
+ var FLEET_JOB_DEFAULT_QUEUED_MAX_AGE_SEC = Object.freeze({
1245
+ "agent-task": 24 * 60 * 60,
1246
+ "acceptance-checks": 2 * 60 * 60,
1247
+ "browser-check": 2 * 60 * 60,
1248
+ // A live view nobody claimed is abandoned by the session service after
1249
+ // 40 seconds, which cancels its job there and then. The queue SLA is only
1250
+ // the backstop behind that, so it deliberately does not undercut the
1251
+ // shortest existing default (the fallback an unknown kind fails closed to).
1252
+ "computer-session": 2 * 60 * 60,
1253
+ // An Agent session (FL-04 P2). Like the live view it does not undercut the
1254
+ // shortest existing default (the fallback an unknown kind fails closed to):
1255
+ // the session sweeper ends one still waiting after ten minutes, and this
1256
+ // queue SLA is only the backstop behind it.
1257
+ "agent-session": 2 * 60 * 60,
1258
+ // Virtual computers (FL-16). The plan proposed an hour for a create and ten
1259
+ // minutes for a control; like the live view and the Agent session they do
1260
+ // NOT undercut the shortest existing default (the fallback an unknown kind
1261
+ // fails closed to), so an older reader's "unknown kind" answer is unchanged.
1262
+ // A control the owner no longer wants is cancelled with its child's row.
1263
+ "vm-create": 2 * 60 * 60,
1264
+ "vm-control": 2 * 60 * 60
1265
+ });
1266
+ var FLEET_JOB_MAX_QUEUED_MAX_AGE_SEC = 7 * 24 * 60 * 60;
1267
+ var FLEET_AGENT_EXECUTION_MAX_INSTRUCTIONS_BYTES = 160 * 1024;
1268
+ var FLEET_AGENT_TASK_TIMELINE_MAX_BYTES = 48 * 1024;
1269
+ var FLEET_AGENT_TASK_TRANSCRIPT_MAX_BYTES = 64 * 1024;
1270
+ var FLEET_AGENT_TASK_QUESTION_MAX_FILE_BYTES = 64 * 1024;
1271
+ var FLEET_AGENT_TASK_QUESTION_MAX_CONTEXT_BYTES = 6 * 1024;
1193
1272
  var CONTROL_TYPES = new Set(FLEET_LINK_CONTROL_TYPES);
1194
1273
  var KIND_JSON = FLEET_LINK_FRAME_KINDS.JSON;
1195
1274
  var utf8Encoder = new TextEncoder();
1275
+ var FLEET_LINK_VIEWER_SLOW_BUFFER_BYTES = 8 * 1024 * 1024;
1276
+ var FLEET_LINK_VIEWER_MAX_BUFFER_BYTES = 32 * 1024 * 1024;
1277
+ var FLEET_LINK_VIEWER_FRAME_KINDS = [FLEET_LINK_FRAME_KINDS.ACK];
1278
+ var FLEET_MACHINE_OPERATION_MAX_MS = 60 * 6e4;
1279
+ var FLEET_LOGS_FOLLOW_BYTES_PER_SEC = 1024 * 1024;
1280
+ var FLEET_LOGS_PENDING_MAX_BYTES = 1024 * 1024;
1281
+ var FLEET_LOGS_MAX_FRAME_BYTES = 64 * 1024;
1282
+ var FLEET_LOGS_MAX_LINE_CHARS = 16 * 1024;
1283
+ var FLEET_LOGS_FILE_SCAN_MAX_BYTES = 8 * 1024 * 1024;
1196
1284
  var FLEET_MODEL_USAGE_LIMIT_FALLBACK_MS = 60 * 60 * 1e3;
1197
1285
  var FLEET_MODEL_USAGE_LIMIT_MIN_MS = 60 * 1e3;
1198
1286
  var FLEET_MODEL_USAGE_LIMIT_MAX_MS = 8 * 24 * 60 * 60 * 1e3;
@@ -1211,6 +1299,51 @@ var FLEET_HEALTH_DISK_CRITICAL_MARGIN_BYTES = 1024 ** 3;
1211
1299
  var FLEET_HEALTH_MAX_MIB = 2 ** 40;
1212
1300
  var FLEET_HEALTH_MAX_UPTIME_SEC = 100 * 365 * 24 * 60 * 60;
1213
1301
  var FLEET_HEALTH_BYTES_PER_MIB = 1024 * 1024;
1302
+ var MINUTE_MS = 6e4;
1303
+ var HOUR_MS = 60 * MINUTE_MS;
1304
+ var DAY_MS2 = 24 * HOUR_MS;
1305
+ var FLEET_HEALTH_RANGE_MS = {
1306
+ "1h": HOUR_MS,
1307
+ "24h": DAY_MS2,
1308
+ "7d": 7 * DAY_MS2,
1309
+ "90d": 90 * DAY_MS2
1310
+ };
1311
+ var FLEET_WAKE_RATE_WINDOW_MS = 5 * 6e4;
1312
+ var FLEET_PORT_PROBE_BODY_CAP = 64 * 1024;
1313
+ var FLEET_PORT_PREVIEW_MAX_MS = 60 * 6e4;
1314
+ var FLEET_PORT_TUNNEL_IDLE_MS = 10 * 6e4;
1315
+ var FLEET_PORT_TUNNEL_HARD_MS = 60 * 6e4;
1316
+ var FLEET_PORT_TUNNEL_CHUNK_BYTES = 64 * 1024;
1317
+ var FLEET_PORT_TUNNEL_MAX_HEADER_BYTES = 64 * 1024;
1318
+ var FLEET_WELL_KNOWN_PORTS = Object.freeze({
1319
+ 21: "ftp",
1320
+ 22: "ssh",
1321
+ 25: "smtp",
1322
+ 53: "dns",
1323
+ 110: "pop3",
1324
+ 143: "imap",
1325
+ 389: "ldap",
1326
+ 1433: "mssql",
1327
+ 1521: "oracle",
1328
+ 2375: "docker",
1329
+ 2376: "docker",
1330
+ 2379: "etcd",
1331
+ 3306: "mysql",
1332
+ 3389: "rdp",
1333
+ 4222: "nats",
1334
+ 5432: "postgres",
1335
+ 5672: "amqp",
1336
+ 5900: "vnc",
1337
+ 6379: "redis",
1338
+ 6443: "kubernetes",
1339
+ 7687: "neo4j",
1340
+ 9042: "cassandra",
1341
+ 9092: "kafka",
1342
+ 9200: "elasticsearch",
1343
+ 11211: "memcached",
1344
+ 15672: "rabbitmq",
1345
+ 27017: "mongo"
1346
+ });
1214
1347
  var FLEET_RUN_TOKEN_ROUTES = Object.freeze([
1215
1348
  // Works — reads, plus the settings update (its merge / check / command
1216
1349
  // fields are refused for run tokens by the Works controller).
@@ -1294,6 +1427,12 @@ var FLEET_RUN_TOKEN_ROUTES = Object.freeze([
1294
1427
  { method: "GET", pathPattern: "/api/fleet/runner-status" },
1295
1428
  { method: "GET", pathPattern: "/api/fleet/execution-preferences" },
1296
1429
  { method: "GET", pathPattern: "/api/fleet/agents/{agentId}/node-affinity" },
1430
+ // Session git & actions (FL-06 FR-18): an Agent session asks the platform to
1431
+ // open or update the pull request of ITS OWN checkout. The route refuses a
1432
+ // checkout that is not the token's session's, and the Agent's "may open pull
1433
+ // requests" permission applies; it never merges anything.
1434
+ { method: "GET", pathPattern: "/api/fleet/checkouts/{id}/pull-request" },
1435
+ { method: "POST", pathPattern: "/api/fleet/checkouts/{id}/pull-request" },
1297
1436
  // Agents — reads, plus cancel and pause (the safe direction).
1298
1437
  { method: "GET", pathPattern: "/api/agents" },
1299
1438
  { method: "GET", pathPattern: "/api/agents/{id}" },
@@ -1316,6 +1455,783 @@ var FLEET_RUN_TOKEN_ROUTE_SHAPES = FLEET_RUN_TOKEN_ROUTES.map((route) => ({
1316
1455
  method: route.method.toUpperCase(),
1317
1456
  shape: splitSegments(route.pathPattern).map((part) => /^\{[^}]+\}$/.test(part) ? "*" : part.toLowerCase())
1318
1457
  }));
1458
+ var FLEET_SESSION_STATES = ["starting", "working", "needs_you", "done", "idle", "ended"];
1459
+ var FLEET_SESSION_LIVE_STATES = FLEET_SESSION_STATES.filter(
1460
+ (state) => state !== "ended"
1461
+ );
1462
+ var FLEET_SESSION_SLOW_VIEWER_BYTES = 1024 * 1024;
1463
+ var FLEET_SESSION_DAEMON_IDLE_EXIT_MS = 5 * 6e4;
1464
+ var FLEET_SESSION_LAST_SCREEN_MAX_CHARS = 256 * 1024;
1465
+ var FLEET_AGENT_SESSION_QUEUED_TIMEOUT_MS = 10 * 6e4;
1466
+ var FLEET_PR_ENRICHMENT_RECENT_MS = 7 * 24 * 60 * 6e4;
1467
+ var FLEET_GIT_LINE_STALE_MS = 5 * 6e4;
1468
+ var FLEET_SESSION_IDLE_AFTER_MS = 30 * 6e4;
1469
+ var FLEET_SESSION_DECISION_STALE_MS = 24 * 60 * 6e4;
1470
+ var FLEET_SESSION_HOOK_BODY_MAX_BYTES = 64 * 1024;
1471
+ var FLEET_SESSION_HOOK_SPOOL_MAX_BYTES = 5 * 1024 * 1024;
1472
+ var FLEET_SESSION_HOOK_SPOOL_MAX_AGE_MS = 7 * 24 * 60 * 6e4;
1473
+ var FLEET_COMMAND_MAX_OUTPUT_BYTES = 10 * 1024 * 1024;
1474
+ var FLEET_COMMAND_STORED_EDGE_BYTES = 64 * 1024;
1475
+ var FLEET_COMMAND_DATA_CHUNK_BYTES = 64 * 1024;
1476
+ var FLEET_COMMAND_MAX_LENGTH = 8 * 1024;
1477
+ var FLEET_SCHEDULE_PROMPT_MAX_BYTES = 16 * 1024;
1478
+ var FLEET_SCHEDULE_BREAKER_UNDO_MS = 15 * 6e4;
1479
+ var MAX_SEARCH_DAYS = 366 * 8 + 1;
1480
+ function row(input) {
1481
+ const rest = input.name.slice("fleet_".length);
1482
+ const cut = rest.indexOf("_");
1483
+ const family = cut === -1 ? rest : rest.slice(0, cut);
1484
+ const verb = cut === -1 ? "" : rest.slice(cut + 1);
1485
+ return Object.freeze({ ...input, family, verb });
1486
+ }
1487
+ function read(name, permissionFamily, owner, flag, status, extra = {}) {
1488
+ return row({
1489
+ name,
1490
+ readOnly: true,
1491
+ category: "read.internal",
1492
+ permissionFamily,
1493
+ owner,
1494
+ phase: "P1",
1495
+ flag,
1496
+ status,
1497
+ ...extra
1498
+ });
1499
+ }
1500
+ function act(name, permissionFamily, owner, flag, status, annotation, extra = {}) {
1501
+ return row({ name, permissionFamily, owner, phase: "P2", flag, status, ...annotation, ...extra });
1502
+ }
1503
+ var plain = (category, destructive = false) => ({
1504
+ destructive,
1505
+ confirmationClass: "plain",
1506
+ category
1507
+ });
1508
+ var confirm = (category, destructive = true) => ({
1509
+ destructive,
1510
+ confirmationClass: "confirm",
1511
+ category
1512
+ });
1513
+ var typed = (category) => ({
1514
+ destructive: true,
1515
+ confirmationClass: "confirm-destructive",
1516
+ category
1517
+ });
1518
+ var GET = (path) => ({ method: "GET", path });
1519
+ var POST = (path) => ({ method: "POST", path });
1520
+ var PATCH = (path) => ({ method: "PATCH", path });
1521
+ var DELETE = (path) => ({ method: "DELETE", path });
1522
+ var FLEET_TOOL_CATALOGUE = Object.freeze([
1523
+ // ── status (FL-19) ──
1524
+ read("fleet_status", "view", "FL-19", "FLEET_ENABLED", "live", {
1525
+ route: GET("/api/fleet/status"),
1526
+ cli: "fleet status"
1527
+ }),
1528
+ // ── nodes (FL-19, FL-03, FL-15) ──
1529
+ read("fleet_nodes_list", "view", "FL-19", "FLEET_ENABLED", "live", {
1530
+ route: GET("/api/fleet/nodes"),
1531
+ cli: "fleet nodes list"
1532
+ }),
1533
+ read("fleet_nodes_get", "view", "FL-19", "FLEET_ENABLED", "live", {
1534
+ route: GET("/api/fleet/nodes/{id}"),
1535
+ cli: "fleet nodes get"
1536
+ }),
1537
+ read("fleet_nodes_health", "view", "FL-03", "FLEET_ENABLED", "live", {
1538
+ route: GET("/api/fleet/nodes/{id}/health"),
1539
+ cli: "fleet nodes health"
1540
+ }),
1541
+ read("fleet_nodes_needs_a_look", "view", "FL-03", "FLEET_ENABLED", "live", {
1542
+ route: GET("/api/fleet/nodes/{id}/needs-a-look"),
1543
+ cli: "fleet nodes needs-a-look"
1544
+ }),
1545
+ read("fleet_nodes_git_identity_get", "view", "FL-15", "FLEET_CHECKOUTS_ENABLED", "live", {
1546
+ route: GET("/api/fleet/nodes/{id}/git/identity"),
1547
+ cli: "fleet nodes git-identity"
1548
+ }),
1549
+ act("fleet_nodes_wake", "machines", "FL-03", "FLEET_ENABLED", "live", plain("machine.admin"), {
1550
+ route: POST("/api/fleet/nodes/{id}/wake"),
1551
+ cli: "fleet nodes wake"
1552
+ }),
1553
+ act(
1554
+ "fleet_nodes_git_identity_set",
1555
+ "commands",
1556
+ "FL-15",
1557
+ "FLEET_CHECKOUTS_ENABLED",
1558
+ "live",
1559
+ confirm("machine.admin", false),
1560
+ { route: POST("/api/fleet/nodes/{id}/git/identity"), cli: "fleet nodes git-identity --set" }
1561
+ ),
1562
+ // ── sessions (FL-04, FL-05, FL-06) ──
1563
+ read("fleet_sessions_list", "sessions", "FL-04", "FLEET_SESSIONS_ENABLED", "live", {
1564
+ route: GET("/api/fleet/sessions"),
1565
+ cli: "fleet sessions list"
1566
+ }),
1567
+ read("fleet_sessions_read", "sessions", "FL-04", "FLEET_SESSIONS_ENABLED", "live", {
1568
+ route: GET("/api/fleet/sessions/{id}"),
1569
+ cli: "fleet sessions read"
1570
+ }),
1571
+ read("fleet_sessions_question", "sessions", "FL-05", "FLEET_SESSIONS_ENABLED", "live", {
1572
+ route: GET("/api/fleet/sessions/{id}"),
1573
+ cli: "fleet sessions question"
1574
+ }),
1575
+ read("fleet_sessions_actions_list", "sessions", "FL-06", "FLEET_SESSIONS_ENABLED", "planned", {
1576
+ route: GET("/api/fleet/sessions/{id}/actions"),
1577
+ cli: "fleet sessions actions"
1578
+ }),
1579
+ act("fleet_sessions_start", "sessions", "FL-04", "FLEET_SESSIONS_ENABLED", "live", plain("machine.run"), {
1580
+ route: POST("/api/fleet/nodes/{id}/sessions"),
1581
+ cli: "fleet sessions start"
1582
+ }),
1583
+ act("fleet_sessions_send", "sessions", "FL-04", "FLEET_SESSIONS_ENABLED", "live", plain("machine.run")),
1584
+ act("fleet_sessions_answer", "sessions", "FL-05", "FLEET_SESSIONS_ENABLED", "live", confirm("machine.run", false), {
1585
+ route: POST("/api/fleet/sessions/{id}/answer"),
1586
+ cli: "fleet sessions answer",
1587
+ confirmationNote: "questions only; a permission prompt is answered by a person (CONTRACTS R-32)"
1588
+ }),
1589
+ act("fleet_sessions_rename", "sessions", "FL-04", "FLEET_SESSIONS_ENABLED", "live", plain("write.internal"), {
1590
+ route: PATCH("/api/fleet/sessions/{id}"),
1591
+ cli: "fleet sessions rename"
1592
+ }),
1593
+ act("fleet_sessions_end", "sessions", "FL-04", "FLEET_SESSIONS_ENABLED", "live", confirm("machine.run"), {
1594
+ route: POST("/api/fleet/sessions/{id}/end"),
1595
+ cli: "fleet sessions end"
1596
+ }),
1597
+ act("fleet_sessions_action", "sessions", "FL-06", "FLEET_SESSIONS_ENABLED", "planned", plain("machine.run"), {
1598
+ route: POST("/api/fleet/sessions/{id}/actions"),
1599
+ cli: "fleet sessions action"
1600
+ }),
1601
+ // ── desktop (FL-07, FL-11 paste) ──
1602
+ read("fleet_desktop_screenshot", "desktop", "FL-07", "FLEET_DESKTOP_ENABLED", "planned", {
1603
+ route: GET("/api/fleet/nodes/{id}/desktop/screenshot"),
1604
+ cli: "fleet desktop screenshot"
1605
+ }),
1606
+ read("fleet_desktop_displays", "desktop", "FL-07", "FLEET_DESKTOP_ENABLED", "planned", {
1607
+ route: GET("/api/fleet/nodes/{id}/desktop/displays"),
1608
+ cli: "fleet desktop displays"
1609
+ }),
1610
+ read("fleet_desktop_recordings_list", "desktop", "FL-07", "FLEET_DESKTOP_ENABLED", "planned", {
1611
+ route: GET("/api/fleet/nodes/{id}/desktop/recordings"),
1612
+ cli: "fleet desktop recordings"
1613
+ }),
1614
+ act("fleet_desktop_input", "desktop", "FL-07", "FLEET_DESKTOP_ENABLED", "planned", plain("machine.admin", true), {
1615
+ route: POST("/api/fleet/nodes/{id}/desktop/input"),
1616
+ cli: "fleet desktop input"
1617
+ }),
1618
+ act("fleet_desktop_set_display", "desktop", "FL-07", "FLEET_DESKTOP_ENABLED", "planned", plain("machine.admin"), {
1619
+ route: POST("/api/fleet/nodes/{id}/desktop/displays"),
1620
+ cli: "fleet desktop set-display"
1621
+ }),
1622
+ act("fleet_desktop_display_add", "desktop", "FL-07", "FLEET_DESKTOP_ENABLED", "planned", confirm("machine.admin"), {
1623
+ phase: "P3",
1624
+ route: POST("/api/fleet/nodes/{id}/desktop/displays/virtual"),
1625
+ cli: "fleet desktop display-add"
1626
+ }),
1627
+ act(
1628
+ "fleet_desktop_display_remove",
1629
+ "desktop",
1630
+ "FL-07",
1631
+ "FLEET_DESKTOP_ENABLED",
1632
+ "planned",
1633
+ confirm("machine.admin"),
1634
+ {
1635
+ phase: "P3",
1636
+ route: DELETE("/api/fleet/nodes/{id}/desktop/displays/virtual/{displayId}"),
1637
+ cli: "fleet desktop display-remove"
1638
+ }
1639
+ ),
1640
+ act(
1641
+ "fleet_desktop_paste",
1642
+ "desktop",
1643
+ "FL-11",
1644
+ "FLEET_MACHINE_FACTS_ENABLED",
1645
+ "planned",
1646
+ plain("machine.admin", true),
1647
+ {
1648
+ route: POST("/api/fleet/nodes/{id}/desktop/paste"),
1649
+ cli: "fleet desktop paste",
1650
+ confirmationNote: "denied unless a tool grant allows it (AW-15)"
1651
+ }
1652
+ ),
1653
+ // ── logs (FL-08) ──
1654
+ read("fleet_logs_sources", "logs", "FL-08", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1655
+ route: GET("/api/fleet/nodes/{id}/logs/sources"),
1656
+ cli: "fleet logs sources"
1657
+ }),
1658
+ read("fleet_logs_read", "logs", "FL-08", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1659
+ route: POST("/api/fleet/nodes/{id}/logs/read"),
1660
+ cli: "fleet logs read"
1661
+ }),
1662
+ // ── services (FL-09) ──
1663
+ read("fleet_services_list", "services", "FL-09", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1664
+ route: GET("/api/fleet/nodes/{id}/services"),
1665
+ cli: "fleet services list"
1666
+ }),
1667
+ act("fleet_services_action", "services", "FL-09", "FLEET_MACHINE_FACTS_ENABLED", "live", confirm("machine.admin"), {
1668
+ route: POST("/api/fleet/nodes/{id}/services/{name}/{action}"),
1669
+ cli: "fleet services action",
1670
+ waitable: true,
1671
+ confirmationNote: "confirm; blast-radius when the node warns it could cut the machine off"
1672
+ }),
1673
+ // ── processes (FL-09) ──
1674
+ read("fleet_processes_list", "processes", "FL-09", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1675
+ route: GET("/api/fleet/nodes/{id}/processes"),
1676
+ cli: "fleet processes list"
1677
+ }),
1678
+ act(
1679
+ "fleet_processes_signal",
1680
+ "processes",
1681
+ "FL-09",
1682
+ "FLEET_MACHINE_FACTS_ENABLED",
1683
+ "live",
1684
+ confirm("machine.admin"),
1685
+ { route: POST("/api/fleet/nodes/{id}/processes/{pid}/signal"), cli: "fleet processes signal" }
1686
+ ),
1687
+ // ── docker (FL-09) ──
1688
+ read("fleet_docker_containers_list", "docker", "FL-09", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1689
+ route: GET("/api/fleet/nodes/{id}/docker/containers"),
1690
+ cli: "fleet docker containers"
1691
+ }),
1692
+ read("fleet_docker_images_list", "docker", "FL-09", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1693
+ route: GET("/api/fleet/nodes/{id}/docker/images"),
1694
+ cli: "fleet docker images"
1695
+ }),
1696
+ read("fleet_docker_compose_list", "docker", "FL-09", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1697
+ route: GET("/api/fleet/nodes/{id}/docker/compose"),
1698
+ cli: "fleet docker compose"
1699
+ }),
1700
+ read("fleet_docker_compose_describe", "docker", "FL-09", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1701
+ cli: "fleet docker compose-describe"
1702
+ }),
1703
+ act(
1704
+ "fleet_docker_container_action",
1705
+ "docker",
1706
+ "FL-09",
1707
+ "FLEET_MACHINE_FACTS_ENABLED",
1708
+ "live",
1709
+ confirm("machine.admin"),
1710
+ {
1711
+ route: POST("/api/fleet/nodes/{id}/docker/containers/{cid}/{action}"),
1712
+ cli: "fleet docker container",
1713
+ waitable: true,
1714
+ confirmationNote: "confirm; remove is confirm-destructive"
1715
+ }
1716
+ ),
1717
+ act("fleet_docker_run", "docker", "FL-09", "FLEET_MACHINE_FACTS_ENABLED", "live", confirm("machine.admin", false), {
1718
+ route: POST("/api/fleet/nodes/{id}/docker/containers"),
1719
+ cli: "fleet docker run",
1720
+ waitable: true,
1721
+ alwaysHeld: true,
1722
+ confirmationNote: "an Agent proposes a run; a person types any secret values"
1723
+ }),
1724
+ act(
1725
+ "fleet_docker_image_action",
1726
+ "docker",
1727
+ "FL-09",
1728
+ "FLEET_MACHINE_FACTS_ENABLED",
1729
+ "live",
1730
+ confirm("machine.admin"),
1731
+ {
1732
+ route: POST("/api/fleet/nodes/{id}/docker/images/{iid}/{action}"),
1733
+ cli: "fleet docker image",
1734
+ waitable: true,
1735
+ confirmationNote: "pull is plain and not destructive; remove and prune confirm"
1736
+ }
1737
+ ),
1738
+ act(
1739
+ "fleet_docker_compose_action",
1740
+ "docker",
1741
+ "FL-09",
1742
+ "FLEET_MACHINE_FACTS_ENABLED",
1743
+ "live",
1744
+ confirm("machine.admin"),
1745
+ {
1746
+ route: POST("/api/fleet/nodes/{id}/docker/compose/{project}/{action}"),
1747
+ cli: "fleet docker compose-action",
1748
+ waitable: true,
1749
+ confirmationNote: "destructive for down"
1750
+ }
1751
+ ),
1752
+ act("fleet_docker_exec", "docker", "FL-09", "FLEET_MACHINE_FACTS_ENABLED", "planned", plain("machine.run"), {
1753
+ phase: "P3",
1754
+ cli: "fleet docker exec"
1755
+ }),
1756
+ // ── ports (FL-10) ──
1757
+ read("fleet_ports_list", "view", "FL-10", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1758
+ route: GET("/api/fleet/nodes/{id}/ports"),
1759
+ cli: "fleet ports list"
1760
+ }),
1761
+ act("fleet_ports_open", "ports", "FL-10", "FLEET_MACHINE_FACTS_ENABLED", "live", plain("machine.run"), {
1762
+ route: POST("/api/fleet/nodes/{id}/ports/{port}/open"),
1763
+ cli: "fleet ports open"
1764
+ }),
1765
+ act("fleet_ports_preview_open", "ports", "FL-10", "FLEET_PORT_TUNNEL_ENABLED", "live", plain("machine.run"), {
1766
+ route: POST("/api/fleet/nodes/{id}/ports/{port}/preview"),
1767
+ cli: "fleet ports preview"
1768
+ }),
1769
+ act("fleet_ports_preview_close", "ports", "FL-10", "FLEET_PORT_TUNNEL_ENABLED", "live", plain("machine.run"), {
1770
+ route: DELETE("/api/fleet/nodes/{id}/ports/{port}/preview"),
1771
+ cli: "fleet ports preview-close"
1772
+ }),
1773
+ // ── files (FL-11) ──
1774
+ // P1 (FL-11 lane log decision 15): the roots read joins the family, and the list's route is the
1775
+ // one FL-11 built (`…/files/list` — `…/files` is the family's prefix, not a route).
1776
+ read("fleet_files_roots", "files", "FL-11", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1777
+ route: GET("/api/fleet/nodes/{id}/files/roots"),
1778
+ cli: "fleet files roots"
1779
+ }),
1780
+ read("fleet_files_list", "files", "FL-11", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1781
+ route: GET("/api/fleet/nodes/{id}/files/list"),
1782
+ cli: "fleet files list"
1783
+ }),
1784
+ read("fleet_files_stat", "files", "FL-11", "FLEET_MACHINE_FACTS_ENABLED", "live", {
1785
+ route: GET("/api/fleet/nodes/{id}/files/stat"),
1786
+ cli: "fleet files stat"
1787
+ }),
1788
+ read("fleet_files_read", "files", "FL-11", "FLEET_MACHINE_FACTS_ENABLED", "planned", {
1789
+ route: GET("/api/fleet/nodes/{id}/files/download"),
1790
+ cli: "fleet files get"
1791
+ }),
1792
+ act("fleet_files_write", "files", "FL-11", "FLEET_MACHINE_FACTS_ENABLED", "planned", confirm("machine.admin"), {
1793
+ route: POST("/api/fleet/nodes/{id}/files/upload"),
1794
+ cli: "fleet files put"
1795
+ }),
1796
+ act("fleet_files_copy", "files", "FL-11", "FLEET_MACHINE_FACTS_ENABLED", "live", confirm("machine.admin"), {
1797
+ route: POST("/api/fleet/nodes/{id}/files/copy"),
1798
+ cli: "fleet files cp",
1799
+ // FL-11 P2 (lane log decision 18): an Agent's copy is held for a person, like its delete.
1800
+ alwaysHeld: true
1801
+ }),
1802
+ act("fleet_files_delete", "files", "FL-11", "FLEET_MACHINE_FACTS_ENABLED", "live", typed("write.destructive"), {
1803
+ route: POST("/api/fleet/nodes/{id}/files/delete"),
1804
+ cli: "fleet files rm",
1805
+ alwaysHeld: true
1806
+ }),
1807
+ // ── commands (FL-12) ──
1808
+ read("fleet_commands_list", "commands", "FL-12", "FLEET_COMMANDS_ENABLED", "live", {
1809
+ route: GET("/api/fleet/commands"),
1810
+ cli: "fleet commands list"
1811
+ }),
1812
+ read("fleet_commands_get", "commands", "FL-12", "FLEET_COMMANDS_ENABLED", "live", {
1813
+ route: GET("/api/fleet/commands/{id}"),
1814
+ cli: "fleet commands get"
1815
+ }),
1816
+ act("fleet_commands_run", "commands", "FL-12", "FLEET_COMMANDS_ENABLED", "live", confirm("machine.run"), {
1817
+ route: POST("/api/fleet/commands"),
1818
+ cli: "fleet commands run",
1819
+ alwaysHeld: true
1820
+ }),
1821
+ act("fleet_commands_cancel", "commands", "FL-12", "FLEET_COMMANDS_ENABLED", "live", plain("machine.run"), {
1822
+ route: POST("/api/fleet/commands/{id}/cancel"),
1823
+ cli: "fleet commands cancel"
1824
+ }),
1825
+ // ── schedules (FL-13 P2: live — `apps/api/src/fleet/schedules/fleet-schedules.controller.ts`) ──
1826
+ read("fleet_schedules_list", "schedules", "FL-13", "FLEET_COMMANDS_ENABLED", "live", {
1827
+ route: GET("/api/fleet/schedules"),
1828
+ cli: "fleet schedules list"
1829
+ }),
1830
+ read("fleet_schedules_get", "schedules", "FL-13", "FLEET_COMMANDS_ENABLED", "live", {
1831
+ route: GET("/api/fleet/schedules/{id}"),
1832
+ cli: "fleet schedules get"
1833
+ }),
1834
+ read("fleet_schedules_runs", "schedules", "FL-13", "FLEET_COMMANDS_ENABLED", "live", {
1835
+ route: GET("/api/fleet/schedules/{id}/runs"),
1836
+ cli: "fleet schedules runs"
1837
+ }),
1838
+ act("fleet_schedules_create", "schedules", "FL-13", "FLEET_COMMANDS_ENABLED", "live", confirm("agent.fanout"), {
1839
+ route: POST("/api/fleet/schedules"),
1840
+ cli: "fleet schedules create"
1841
+ }),
1842
+ act("fleet_schedules_update", "schedules", "FL-13", "FLEET_COMMANDS_ENABLED", "live", confirm("agent.fanout"), {
1843
+ route: PATCH("/api/fleet/schedules/{id}"),
1844
+ cli: "fleet schedules update"
1845
+ }),
1846
+ act(
1847
+ "fleet_schedules_delete",
1848
+ "schedules",
1849
+ "FL-13",
1850
+ "FLEET_COMMANDS_ENABLED",
1851
+ "live",
1852
+ confirm("write.destructive"),
1853
+ { route: DELETE("/api/fleet/schedules/{id}"), cli: "fleet schedules delete" }
1854
+ ),
1855
+ act("fleet_schedules_run", "schedules", "FL-13", "FLEET_COMMANDS_ENABLED", "live", confirm("machine.run"), {
1856
+ route: POST("/api/fleet/schedules/{id}/run"),
1857
+ cli: "fleet schedules run"
1858
+ }),
1859
+ act("fleet_schedules_pause", "schedules", "FL-13", "FLEET_COMMANDS_ENABLED", "live", plain("agent.fanout"), {
1860
+ route: POST("/api/fleet/schedules/{id}/pause"),
1861
+ cli: "fleet schedules pause"
1862
+ }),
1863
+ act("fleet_schedules_resume", "schedules", "FL-13", "FLEET_COMMANDS_ENABLED", "live", plain("agent.fanout"), {
1864
+ route: POST("/api/fleet/schedules/{id}/resume"),
1865
+ cli: "fleet schedules resume"
1866
+ }),
1867
+ // ── checkouts (FL-14, FL-06) ──
1868
+ read("fleet_checkouts_list", "checkouts", "FL-14", "FLEET_CHECKOUTS_ENABLED", "live", {
1869
+ route: GET("/api/fleet/checkouts"),
1870
+ cli: "fleet checkouts list"
1871
+ }),
1872
+ read("fleet_checkouts_get", "checkouts", "FL-14", "FLEET_CHECKOUTS_ENABLED", "live", {
1873
+ route: GET("/api/fleet/checkouts/{id}"),
1874
+ cli: "fleet checkouts get"
1875
+ }),
1876
+ read("fleet_checkouts_changes", "checkouts", "FL-06", "FLEET_CHECKOUTS_ENABLED", "planned", {
1877
+ route: GET("/api/fleet/checkouts/{id}/changes"),
1878
+ cli: "fleet checkouts changes"
1879
+ }),
1880
+ act("fleet_checkouts_create", "checkouts", "FL-14", "FLEET_CHECKOUTS_ENABLED", "live", plain("machine.run"), {
1881
+ route: POST("/api/fleet/checkouts"),
1882
+ cli: "fleet checkouts create",
1883
+ waitable: true
1884
+ }),
1885
+ act("fleet_checkouts_sync", "checkouts", "FL-14", "FLEET_CHECKOUTS_ENABLED", "live", plain("machine.run"), {
1886
+ route: POST("/api/fleet/checkouts/{id}/sync"),
1887
+ cli: "fleet checkouts sync",
1888
+ waitable: true,
1889
+ confirmationNote: "plain for fetch; confirm for pull and push"
1890
+ }),
1891
+ act(
1892
+ "fleet_checkouts_archive",
1893
+ "checkouts",
1894
+ "FL-14",
1895
+ "FLEET_CHECKOUTS_ENABLED",
1896
+ "live",
1897
+ confirm("machine.run", false),
1898
+ { route: POST("/api/fleet/checkouts/{id}/archive"), cli: "fleet checkouts archive" }
1899
+ ),
1900
+ act(
1901
+ "fleet_checkouts_delete",
1902
+ "checkouts",
1903
+ "FL-14",
1904
+ "FLEET_CHECKOUTS_ENABLED",
1905
+ "live",
1906
+ confirm("write.destructive"),
1907
+ {
1908
+ route: DELETE("/api/fleet/checkouts/{id}"),
1909
+ cli: "fleet checkouts delete",
1910
+ confirmationNote: "confirm; confirm-destructive when it has uncommitted changes"
1911
+ }
1912
+ ),
1913
+ act(
1914
+ "fleet_checkouts_open_pull_request",
1915
+ "checkouts",
1916
+ "FL-06",
1917
+ "FLEET_CHECKOUTS_ENABLED",
1918
+ "planned",
1919
+ plain("publish.external"),
1920
+ { route: POST("/api/fleet/checkouts/{id}/pull-request"), cli: "fleet checkouts pull-request" }
1921
+ ),
1922
+ // ── tasks (FL-15) ── the hand-off itself is `fleet_sessions_start` with `taskId`
1923
+ read("fleet_tasks_handoff_options", "sessions", "FL-15", "FLEET_CHECKOUTS_ENABLED", "live", {
1924
+ route: GET("/api/fleet/tasks/{taskId}/handoff-options"),
1925
+ cli: "fleet tasks handoff-options"
1926
+ }),
1927
+ // ── virtual (FL-16) ── P1 shipped: Containers. A create, a stop and a destroy are held for
1928
+ // the owner's approval by the Agent tools (`agent-fleet-virtual-tools.ts`).
1929
+ read("fleet_virtual_list", "view", "FL-16", "FLEET_VIRTUAL_ENABLED", "live", {
1930
+ phase: "P3",
1931
+ route: GET("/api/fleet/nodes/{id}/virtual"),
1932
+ cli: "fleet virtual list"
1933
+ }),
1934
+ read("fleet_virtual_options", "view", "FL-16", "FLEET_VIRTUAL_ENABLED", "live", {
1935
+ phase: "P3",
1936
+ route: GET("/api/fleet/nodes/{id}/virtual/options"),
1937
+ cli: "fleet virtual options"
1938
+ }),
1939
+ act("fleet_virtual_create", "machines", "FL-16", "FLEET_VIRTUAL_ENABLED", "live", confirm("machine.admin"), {
1940
+ phase: "P3",
1941
+ route: POST("/api/fleet/nodes/{id}/virtual"),
1942
+ cli: "fleet virtual create",
1943
+ waitable: true,
1944
+ alwaysHeld: true
1945
+ }),
1946
+ act("fleet_virtual_power", "machines", "FL-16", "FLEET_VIRTUAL_ENABLED", "live", confirm("machine.admin"), {
1947
+ phase: "P3",
1948
+ route: POST("/api/fleet/nodes/{id}/virtual/{childId}/power"),
1949
+ cli: "fleet virtual power",
1950
+ waitable: true,
1951
+ confirmationNote: "plain to start; confirm to stop (an Agent's stop is held for the owner)"
1952
+ }),
1953
+ act("fleet_virtual_destroy", "machines", "FL-16", "FLEET_VIRTUAL_ENABLED", "live", typed("write.destructive"), {
1954
+ phase: "P3",
1955
+ route: POST("/api/fleet/nodes/{id}/virtual/{childId}/destroy"),
1956
+ cli: "fleet virtual destroy",
1957
+ waitable: true,
1958
+ alwaysHeld: true
1959
+ }),
1960
+ // ── cloud (FL-17) ── P1 shipped: providers, create, power, destroy, usage. A create, a power
1961
+ // change and a destroy are held for the owner's approval by the Agent tools
1962
+ // (`agent-fleet-cloud-tools.ts`); the idle policy arrives with P2.
1963
+ read("fleet_cloud_list", "view", "FL-17", "FLEET_CLOUD_ENABLED", "live", {
1964
+ phase: "P3",
1965
+ route: GET("/api/fleet/cloud"),
1966
+ cli: "fleet cloud list"
1967
+ }),
1968
+ read("fleet_cloud_options", "view", "FL-17", "FLEET_CLOUD_ENABLED", "live", {
1969
+ phase: "P3",
1970
+ route: GET("/api/fleet/providers/{plugin}/options"),
1971
+ cli: "fleet cloud options"
1972
+ }),
1973
+ read("fleet_cloud_usage", "view", "FL-17", "FLEET_CLOUD_ENABLED", "live", {
1974
+ phase: "P3",
1975
+ route: GET("/api/fleet/cloud/usage"),
1976
+ cli: "fleet cloud usage"
1977
+ }),
1978
+ act("fleet_cloud_create", "machines", "FL-17", "FLEET_CLOUD_ENABLED", "live", confirm("spend.metered"), {
1979
+ phase: "P3",
1980
+ route: POST("/api/fleet/cloud"),
1981
+ cli: "fleet cloud create",
1982
+ waitable: true,
1983
+ alwaysHeld: true,
1984
+ confirmationNote: "confirm with the price (acknowledgedPriceCents); also machine.admin"
1985
+ }),
1986
+ act("fleet_cloud_power", "machines", "FL-17", "FLEET_CLOUD_ENABLED", "live", confirm("machine.admin"), {
1987
+ phase: "P3",
1988
+ route: POST("/api/fleet/cloud/{id}/power"),
1989
+ cli: "fleet cloud power",
1990
+ waitable: true,
1991
+ alwaysHeld: true
1992
+ }),
1993
+ act("fleet_cloud_destroy", "machines", "FL-17", "FLEET_CLOUD_ENABLED", "live", typed("write.destructive"), {
1994
+ phase: "P3",
1995
+ // FL-17 plan §5 — `DELETE /api/fleet/cloud/{id}` answers the same (an alias).
1996
+ route: POST("/api/fleet/cloud/{id}/destroy"),
1997
+ cli: "fleet cloud destroy",
1998
+ waitable: true,
1999
+ alwaysHeld: true
2000
+ }),
2001
+ act("fleet_cloud_idle_policy", "machines", "FL-17", "FLEET_CLOUD_ENABLED", "planned", plain("machine.admin"), {
2002
+ phase: "P3",
2003
+ route: PATCH("/api/fleet/cloud/{id}/idle-policy"),
2004
+ cli: "fleet cloud idle-policy"
2005
+ }),
2006
+ // ── runners (FL-18) ──
2007
+ read("fleet_runners_list", "view", "FL-18", "FLEET_ACTIONS_RUNNERS_ENABLED", "planned", {
2008
+ phase: "P3",
2009
+ route: GET("/api/fleet/nodes/{id}/runners"),
2010
+ cli: "fleet runners list"
2011
+ }),
2012
+ read("fleet_runners_jobs", "view", "FL-18", "FLEET_ACTIONS_RUNNERS_ENABLED", "planned", {
2013
+ phase: "P3",
2014
+ route: GET("/api/fleet/runners/jobs"),
2015
+ cli: "fleet runners jobs"
2016
+ }),
2017
+ act(
2018
+ "fleet_runners_install",
2019
+ "machines",
2020
+ "FL-18",
2021
+ "FLEET_ACTIONS_RUNNERS_ENABLED",
2022
+ "planned",
2023
+ confirm("machine.admin"),
2024
+ { phase: "P3", route: POST("/api/fleet/nodes/{id}/runners"), cli: "fleet runners install", waitable: true }
2025
+ ),
2026
+ act(
2027
+ "fleet_runners_action",
2028
+ "machines",
2029
+ "FL-18",
2030
+ "FLEET_ACTIONS_RUNNERS_ENABLED",
2031
+ "planned",
2032
+ confirm("machine.admin"),
2033
+ {
2034
+ phase: "P3",
2035
+ route: POST("/api/fleet/nodes/{id}/runners/{runnerId}/{action}"),
2036
+ cli: "fleet runners action",
2037
+ waitable: true,
2038
+ confirmationNote: "plain to start; confirm to stop and restart"
2039
+ }
2040
+ ),
2041
+ act(
2042
+ "fleet_runners_remove",
2043
+ "machines",
2044
+ "FL-18",
2045
+ "FLEET_ACTIONS_RUNNERS_ENABLED",
2046
+ "planned",
2047
+ typed("write.destructive"),
2048
+ { phase: "P3", route: DELETE("/api/fleet/nodes/{id}/runners/{runnerId}"), cli: "fleet runners remove" }
2049
+ ),
2050
+ act(
2051
+ "fleet_runners_cancel_run",
2052
+ "machines",
2053
+ "FL-18",
2054
+ "FLEET_ACTIONS_RUNNERS_ENABLED",
2055
+ "planned",
2056
+ confirm("machine.admin"),
2057
+ { phase: "P3", route: POST("/api/fleet/runners/jobs/{jobId}/cancel"), cli: "fleet runners cancel-run" }
2058
+ ),
2059
+ // ── usage (FL-20) ──
2060
+ read("fleet_usage_get", "view", "FL-20", "FLEET_USAGE_SCAN_ENABLED", "planned", {
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;
1319
2235
  var EMAIL_INBOX_DEFAULT_DAILY_CAP = 100;
1320
2236
  var EMAIL_INBOX_BURST_SENDS = 10;
1321
2237
  var EMAIL_INBOX_BURST_RECIPIENTS = 20;
@@ -1344,7 +2260,7 @@ var EMAIL_SEND_CAP_FIELDS = [
1344
2260
  "workspaceMonthlySends"
1345
2261
  ];
1346
2262
  var INBOX_CAP_FIELD_SET = new Set(EMAIL_INBOX_CAP_FIELDS);
1347
- var DAY_MS2 = 24 * 60 * 60 * 1e3;
2263
+ var DAY_MS3 = 24 * 60 * 60 * 1e3;
1348
2264
  var PROMOTION_GATE_DECISION_GRACE_MS = 20 * 60 * 1e3;
1349
2265
  var RELEASE_VERIFY_ATTEMPT_INTERVAL_MS = 10 * 60 * 1e3;
1350
2266
  var RELEASE_VERIFY_BUDGET_MS = 8 * 60 * 60 * 1e3;
@@ -1550,8 +2466,8 @@ var BACKUP_DEFAULT_LIMITS = Object.freeze({
1550
2466
  /** Retries a storage write gets before the backup fails as `storage_unavailable`. */
1551
2467
  storageRetries: 3
1552
2468
  });
1553
- var HOUR_MS = 60 * 60 * 1e3;
1554
- var MINUTE_MS = 60 * 1e3;
2469
+ var HOUR_MS3 = 60 * 60 * 1e3;
2470
+ var MINUTE_MS2 = 60 * 1e3;
1555
2471
  var ACTION_CATEGORIES = Object.freeze([
1556
2472
  "read.internal",
1557
2473
  "read.external",
@@ -1858,13 +2774,16 @@ var INTEGRATION_SCOPES = [
1858
2774
  "events:read",
1859
2775
  "webhooks:manage",
1860
2776
  "links:write",
1861
- "merges:decide"
2777
+ "merges:decide",
2778
+ "decisions:individual"
1862
2779
  ];
1863
2780
  var INTEGRATION_MERGE_DECISION_SCOPE = "merges:decide";
2781
+ var INTEGRATION_INDIVIDUAL_DECISION_SCOPE = "decisions:individual";
1864
2782
  var INTEGRATION_OPT_IN_SCOPES = [
1865
2783
  "org:write",
1866
2784
  "email:write",
1867
- INTEGRATION_MERGE_DECISION_SCOPE
2785
+ INTEGRATION_MERGE_DECISION_SCOPE,
2786
+ INTEGRATION_INDIVIDUAL_DECISION_SCOPE
1868
2787
  ];
1869
2788
  var EVER_GAUZY_PRESET_SCOPES = INTEGRATION_SCOPES.filter(
1870
2789
  (scope) => !INTEGRATION_OPT_IN_SCOPES.includes(scope)
@@ -2022,7 +2941,16 @@ var PLUGIN_CAPABILITIES = {
2022
2941
  // `capabilities/domain-event-subscriber.interface.ts`. Appended last, so
2023
2942
  // every existing constant keeps its value and its position; no category is
2024
2943
  // added (a subscriber plugin keeps the category of what it otherwise is).
2025
- DOMAIN_EVENT_SUBSCRIBER: "domain-event-subscriber"
2944
+ DOMAIN_EVENT_SUBSCRIBER: "domain-event-subscriber",
2945
+ // Cloud computers (FL-17, CONTRACTS R-15) — plugins that create, power and
2946
+ // destroy machines at a cloud provider on the owner's own account and say
2947
+ // what they cost (`IMachineProviderPlugin`). The first plugin ships under
2948
+ // `packages/plugins/`. Consumed only through
2949
+ // `MachineProviderFacadeService`; see
2950
+ // `capabilities/machine-provider.interface.ts`. Appended **last**, so every
2951
+ // existing constant keeps its value and its position, and landed in the same
2952
+ // change as the `machine-provider` category in `plugin-manifest.types.ts`.
2953
+ MACHINE_PROVIDER: "machine-provider"
2026
2954
  };
2027
2955
  var ALL_PLUGIN_CAPABILITIES = Object.values(PLUGIN_CAPABILITIES);
2028
2956
  function initializePipelineState(stepDefinitions) {