@byollm/protocol 0.1.0-alpha.94 → 0.1.0-alpha.96

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/dist/index.js CHANGED
@@ -1,3 +1,23 @@
1
+ import {
2
+ CONSOLE_FRAME_VERSION,
3
+ CONSOLE_MAX_DATA_BYTES,
4
+ ConsoleBye,
5
+ ConsoleFrame,
6
+ ConsoleHello,
7
+ ConsoleResize,
8
+ ConsoleStdin,
9
+ ConsoleStdout,
10
+ ENVELOPE_BODY_VERSION,
11
+ PublicIdentity,
12
+ consoleEnvelope,
13
+ consoleOrder,
14
+ decodeEnvelopeInner,
15
+ encodeEnvelopeInner,
16
+ envelopeSignedBody,
17
+ fromBase64Url,
18
+ toBase64Url
19
+ } from "./chunk-W7Q7DKQ6.js";
20
+
1
21
  // src/wire.ts
2
22
  import { z as z9 } from "zod";
3
23
 
@@ -11,20 +31,6 @@ import {
11
31
  verify
12
32
  } from "crypto";
13
33
  import { z } from "zod";
14
- var PublicIdentity = z.object({
15
- /** Raw Ed25519 public key. The pinned one. */
16
- identity: z.string().min(1),
17
- /** Raw X25519 public key, for sealing to this party. */
18
- encryption: z.string().min(1),
19
- /**
20
- * Ed25519 signature over the encryption key, by the identity key.
21
- *
22
- * This is what stops an upstream substituting an encryption key of its
23
- * own while relaying a genuine identity: the receiver pins the identity
24
- * and refuses any encryption key not signed by it.
25
- */
26
- encryptionSig: z.string().min(1)
27
- }).strict();
28
34
  var StoredKeys = z.object({
29
35
  version: z.literal(1),
30
36
  identityPublic: z.string().min(1),
@@ -89,16 +95,16 @@ function verifyPublicIdentity(identity) {
89
95
  return false;
90
96
  }
91
97
  }
92
- function signWith(keys, data2) {
93
- return sign(null, data2, importPrivate(keys.identityPrivate)).toString(
98
+ function signWith(keys, data) {
99
+ return sign(null, data, importPrivate(keys.identityPrivate)).toString(
94
100
  "base64url"
95
101
  );
96
102
  }
97
- function verifyWith(identityPublic, data2, signature) {
103
+ function verifyWith(identityPublic, data, signature) {
98
104
  try {
99
105
  return verify(
100
106
  null,
101
- data2,
107
+ data,
102
108
  importPublic(identityPublic, "Ed25519"),
103
109
  Buffer.from(signature, "base64url")
104
110
  );
@@ -1163,85 +1169,6 @@ var ClaimedStub = JobStub.extend({
1163
1169
  import { createPrivateKey as createPrivateKey2, createPublicKey as createPublicKey2 } from "crypto";
1164
1170
  import sodium from "libsodium-wrappers";
1165
1171
  import { z as z8 } from "zod";
1166
-
1167
- // src/envelope-format.ts
1168
- var ALPHABET2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
1169
- var CHARS = ALPHABET2.split("");
1170
- var VALUES = /* @__PURE__ */ (() => {
1171
- const table = new Uint8Array(128).fill(255);
1172
- for (let at = 0; at < ALPHABET2.length; at += 1) {
1173
- table[ALPHABET2.charCodeAt(at)] = at;
1174
- }
1175
- return table;
1176
- })();
1177
- function toBase64Url(bytes) {
1178
- let out = "";
1179
- for (let at = 0; at < bytes.length; at += 3) {
1180
- const a = bytes[at] ?? 0;
1181
- const b = bytes[at + 1];
1182
- const c = bytes[at + 2];
1183
- const word = a << 16 | (b ?? 0) << 8 | (c ?? 0);
1184
- out += CHARS[word >> 18 & 63] ?? "";
1185
- out += CHARS[word >> 12 & 63] ?? "";
1186
- if (b !== void 0) out += CHARS[word >> 6 & 63] ?? "";
1187
- if (c !== void 0) out += CHARS[word & 63] ?? "";
1188
- }
1189
- return out;
1190
- }
1191
- function fromBase64Url(text) {
1192
- const length = text.length;
1193
- if (length % 4 === 1) return void 0;
1194
- const bytes = new Uint8Array(Math.floor(length * 3 / 4));
1195
- let written = 0;
1196
- let word = 0;
1197
- let bits = 0;
1198
- for (let at = 0; at < length; at += 1) {
1199
- const code = text.charCodeAt(at);
1200
- const value = code < 128 ? VALUES[code] : 255;
1201
- if (value === void 0 || value === 255) return void 0;
1202
- word = word << 6 | value;
1203
- bits += 6;
1204
- if (bits >= 8) {
1205
- bits -= 8;
1206
- bytes[written] = word >> bits & 255;
1207
- written += 1;
1208
- }
1209
- }
1210
- return bytes.subarray(0, written);
1211
- }
1212
- var ENVELOPE_BODY_VERSION = "byollm/v1/envelope";
1213
- function envelopeSignedBody(context, plaintext) {
1214
- return new TextEncoder().encode(
1215
- JSON.stringify({
1216
- v: ENVELOPE_BODY_VERSION,
1217
- jobId: context.jobId,
1218
- senderKeyId: context.senderKeyId,
1219
- recipientKeyId: context.recipientKeyId,
1220
- deadlineAt: context.deadlineAt,
1221
- direction: context.direction,
1222
- plaintext
1223
- })
1224
- );
1225
- }
1226
- function encodeEnvelopeInner(body, signature) {
1227
- return JSON.stringify({ body: toBase64Url(body), signature });
1228
- }
1229
- function decodeEnvelopeInner(text) {
1230
- let parsed;
1231
- try {
1232
- parsed = JSON.parse(text);
1233
- } catch {
1234
- return void 0;
1235
- }
1236
- if (typeof parsed.body !== "string" || typeof parsed.signature !== "string") {
1237
- return void 0;
1238
- }
1239
- const body = fromBase64Url(parsed.body);
1240
- if (body === void 0) return void 0;
1241
- return { body, signature: parsed.signature };
1242
- }
1243
-
1244
- // src/envelope.ts
1245
1172
  var readied;
1246
1173
  async function cryptoReady() {
1247
1174
  readied ??= sodium.ready;
@@ -2722,118 +2649,6 @@ var MUST_IDS = Object.freeze(Object.keys(MUSTS));
2722
2649
  function mustsVerifiedBy(kind) {
2723
2650
  return MUST_IDS.filter((id) => kindsOf(MUSTS[id]).includes(kind));
2724
2651
  }
2725
-
2726
- // src/console.ts
2727
- import { z as z12 } from "zod";
2728
- var CONSOLE_FRAME_VERSION = "byollm/v1/console";
2729
- var CONSOLE_MAX_DATA_BYTES = 64 * 1024;
2730
- var data = z12.string().max(Math.ceil(CONSOLE_MAX_DATA_BYTES * 4 / 3) + 4).describe("base64");
2731
- var cols = z12.number().int().min(1).max(1e4);
2732
- var rows = z12.number().int().min(1).max(1e4);
2733
- var seq = z12.number().int().positive();
2734
- var ConsoleHello = z12.object({
2735
- v: z12.literal(CONSOLE_FRAME_VERSION),
2736
- kind: z12.literal("hello"),
2737
- seq: z12.literal(1),
2738
- /**
2739
- * The browser's EPHEMERAL identity for this session, and the reason hello
2740
- * exists as its own frame.
2741
- *
2742
- * A browser has no long-term key — it is a tab, not a machine — so it
2743
- * generates one per session and the box seals its output to it. That key
2744
- * has to reach the box without the hub being able to substitute one of its
2745
- * own, which is the classic broker attack. So it travels SEALED TO THE
2746
- * BOX'S PINNED IDENTITY like every other frame: the hub cannot read it and
2747
- * cannot replace it, because replacing it means producing a sealed box
2748
- * the box's key opens and the browser's key signed.
2749
- *
2750
- * The box does not pin this. It cannot — it is new every session, and
2751
- * nothing authorises it cryptographically. What authorises the browser is
2752
- * the hub's per-session grant (ruling item 2); what this key does is keep
2753
- * the hub from READING what it authorised.
2754
- */
2755
- browser: PublicIdentity,
2756
- cols,
2757
- rows
2758
- }).strict();
2759
- var ConsoleStdin = z12.object({
2760
- v: z12.literal(CONSOLE_FRAME_VERSION),
2761
- /** Browser→box only. A `stdin` arriving from the box is `wrong-way`. */
2762
- kind: z12.literal("stdin"),
2763
- seq,
2764
- data
2765
- }).strict();
2766
- var ConsoleStdout = z12.object({
2767
- v: z12.literal(CONSOLE_FRAME_VERSION),
2768
- /** Box→browser only. */
2769
- kind: z12.literal("stdout"),
2770
- seq,
2771
- data
2772
- }).strict();
2773
- var ConsoleResize = z12.object({
2774
- v: z12.literal(CONSOLE_FRAME_VERSION),
2775
- kind: z12.literal("resize"),
2776
- seq,
2777
- cols,
2778
- rows
2779
- }).strict();
2780
- var ConsoleBye = z12.object({
2781
- v: z12.literal(CONSOLE_FRAME_VERSION),
2782
- kind: z12.literal("bye"),
2783
- seq,
2784
- /** Shown to the owner in the session feed, so it is a sentence. */
2785
- reason: z12.string().min(1).max(200)
2786
- }).strict();
2787
- var ConsoleFrame = z12.discriminatedUnion("kind", [
2788
- ConsoleHello,
2789
- ConsoleStdin,
2790
- ConsoleStdout,
2791
- ConsoleResize,
2792
- ConsoleBye
2793
- ]);
2794
- function consoleEnvelope(input) {
2795
- return {
2796
- jobId: input.sessionId,
2797
- senderKeyId: input.senderKeyId,
2798
- recipientKeyId: input.recipientKeyId,
2799
- deadlineAt: input.deadlineAt,
2800
- direction: input.from === "browser" ? "payload" : "result"
2801
- };
2802
- }
2803
- function consoleOrder(from) {
2804
- const maySend = {
2805
- // The browser drives: it opens, it types, it sets the size, it leaves.
2806
- browser: ["hello", "stdin", "resize", "bye"],
2807
- // The box answers, and can end a session. Nothing else.
2808
- box: ["stdout", "bye"]
2809
- };
2810
- const allowed = maySend[from];
2811
- const opensWithHello = from === "browser";
2812
- let last = 0;
2813
- let closed = false;
2814
- return {
2815
- /** The last sequence accepted. 0 before anything has been. */
2816
- get seen() {
2817
- return last;
2818
- },
2819
- accept(frame) {
2820
- if (closed) return { ok: false, fault: "closed" };
2821
- if (!allowed.includes(frame.kind)) {
2822
- return { ok: false, fault: "wrong-way" };
2823
- }
2824
- const isFirst = last === 0;
2825
- const wantsHello = isFirst && opensWithHello;
2826
- if (wantsHello !== (frame.kind === "hello")) {
2827
- return { ok: false, fault: "out-of-turn" };
2828
- }
2829
- if (frame.seq <= last) return { ok: false, fault: "replayed" };
2830
- if (frame.seq !== last + 1) return { ok: false, fault: "gap" };
2831
- last = frame.seq;
2832
- if (frame.kind === "bye") closed = true;
2833
- return { ok: true };
2834
- }
2835
- };
2836
- }
2837
2652
  export {
2838
2653
  ABOUT,
2839
2654
  ABOUT_SHORT,