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