@ai-ecoverse/slicc-kernel 1.133.5 → 1.134.0

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/README.md CHANGED
@@ -504,7 +504,13 @@ The module's default export (or its `main` export) is called with a context and
504
504
  - `AUTH PLAIN <blob>`, or the line after a bare `AUTH PLAIN`: the kernel decodes the blob, and asks the vault (`auth-plain`) only when the placeholders are in the **password field**. A placeholder in the user or authorization identity goes out as written. It substitutes there and re-encodes.
505
505
  - `AUTH LOGIN`: the password line (the second line, or the first after `AUTH LOGIN <user>`) is decoded, substituted (`auth-login`) and re-encoded; the user line goes out as written.
506
506
  - Every other line goes out as written. After the first `AUTH`, or once `MAIL`, `RCPT`, `DATA` or `BDAT` is seen, so is the rest of the session. A line still unfinished after 2 s, or longer than 4 KiB, is sent as written, and so is the rest.
507
- - **pg:** a session that starts with a protocol 3 `StartupMessage` (after `sslmode`'s `SSLRequest` upgrade, or with direct TLS) is followed message by message. The only position is the **`PasswordMessage` answering `AuthenticationCleartextPassword` (`R` 3)**, as the program read it from the server. The password is substituted (`password-cleartext`) and the message is framed again. Anything else goes out as written: the startup, an MD5 (`R` 5) or SCRAM (`R` 10) answer, every later message, and a frame over 16 KiB. MD5 and SCRAM need the kernel to compute the answer from the password, so they aren't supported yet. A server whose `pg_hba` asks for them gets the placeholder, and refuses.
507
+ - **pg:** a session that starts with a protocol 3 `StartupMessage` (after `sslmode`'s `SSLRequest` upgrade, or with direct TLS) is followed message by message. The only position is the **`PasswordMessage` answering `AuthenticationCleartextPassword` (`R` 3)**, as the program read it from the server. The password is substituted (`password-cleartext`) and the message is framed again. **SCRAM-SHA-256** (`R` 10, the pg 14+ default) works with an unmodified client:
508
+ - **What the server is offered:** in a session that can substitute, the kernel offers the program only `SCRAM-SHA-256`, never `-PLUS`. The program's client computes its proof from the placeholder. Dropping `-PLUS` costs nothing here: the kernel terminates and verifies the TLS itself, so channel binding would only bind to the kernel's own session. A client that **requires** channel binding (libpq's `channel_binding=require`) refuses the connection and never gets the value, so leave it at `prefer` or `disable` for sealed SCRAM.
509
+ - **The match:** the kernel sends the three SCRAM messages and that proof to the vault (`scram-sha-256`, with no placeholders), and the vault names the one bound placeholder whose proof matches.
510
+ - **The exchange:** the kernel recomputes the proof from the value and sends that instead. It checks the server's final signature against the value **before** it hands the program the signature its own placeholder-based check expects. A server whose signature doesn't verify, or that answers with an error, ends the session (`EPROTO`) without passing it on. The salted password and the derived keys are wiped after the exchange.
511
+ - **Requirements:** only the plain GS2 header (`n,,`) and the bare RFC 5802 messages; at most 100000 iterations.
512
+
513
+ Anything else goes out as written: the startup, an MD5 (`R` 5) answer, every later message, and a frame over 16 KiB. A server whose `pg_hba` asks for MD5 gets the placeholder, and refuses.
508
514
  - **What goes out:** the placeholders the vault answers with a value of at least 8 bytes go out as that value (`Basic` decoded, substituted and re-encoded). Everything else goes out as written:
509
515
  - the request line and the body;
510
516
  - other headers;
@@ -7095,7 +7095,7 @@ function satisfies(version, range2) {
7095
7095
  }
7096
7096
 
7097
7097
  // src/version.ts
7098
- var KERNEL_VERSION = true ? "1.133.5" : "0.0.0-dev";
7098
+ var KERNEL_VERSION = true ? "1.134.0" : "0.0.0-dev";
7099
7099
  var OS_RELEASE = "6.0.0-slicc";
7100
7100
  function procVersion() {
7101
7101
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -14158,8 +14158,8 @@ var EventFd = class _EventFd {
14158
14158
  count;
14159
14159
  semaphore;
14160
14160
  changes = new Notifier();
14161
- constructor(initial, semaphore) {
14162
- this.count = initial;
14161
+ constructor(initial2, semaphore) {
14162
+ this.count = initial2;
14163
14163
  this.semaphore = semaphore;
14164
14164
  }
14165
14165
  async read(max, signal) {
@@ -17908,7 +17908,7 @@ var UNSAFE = /[\r\n\0]/;
17908
17908
  var POSITIONS = {
17909
17909
  http1: (position) => HEADER.test(position),
17910
17910
  smtp: (position) => position === "auth-plain" || position === "auth-login",
17911
- pg: (position) => position === "password-cleartext"
17911
+ pg: (position) => position === "password-cleartext" || position === "scram-sha-256"
17912
17912
  };
17913
17913
  function boundHost(servername) {
17914
17914
  const lower = servername.toLowerCase();
@@ -17923,6 +17923,15 @@ function placeholdersOk(list) {
17923
17923
  if (!Array.isArray(list) || list.length === 0 || list.length > SESSION_PLACEHOLDERS) return false;
17924
17924
  return new Set(list).size === list.length && list.every((p) => typeof p === "string" && SESSION_PLACEHOLDER.test(p));
17925
17925
  }
17926
+ var SCRAM_TEXT = /^[\x21-\x7e]{1,1024}$/;
17927
+ function scramOk(f) {
17928
+ if (f.position !== "scram-sha-256")
17929
+ return f.scram === void 0 && placeholdersOk(f.placeholders);
17930
+ const x = f.scram;
17931
+ if (f.placeholders !== void 0 || typeof x !== "object" || x === null) return false;
17932
+ const texts = [x.clientFirstBare, x.serverFirst, x.clientFinalBare, x.proof];
17933
+ return texts.every((t) => typeof t === "string" && SCRAM_TEXT.test(t));
17934
+ }
17926
17935
  function hostOk(host) {
17927
17936
  return typeof host === "string" && HOST.test(host) && boundHost(host) === host;
17928
17937
  }
@@ -17934,7 +17943,7 @@ function sessionAskable(f, now) {
17934
17943
  if (!Number.isInteger(f.port) || f.port < 1 || f.port > 65535) return false;
17935
17944
  const age = now - f.handshakeAt;
17936
17945
  if (!Number.isFinite(age) || age < 0 || age > SESSION_WINDOW_MS) return false;
17937
- return typeof f.exit === "string" && SESSION_EXIT.test(f.exit) && placeholdersOk(f.placeholders) && headOk(f);
17946
+ return typeof f.exit === "string" && SESSION_EXIT.test(f.exit) && scramOk(f) && headOk(f);
17938
17947
  }
17939
17948
  function sessionRequest(f) {
17940
17949
  return {
@@ -17950,8 +17959,16 @@ function sessionRequest(f) {
17950
17959
  verified: true,
17951
17960
  handshakeAt: f.handshakeAt,
17952
17961
  exit: f.exit,
17953
- placeholders: [...f.placeholders],
17954
- ...f.head ? { head: { method: f.head.method, path: f.head.path } } : {}
17962
+ ...f.placeholders ? { placeholders: [...f.placeholders] } : {},
17963
+ ...f.head ? { head: { method: f.head.method, path: f.head.path } } : {},
17964
+ ...f.scram ? {
17965
+ scram: {
17966
+ clientFirstBare: f.scram.clientFirstBare,
17967
+ serverFirst: f.scram.serverFirst,
17968
+ clientFinalBare: f.scram.clientFinalBare,
17969
+ proof: f.scram.proof
17970
+ }
17971
+ } : {}
17955
17972
  };
17956
17973
  }
17957
17974
  function sessionValues(reply, asked) {
@@ -17959,7 +17976,9 @@ function sessionValues(reply, asked) {
17959
17976
  const { error, values } = reply;
17960
17977
  if (error !== void 0 || typeof values !== "object" || values === null) return void 0;
17961
17978
  const out = {};
17962
- for (const ph of asked) {
17979
+ const keys = Object.keys(values);
17980
+ const wanted = asked ?? (keys.length === 1 && SESSION_PLACEHOLDER.test(keys[0]) ? keys : []);
17981
+ for (const ph of wanted) {
17963
17982
  const value2 = values[ph];
17964
17983
  if (typeof value2 === "string" && value2.length > 0 && !UNSAFE.test(value2)) out[ph] = value2;
17965
17984
  }
@@ -18651,6 +18670,104 @@ async function substituteHead(head, ask) {
18651
18670
  `, values };
18652
18671
  }
18653
18672
 
18673
+ // src/kernel/net/sealed-scram.ts
18674
+ var encoder8 = new TextEncoder();
18675
+ function base64Bytes(text) {
18676
+ try {
18677
+ return Uint8Array.from(atob(text), (c) => c.charCodeAt(0));
18678
+ } catch {
18679
+ return void 0;
18680
+ }
18681
+ }
18682
+ function base64Of(bytes) {
18683
+ let bin = "";
18684
+ for (const b of bytes) bin += String.fromCharCode(b);
18685
+ return btoa(bin);
18686
+ }
18687
+ function clientFirstBare(message3) {
18688
+ const m = /^n,,(n=[^,]*,r=[^,]+)$/.exec(message3);
18689
+ return m ? m[1] : void 0;
18690
+ }
18691
+ var SERVER_FIRST = /^r=([^,]+),s=([^,]+),i=(\d{1,6})$/;
18692
+ var CLIENT_FINAL = /^(c=biws,r=([^,]+)),p=([^,]+)$/;
18693
+ var SCRAM_MAX = 1024;
18694
+ function exchangeOf(clientFirst, serverFirst, clientFinal) {
18695
+ const bare = clientFirstBare(clientFirst);
18696
+ const sf = SERVER_FIRST.exec(serverFirst);
18697
+ const fin = CLIENT_FINAL.exec(clientFinal);
18698
+ if (!bare || !sf || !fin || [bare, serverFirst, clientFinal].some((t) => t.length > SCRAM_MAX))
18699
+ return void 0;
18700
+ const cnonce = bare.slice(bare.indexOf(",r=") + 3);
18701
+ const nonce = sf[1];
18702
+ const salt = base64Bytes(sf[2]);
18703
+ const iterations = Number(sf[3]);
18704
+ const proof = base64Bytes(fin[3]);
18705
+ const ok4 = fin[2] === nonce && nonce.startsWith(cnonce) && iterations >= 1 && iterations <= 1e5 && salt !== void 0 && proof?.length === 32;
18706
+ if (!ok4) return void 0;
18707
+ return {
18708
+ exchange: {
18709
+ clientFirstBare: bare,
18710
+ serverFirst,
18711
+ clientFinalBare: fin[1],
18712
+ salt,
18713
+ iterations
18714
+ },
18715
+ proof
18716
+ };
18717
+ }
18718
+ async function hmac(key, data) {
18719
+ const k = await crypto.subtle.importKey(
18720
+ "raw",
18721
+ key,
18722
+ { name: "HMAC", hash: "SHA-256" },
18723
+ false,
18724
+ ["sign"]
18725
+ );
18726
+ return new Uint8Array(await crypto.subtle.sign("HMAC", k, data));
18727
+ }
18728
+ async function scramKeys(password, x) {
18729
+ const base = await crypto.subtle.importKey("raw", encoder8.encode(password), "PBKDF2", false, [
18730
+ "deriveBits"
18731
+ ]);
18732
+ const salted = new Uint8Array(
18733
+ await crypto.subtle.deriveBits(
18734
+ {
18735
+ name: "PBKDF2",
18736
+ hash: "SHA-256",
18737
+ salt: x.salt,
18738
+ iterations: x.iterations
18739
+ },
18740
+ base,
18741
+ 256
18742
+ )
18743
+ );
18744
+ const clientKey = await hmac(salted, encoder8.encode("Client Key"));
18745
+ const stored = new Uint8Array(
18746
+ await crypto.subtle.digest("SHA-256", clientKey)
18747
+ );
18748
+ const auth = encoder8.encode(`${x.clientFirstBare},${x.serverFirst},${x.clientFinalBare}`);
18749
+ const signature = await hmac(stored, auth);
18750
+ const proof = clientKey.map((b, i) => b ^ signature[i]);
18751
+ const serverKey = await hmac(salted, encoder8.encode("Server Key"));
18752
+ const serverSignature = await hmac(serverKey, auth);
18753
+ for (const k of [salted, clientKey, stored, signature, serverKey]) k.fill(0);
18754
+ return { proof, serverSignature };
18755
+ }
18756
+ var SPACES = /[\u00A0\u1680\u2000-\u200B\u202F\u205F\u3000]/g;
18757
+ var NOTHING2 = /\u00AD|\u034F|\u1806|[\u180B-\u180D]|\u200C|\u200D|\u2060|[\uFE00-\uFE0F]|\uFEFF/g;
18758
+ var PROHIBITED = /[\u0000-\u001F\u007F-\u009F\uE000-\uF8FF\uFFFE\uFFFF]/;
18759
+ function saslprep(password) {
18760
+ if (/^[\x20-\x7e]*$/.test(password)) return password;
18761
+ const mapped = password.replace(SPACES, " ").replace(NOTHING2, "").normalize("NFKC");
18762
+ return PROHIBITED.test(mapped) ? password : mapped;
18763
+ }
18764
+ function sameBytes(a, b) {
18765
+ if (a.length !== b.length) return false;
18766
+ let d = 0;
18767
+ for (let i = 0; i < a.length; i++) d |= a[i] ^ b[i];
18768
+ return d === 0;
18769
+ }
18770
+
18654
18771
  // src/kernel/net/sealed-pg.ts
18655
18772
  var PG_MESSAGE_MAX = 16 * 1024;
18656
18773
  var PROTOCOL_3 = 196608;
@@ -18665,44 +18782,101 @@ function sniffPg(start2) {
18665
18782
  const length2 = int32(bytes, 0);
18666
18783
  return length2 >= 8 && length2 <= PG_MESSAGE_MAX && int32(bytes, 4) === PROTOCOL_3 ? "yes" : "no";
18667
18784
  }
18785
+ var PLUS = "SCRAM-SHA-256-PLUS";
18786
+ var SASL = 10;
18787
+ var SASL_CONTINUE = 11;
18788
+ var SASL_FINAL = 12;
18789
+ function latin(bytes) {
18790
+ let out = "";
18791
+ for (const b of bytes) out += String.fromCharCode(b);
18792
+ return out;
18793
+ }
18668
18794
  var PgServer = class {
18669
18795
  buffer = new Uint8Array(0);
18670
18796
  skip = 0;
18671
- lost = false;
18672
18797
  cleartext = false;
18673
- feed(bytes) {
18674
- if (this.lost) return;
18798
+ sasl = false;
18799
+ serverFirst;
18800
+ expect;
18801
+ failed = false;
18802
+ lost = false;
18803
+ auth(message3) {
18804
+ const code = message3.length >= 9 ? int32(message3, 5) : -1;
18805
+ if (this.expect && code !== SASL_FINAL) this.failed = true;
18806
+ this.cleartext = message3.length === 9 && code === CLEARTEXT;
18807
+ if (code === SASL) return this.mechanisms(message3);
18808
+ else if (code === SASL_CONTINUE) this.serverFirst = latin(message3.subarray(9));
18809
+ else if (code === SASL_FINAL) this.final(message3);
18810
+ return message3;
18811
+ }
18812
+ mechanisms(message3) {
18813
+ this.sasl = true;
18814
+ const names2 = latin(message3.subarray(9)).split("\0").filter((n) => n !== "" && n !== PLUS);
18815
+ return frame3(82, `${latin(message3.subarray(5, 9))}${names2.map((n) => `${n}\0`).join("")}\0`);
18816
+ }
18817
+ final(message3) {
18818
+ const expect = this.expect;
18819
+ if (!expect) return;
18820
+ this.expect = void 0;
18821
+ const data = latin(message3.subarray(9));
18822
+ if (data !== expect.real || expect.fake.length !== expect.real.length) {
18823
+ this.failed = true;
18824
+ return;
18825
+ }
18826
+ for (let i = 0; i < expect.fake.length; i++) message3[9 + i] = expect.fake.charCodeAt(i);
18827
+ }
18828
+ lose() {
18829
+ this.lost = true;
18830
+ this.cleartext = false;
18831
+ this.sasl = false;
18832
+ if (this.expect) this.failed = true;
18833
+ this.expect = void 0;
18834
+ }
18835
+ filter(bytes) {
18836
+ if (this.lost) return bytes;
18675
18837
  const data = new Uint8Array(this.buffer.length + bytes.length);
18676
18838
  data.set(this.buffer);
18677
18839
  data.set(bytes, this.buffer.length);
18840
+ const out = [];
18678
18841
  let at = 0;
18679
18842
  for (; ; ) {
18680
18843
  const left = data.length - at;
18681
18844
  if (this.skip > 0) {
18682
18845
  const n = Math.min(this.skip, left);
18846
+ out.push(data.subarray(at, at + n));
18683
18847
  this.skip -= n;
18684
18848
  at += n;
18685
18849
  if (this.skip > 0) break;
18686
18850
  continue;
18687
18851
  }
18688
18852
  if (left < 5) break;
18689
- const type = data[at];
18690
18853
  const whole = 1 + int32(data, at + 1);
18691
- if (whole < 5 || type === 82 && whole > PG_MESSAGE_MAX) {
18692
- this.lost = true;
18693
- this.cleartext = false;
18694
- this.buffer = new Uint8Array(0);
18695
- return;
18854
+ if (whole < 5 || data[at] === 82 && whole > PG_MESSAGE_MAX) {
18855
+ this.lose();
18856
+ out.push(data.subarray(at));
18857
+ at = data.length;
18858
+ break;
18696
18859
  }
18697
- if (type !== 82) {
18860
+ if (data[at] !== 82) {
18861
+ if (this.expect) {
18862
+ this.failed = true;
18863
+ break;
18864
+ }
18698
18865
  this.skip = whole;
18699
18866
  continue;
18700
18867
  }
18701
18868
  if (left < whole) break;
18702
- this.cleartext = whole === 9 && int32(data, at + 5) === CLEARTEXT;
18869
+ out.push(this.auth(data.slice(at, at + whole)));
18703
18870
  at += whole;
18704
18871
  }
18705
18872
  this.buffer = data.slice(at);
18873
+ const joined4 = new Uint8Array(out.reduce((n, b) => n + b.length, 0));
18874
+ let to = 0;
18875
+ for (const b of out) {
18876
+ joined4.set(b, to);
18877
+ to += b.length;
18878
+ }
18879
+ return joined4;
18706
18880
  }
18707
18881
  };
18708
18882
  function frame3(type, body) {
@@ -18719,21 +18893,76 @@ function pgLength(bytes, started) {
18719
18893
  const length2 = int32(bytes, started ? 1 : 0);
18720
18894
  return started ? 1 + length2 : length2;
18721
18895
  }
18722
- async function pgPassword(message3, server, ask) {
18723
- if (message3[0] !== 112 || !server.cleartext) return { bytes: message3, done: true };
18724
- server.cleartext = false;
18725
- let body = "";
18726
- for (const b of message3.subarray(5)) body += String.fromCharCode(b);
18896
+ var MECHANISMS = /* @__PURE__ */ new Set(["SCRAM-SHA-256"]);
18897
+ async function cleartext(message3, asks) {
18898
+ const body = latin(message3.subarray(5));
18727
18899
  if (!body.endsWith("\0") || body.indexOf("\0") !== body.length - 1)
18728
18900
  return { bytes: message3, done: true };
18729
18901
  const password = body.slice(0, -1);
18730
18902
  const placeholders = placeholdersIn(password);
18731
18903
  if (placeholders.length === 0 || placeholders.length > SESSION_PLACEHOLDERS)
18732
18904
  return { bytes: message3, done: true };
18733
- const values = usable(await ask(placeholders));
18905
+ const values = usable(await asks.cleartext(placeholders));
18734
18906
  if (Object.keys(values).length === 0) return { bytes: message3, done: true };
18735
18907
  return { bytes: frame3(112, `${replaced(password, values)}\0`), values, done: true };
18736
18908
  }
18909
+ function initial(message3) {
18910
+ const body = latin(message3.subarray(5));
18911
+ const nul = body.indexOf("\0");
18912
+ if (nul < 0 || !MECHANISMS.has(body.slice(0, nul)) || body.length < nul + 5) return void 0;
18913
+ const data = message3.subarray(5 + nul + 5);
18914
+ return int32(message3, 5 + nul + 1) === data.length ? latin(data) : void 0;
18915
+ }
18916
+ var PgClient = class {
18917
+ clientFirst;
18918
+ server;
18919
+ asks;
18920
+ constructor(server, asks) {
18921
+ this.server = server;
18922
+ this.asks = asks;
18923
+ }
18924
+ async message(message3) {
18925
+ const server = this.server;
18926
+ if (message3[0] !== 112) return { bytes: message3, done: true };
18927
+ if (server.cleartext) {
18928
+ server.cleartext = false;
18929
+ return cleartext(message3, this.asks);
18930
+ }
18931
+ if (server.sasl && this.clientFirst === void 0) {
18932
+ this.clientFirst = initial(message3);
18933
+ return { bytes: message3, done: this.clientFirst === void 0 };
18934
+ }
18935
+ if (this.clientFirst !== void 0 && server.serverFirst !== void 0)
18936
+ return this.final(message3, this.clientFirst, server.serverFirst);
18937
+ return { bytes: message3, done: true };
18938
+ }
18939
+ async final(message3, first, serverFirst) {
18940
+ const got = exchangeOf(first, serverFirst, latin(message3.subarray(5)));
18941
+ if (!got) return { bytes: message3, done: true };
18942
+ const x = got.exchange;
18943
+ const values = usable(
18944
+ await this.asks.scram({
18945
+ clientFirstBare: x.clientFirstBare,
18946
+ serverFirst: x.serverFirst,
18947
+ clientFinalBare: x.clientFinalBare,
18948
+ proof: base64Of(got.proof)
18949
+ })
18950
+ );
18951
+ const [entry, ...more] = Object.entries(values);
18952
+ if (!entry || more.length > 0) return { bytes: message3, done: true };
18953
+ const [placeholder, value2] = entry;
18954
+ const fake = await scramKeys(placeholder, x);
18955
+ if (!sameBytes(fake.proof, got.proof)) return { bytes: message3, done: true };
18956
+ const real = await scramKeys(saslprep(value2), x);
18957
+ this.server.expect = {
18958
+ real: `v=${base64Of(real.serverSignature)}`,
18959
+ fake: `v=${base64Of(fake.serverSignature)}`
18960
+ };
18961
+ const bytes = frame3(112, `${x.clientFinalBare},p=${base64Of(real.proof)}`);
18962
+ for (const k of [real.proof, real.serverSignature, fake.proof, fake.serverSignature]) k.fill(0);
18963
+ return { bytes, values, done: true };
18964
+ }
18965
+ };
18737
18966
 
18738
18967
  // src/kernel/net/sealed-smtp.ts
18739
18968
  var SMTP_LINE_MAX = 4096;
@@ -18878,17 +19107,21 @@ var SessionWriter = class {
18878
19107
  session = sessionId();
18879
19108
  smtp;
18880
19109
  pgStarted = false;
19110
+ sawPg = false;
18881
19111
  conn;
18882
19112
  s;
18883
- pg;
19113
+ pgClient;
18884
19114
  scope;
18885
19115
  constructor(conn, s, pg, scope) {
18886
19116
  this.conn = conn;
18887
19117
  this.s = s;
18888
- this.pg = pg;
18889
19118
  this.scope = scope;
19119
+ this.pgClient = new PgClient(pg, {
19120
+ cleartext: (placeholders) => this.ask("pg", "password-cleartext", { placeholders }),
19121
+ scram: (scram) => this.ask("pg", "scram-sha-256", { scram })
19122
+ });
18890
19123
  this.smtp = new SmtpClient(
18891
- (position, placeholders) => this.ask("smtp", position, placeholders)
19124
+ (position, placeholders) => this.ask("smtp", position, { placeholders })
18892
19125
  );
18893
19126
  }
18894
19127
  write(bytes) {
@@ -18899,7 +19132,7 @@ var SessionWriter = class {
18899
19132
  );
18900
19133
  return run2;
18901
19134
  }
18902
- async ask(protocol, position, placeholders, head) {
19135
+ async ask(protocol, position, extra) {
18903
19136
  const s = this.s;
18904
19137
  const values = await s.broker.sessionMaterialize({
18905
19138
  stamp: await s.stamp(),
@@ -18911,8 +19144,7 @@ var SessionWriter = class {
18911
19144
  verified: s.verified,
18912
19145
  handshakeAt: s.handshakeAt,
18913
19146
  exit: s.exit,
18914
- placeholders,
18915
- ...head ? { head } : {}
19147
+ ...extra
18916
19148
  });
18917
19149
  return values;
18918
19150
  }
@@ -18931,6 +19163,7 @@ var SessionWriter = class {
18931
19163
  this.buffer.fill(0);
18932
19164
  this.buffer = joined4;
18933
19165
  if (this.mode === "sniff") this.mode = modeOf(latin12(joined4.subarray(0, 8))) ?? "sniff";
19166
+ if (this.mode === "pg") this.sawPg = true;
18934
19167
  if (this.mode === "pass") await this.release();
18935
19168
  else if (this.mode === "http1") await this.http1();
18936
19169
  else if (this.mode === "smtp") await this.lines();
@@ -18977,11 +19210,7 @@ var SessionWriter = class {
18977
19210
  this.buffer = this.buffer.slice(whole);
18978
19211
  const started = this.pgStarted;
18979
19212
  this.pgStarted = true;
18980
- const out = started ? await pgPassword(
18981
- message3,
18982
- this.pg,
18983
- (placeholders) => this.ask("pg", "password-cleartext", placeholders)
18984
- ).catch(() => ({ bytes: message3, done: true })) : { bytes: message3, done: false };
19213
+ const out = started ? await this.pgClient.message(message3).catch(() => ({ bytes: message3, done: true })) : { bytes: message3, done: false };
18985
19214
  if ("values" in out && out.values) this.remember(out.values);
18986
19215
  try {
18987
19216
  await writeAll4(this.conn, out.bytes);
@@ -19013,7 +19242,7 @@ var SessionWriter = class {
19013
19242
  this.buffer = new Uint8Array(0);
19014
19243
  const done5 = await substituteHead(
19015
19244
  latin12(all.subarray(0, end)),
19016
- (position, placeholders, head2) => this.ask("http1", position, placeholders, head2)
19245
+ (position, placeholders, head2) => this.ask("http1", position, { placeholders, head: head2 })
19017
19246
  ).catch(() => void 0);
19018
19247
  const head = done5 ? bytesOf(done5.head) : all.subarray(0, end);
19019
19248
  if (done5) this.remember(done5.values);
@@ -19111,9 +19340,19 @@ function sealedConn(conn, s) {
19111
19340
  const observed = {
19112
19341
  ...conn,
19113
19342
  read: async () => {
19114
- const bytes = await conn.read();
19115
- if (bytes) pg.feed(bytes);
19116
- return bytes;
19343
+ for (; ; ) {
19344
+ const bytes = await conn.read();
19345
+ if (!bytes) return bytes;
19346
+ const out = writer?.sawPg ? pg.filter(bytes) : bytes;
19347
+ if (pg.failed) {
19348
+ conn.close();
19349
+ throw new KernelError(
19350
+ "EPROTO",
19351
+ "ERR_SSL_PROTOCOL_ERROR: the pg server failed the SCRAM proof"
19352
+ );
19353
+ }
19354
+ if (out.length > 0) return out;
19355
+ }
19117
19356
  }
19118
19357
  };
19119
19358
  const reader = new ScrubReader(writer ? observed : conn, scope);
@@ -24193,7 +24432,7 @@ var SEALED_OPS = /* @__PURE__ */ new Set([
24193
24432
  "cancel",
24194
24433
  "materialize"
24195
24434
  ]);
24196
- var encoder8 = new TextEncoder();
24435
+ var encoder9 = new TextEncoder();
24197
24436
  var decoder3 = new TextDecoder("utf-8", { fatal: true });
24198
24437
  function parseSealed(bytes) {
24199
24438
  try {
@@ -24274,7 +24513,7 @@ var SealedChannel = class {
24274
24513
  await this.broker.tickets.record(req, reply, caller.pid);
24275
24514
  if (this.inflight !== flight) return;
24276
24515
  this.inflight = void 0;
24277
- if (reply) this.reply = encoder8.encode(serialized(reply));
24516
+ if (reply) this.reply = encoder9.encode(serialized(reply));
24278
24517
  });
24279
24518
  this.inflight = flight;
24280
24519
  return length2;
@@ -26010,9 +26249,9 @@ function importedMemory(bytes) {
26010
26249
  };
26011
26250
  const limits = () => {
26012
26251
  const flags2 = bytes[at++];
26013
- const initial = u32();
26252
+ const initial2 = u32();
26014
26253
  const maximum = flags2 & 1 ? u32() : void 0;
26015
- return { initial, maximum, shared: (flags2 & 2) !== 0 };
26254
+ return { initial: initial2, maximum, shared: (flags2 & 2) !== 0 };
26016
26255
  };
26017
26256
  while (at < bytes.length) {
26018
26257
  const id2 = bytes[at++];
@@ -26657,7 +26896,7 @@ var LAYOUT = [
26657
26896
  var IN_TREE = /* @__PURE__ */ new Set([SUDO_PATH, CRONTAB_PATH]);
26658
26897
  var LOAD_SAMPLE_MS = 5e3;
26659
26898
  var LOAD_WINDOWS_MS = [6e4, 3e5, 9e5];
26660
- var encoder9 = new TextEncoder();
26899
+ var encoder10 = new TextEncoder();
26661
26900
  var USERS_MODES = ["off", "report", "enforce"];
26662
26901
  function usersMode(mode = "off") {
26663
26902
  if (USERS_MODES.includes(mode)) return mode;
@@ -28932,7 +29171,7 @@ var Launcher = class {
28932
29171
  },
28933
29172
  account
28934
29173
  );
28935
- const report = (message3) => options.onData(encoder9.encode(`${message3}\r
29174
+ const report = (message3) => options.onData(encoder10.encode(`${message3}\r
28936
29175
  `));
28937
29176
  const handle = await this.launch(planned, {
28938
29177
  env,
@@ -28970,7 +29209,7 @@ var Launcher = class {
28970
29209
  };
28971
29210
  const stdout = collect(out, options.onStdout);
28972
29211
  const stderr = collect(err, options.onStderr);
28973
- const report = (message3) => stderr(encoder9.encode(`${message3}
29212
+ const report = (message3) => stderr(encoder10.encode(`${message3}
28974
29213
  `));
28975
29214
  if (!planned) {
28976
29215
  const directory = await this.directory(file, this.fs.resolvePath(cwd, file));