@runuai/host 0.9.44 → 0.9.46

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.
@@ -17,12 +17,29 @@ export const STABLE_RELEASE_MANIFEST_URL =
17
17
  * Provisioning a key is necessary but not sufficient to advertise or serve
18
18
  * the one-line installer. The release coordinator flips this only in the same
19
19
  * reviewed change that publishes the complete, version-matched four-platform
20
- * release. Keeping it false while this stack is under review makes accidental
21
- * key/feed provisioning fail closed.
20
+ * release. Flipped 2026-08-19 in the change that provisioned
21
+ * `uai-release-2026-a` and wired auto-release to sign and publish the
22
+ * four-platform feed on every host version bump.
22
23
  */
23
- export const HOST_INSTALLER_RELEASE_PROMOTED = false;
24
+ export const HOST_INSTALLER_RELEASE_PROMOTED = true;
24
25
 
26
+ /**
27
+ * `uai-release-2026-a`: minted by the operator 2026-08-19 (Ed25519; private
28
+ * key lives in Infisical and reaches CI as UAI_RELEASE_SIGNING_KEY). Rotation
29
+ * is additive: pin the successor key beside this one, publish releases signed
30
+ * by it, and retire this entry only after every supported host updated past
31
+ * a release that pins both.
32
+ */
25
33
  export const PINNED_RELEASE_MANIFEST_KEYS: ReadonlyMap<
26
34
  string,
27
35
  PinnedReleaseManifestKey
28
- > = new Map();
36
+ > = new Map([
37
+ [
38
+ "uai-release-2026-a",
39
+ {
40
+ publicKey: `-----BEGIN PUBLIC KEY-----
41
+ MCowBQYDK2VwAyEAeCBzaLTNYNGkI59T+vNu2M/DMTeTsmfABDtwN9IDejY=
42
+ -----END PUBLIC KEY-----`,
43
+ },
44
+ ],
45
+ ]);
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@runuai/host",
3
- "version": "0.9.44",
4
- "description": "Uai host — runs ephemeral AI coding tasks in Docker on a machine you control.",
3
+ "version": "0.9.46",
4
+ "description": "Uai host — runs ephemeral AI tasks in containers on a machine you control.",
5
5
  "license": "MIT",
6
- "author": "Diogo Perillo <diogo.perillo@gmail.com>",
6
+ "author": "Uai Tech <team@runuai.com>",
7
7
  "homepage": "https://github.com/runuai/uai#readme",
8
8
  "repository": {
9
9
  "type": "git",
package/src/index.ts CHANGED
@@ -75,7 +75,10 @@ import {
75
75
  } from "../lib/preview-sidecar";
76
76
  import { inspectTunnelContainer } from "../lib/tunnel-runtime";
77
77
  import { ContainerRuntimeUnavailableError } from "../lib/runtime-guard";
78
- import { managedRuntimeAdmissionBlocker } from "../lib/managed-runtime";
78
+ import {
79
+ managedRuntimeAdmissionBlocker,
80
+ reclaimAbandonedMaintenanceCheck,
81
+ } from "../lib/managed-runtime";
79
82
  import { retireTaskSshIdentityEnsures } from "../lib/git-identity";
80
83
  import { removeTaskIdentityStrict } from "../lib/ssh";
81
84
  import { proveOrphanTaskResourcesAbsent } from "../lib/task-inventory";
@@ -1347,13 +1350,44 @@ function boundedFailureMessage(error: unknown): string {
1347
1350
 
1348
1351
  /** Managed installation, activation, and uninstall drain instead of admitting work. */
1349
1352
  let lastAdmissionRefusalLogAt = 0;
1353
+ let lastAdmissionReclaimAt = 0;
1354
+ let admissionReclaimInFlight: Promise<"cleared" | "kept" | "none"> | null =
1355
+ null;
1350
1356
  function managedMaintenanceUnavailable(): HostCommandResult<never> | null {
1351
1357
  const blocker = managedRuntimeAdmissionBlocker();
1352
1358
  if (blocker === null) return null;
1359
+ const now = Date.now();
1360
+ // Mid-run self-heal (the abandoned-uninstall marker recurred WHILE the
1361
+ // service was up, 2026-08-19 — boot-time reclaim alone cannot cover a
1362
+ // writer on a schedule). Reclaim only ever touches a provably-untorn
1363
+ // "checking" marker, under the operation lock; rate-limited so the
1364
+ // cloud's retry hammer cannot churn the lock. The command that observed
1365
+ // the marker still refuses — the NEXT retry finds admission open.
1366
+ if (now - lastAdmissionReclaimAt > 30_000 && !admissionReclaimInFlight) {
1367
+ lastAdmissionReclaimAt = now;
1368
+ admissionReclaimInFlight = reclaimAbandonedMaintenanceCheck();
1369
+ void admissionReclaimInFlight
1370
+ .then((verdict) => {
1371
+ if (verdict === "cleared") {
1372
+ console.warn(
1373
+ "[host-agent] cleared an abandoned maintenance marker mid-run (a managed uninstall/update died before any teardown); task admission reopened",
1374
+ );
1375
+ }
1376
+ })
1377
+ .catch((error) => {
1378
+ console.warn(
1379
+ `[host-agent] mid-run maintenance-marker reclaim failed: ${
1380
+ error instanceof Error ? error.message : String(error)
1381
+ }`,
1382
+ );
1383
+ })
1384
+ .finally(() => {
1385
+ admissionReclaimInFlight = null;
1386
+ });
1387
+ }
1353
1388
  // A refusal must NAME its gate somewhere an operator can find it. Three
1354
1389
  // stacked silent refusals cost hours live (2026-08-18); rate-limited so a
1355
1390
  // retrying cloud cannot flood the log.
1356
- const now = Date.now();
1357
1391
  if (now - lastAdmissionRefusalLogAt > 60_000) {
1358
1392
  lastAdmissionRefusalLogAt = now;
1359
1393
  console.warn(