@nylorun/runtime 0.53.1-beta → 0.53.2-beta
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.
- package/CHANGELOG.md +11 -0
- package/dist/host/restate-identity.d.ts +9 -0
- package/dist/host/restate-identity.js +41 -0
- package/dist/host/stack-config.js +18 -2
- package/dist/management-openapi.json +1 -1
- package/dist/openapi.json +1 -1
- package/dist/sandbox/computer.js +4 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.53.2-beta
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- d423ecf: Computers on Kubernetes, the rest of the plan: the Helm chart signs Restate's requests to the
|
|
8
|
+
worker with an identity key it keeps (the runtime reads it from `NYLORUN_RESTATE_IDENTITY_KEY_FILE`,
|
|
9
|
+
a PEM it derives `publickeyv1_…` from), writes Restate's partition snapshots to the object store,
|
|
10
|
+
and can run the keys provider beside Substrate's egress (`keysProvider.enabled`) with the decide
|
|
11
|
+
route on the gateway. A computer resumed elsewhere by a drain records `agent.suspended` (reason
|
|
12
|
+
`drain`) on its next use, not only on its next reconcile.
|
|
13
|
+
|
|
3
14
|
## 0.53.1-beta
|
|
4
15
|
|
|
5
16
|
### Patch Changes
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Restate's request identity key in its own format (`publickeyv1_` and the base58btc encoding of
|
|
3
|
+
* the raw 32-byte Ed25519 public key), from a PEM: Restate's PKCS#8 private key, as the Helm chart
|
|
4
|
+
* mounts it, or the SPKI public key. `nylorun start` computes the same string
|
|
5
|
+
* (cli/nylorun/src/stack/restate-identity.ts) and passes it as NYLORUN_RESTATE_IDENTITY_KEY.
|
|
6
|
+
*/
|
|
7
|
+
export declare function restateIdentityKeyOf(pem: string): string;
|
|
8
|
+
/** Base58 with the Bitcoin alphabet; each leading zero byte becomes "1". */
|
|
9
|
+
export declare function base58btc(bytes: Uint8Array): string;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { createPrivateKey, createPublicKey } from "node:crypto";
|
|
2
|
+
/**
|
|
3
|
+
* Restate's request identity key in its own format (`publickeyv1_` and the base58btc encoding of
|
|
4
|
+
* the raw 32-byte Ed25519 public key), from a PEM: Restate's PKCS#8 private key, as the Helm chart
|
|
5
|
+
* mounts it, or the SPKI public key. `nylorun start` computes the same string
|
|
6
|
+
* (cli/nylorun/src/stack/restate-identity.ts) and passes it as NYLORUN_RESTATE_IDENTITY_KEY.
|
|
7
|
+
*/
|
|
8
|
+
export function restateIdentityKeyOf(pem) {
|
|
9
|
+
const text = pem.trim();
|
|
10
|
+
const key = text.includes("PRIVATE KEY") ? createPublicKey(createPrivateKey(text)) : createPublicKey(text);
|
|
11
|
+
if (key.asymmetricKeyType !== "ed25519")
|
|
12
|
+
throw new Error("not an Ed25519 key");
|
|
13
|
+
const raw = Buffer.from(key.export({ format: "jwk" }).x ?? "", "base64url");
|
|
14
|
+
if (raw.length !== 32)
|
|
15
|
+
throw new Error("the public key is not 32 bytes");
|
|
16
|
+
return `publickeyv1_${base58btc(raw)}`;
|
|
17
|
+
}
|
|
18
|
+
const BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
19
|
+
/** Base58 with the Bitcoin alphabet; each leading zero byte becomes "1". */
|
|
20
|
+
export function base58btc(bytes) {
|
|
21
|
+
let zeros = 0;
|
|
22
|
+
while (zeros < bytes.length && bytes[zeros] === 0)
|
|
23
|
+
zeros += 1;
|
|
24
|
+
const digits = [];
|
|
25
|
+
for (let index = zeros; index < bytes.length; index += 1) {
|
|
26
|
+
let carry = bytes[index];
|
|
27
|
+
for (let digit = 0; digit < digits.length; digit += 1) {
|
|
28
|
+
carry += digits[digit] * 256;
|
|
29
|
+
digits[digit] = carry % 58;
|
|
30
|
+
carry = Math.floor(carry / 58);
|
|
31
|
+
}
|
|
32
|
+
while (carry > 0) {
|
|
33
|
+
digits.push(carry % 58);
|
|
34
|
+
carry = Math.floor(carry / 58);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
let out = "1".repeat(zeros);
|
|
38
|
+
for (let digit = digits.length - 1; digit >= 0; digit -= 1)
|
|
39
|
+
out += BASE58_ALPHABET[digits[digit]];
|
|
40
|
+
return out;
|
|
41
|
+
}
|
|
@@ -53,6 +53,8 @@ import { LOOPBACK_HOSTS } from "@nylorun/core/contracts";
|
|
|
53
53
|
import { blockedAddresses } from "../sandbox/pods/network-gate.js";
|
|
54
54
|
import { HostTuningError, parseHostTuning } from "../tuning.js";
|
|
55
55
|
import { HOST_IDENTITY_PROVIDERS } from "../vault/host-identity.js";
|
|
56
|
+
import { readFileSync } from "node:fs";
|
|
57
|
+
import { restateIdentityKeyOf } from "./restate-identity.js";
|
|
56
58
|
export const RUNTIME_SERVICES = ["core", "loop", "gates", "keys", "egress", "harness", "computer"];
|
|
57
59
|
/**
|
|
58
60
|
* Services that may share a process (D12): they hold the same secrets and parse the same
|
|
@@ -246,14 +248,28 @@ function parseListen(env) {
|
|
|
246
248
|
});
|
|
247
249
|
}
|
|
248
250
|
const IDENTITY_KEY = /^publickeyv1_[1-9A-HJ-NP-Za-km-z]{32,64}$/;
|
|
251
|
+
/**
|
|
252
|
+
* The keys Restate signs with: NYLORUN_RESTATE_IDENTITY_KEY (`publickeyv1_…`, comma-separated),
|
|
253
|
+
* and NYLORUN_RESTATE_IDENTITY_KEY_FILE, a PEM of the key (Restate's private key as the Helm chart
|
|
254
|
+
* mounts it, or the public key) whose `publickeyv1_…` the Runtime computes.
|
|
255
|
+
*/
|
|
249
256
|
function parseIdentityKeys(env) {
|
|
250
257
|
const raw = read(env, "NYLORUN_RESTATE_IDENTITY_KEY");
|
|
251
|
-
|
|
258
|
+
const file = read(env, "NYLORUN_RESTATE_IDENTITY_KEY_FILE");
|
|
259
|
+
if (raw === undefined && file === undefined)
|
|
252
260
|
return undefined;
|
|
253
|
-
const keys = raw
|
|
261
|
+
const keys = (raw ?? "")
|
|
254
262
|
.split(",")
|
|
255
263
|
.map((key) => key.trim())
|
|
256
264
|
.filter((key) => key !== "");
|
|
265
|
+
if (file !== undefined) {
|
|
266
|
+
try {
|
|
267
|
+
keys.push(restateIdentityKeyOf(readFileSync(file, "utf8")));
|
|
268
|
+
}
|
|
269
|
+
catch (error) {
|
|
270
|
+
throw new StackConfigError(`NYLORUN_RESTATE_IDENTITY_KEY_FILE ${file} is not an Ed25519 PEM: ${error instanceof Error ? error.message : String(error)}`);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
257
273
|
for (const key of keys)
|
|
258
274
|
if (!IDENTITY_KEY.test(key))
|
|
259
275
|
throw new StackConfigError("NYLORUN_RESTATE_IDENTITY_KEY must be publickeyv1_<base58 Ed25519 public key>, comma-separated");
|
package/dist/openapi.json
CHANGED
package/dist/sandbox/computer.js
CHANGED
|
@@ -68,6 +68,10 @@ export async function computerAccess(ctx, id, signal) {
|
|
|
68
68
|
return fail(409, `Agent ${id}'s computer failed: ${pod.reason ?? "it did not start"}.`, { code: "agent_unavailable" });
|
|
69
69
|
const status = await pods.client.status(pod.k8sName, { wait: "ready", timeoutMs: 20_000 }).catch(() => undefined);
|
|
70
70
|
if (status?.ready && status.podUID) {
|
|
71
|
+
// A drain the reconcile hasn't recorded yet (suspend before drain resumed it elsewhere,
|
|
72
|
+
// ready at once): the reconcile records it, once.
|
|
73
|
+
if (status.drainedAt !== undefined && status.drainedAt !== pod.drainedAt)
|
|
74
|
+
await ctx.sandboxSignal(id, { kind: "reconcile" }).catch(() => undefined);
|
|
71
75
|
await firstContact(ctx, id, status.podUID);
|
|
72
76
|
const expiresAt = Date.now() + computers.ttlMs;
|
|
73
77
|
return {
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const RUNTIME_VERSION = "0.53.
|
|
1
|
+
export declare const RUNTIME_VERSION = "0.53.2-beta";
|
package/dist/version.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// Kept in step with package.json by runtime/server/scripts/check-package.mjs, which runs in npm run check.
|
|
2
2
|
// release:prepare also rewrites this when it bumps @nylorun/runtime.
|
|
3
|
-
export const RUNTIME_VERSION = "0.53.
|
|
3
|
+
export const RUNTIME_VERSION = "0.53.2-beta";
|
package/package.json
CHANGED