@ai-ecoverse/slicc-kernel 1.133.4 → 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.
@@ -2307,6 +2307,9 @@ var OpfsFs = class {
2307
2307
  }
2308
2308
  }
2309
2309
  await this.meta.remove([found.path]);
2310
+ if (found.handle?.kind === "directory") {
2311
+ await this.meta.update(found.path, (entry) => entry ?? vacatedAt(found.path));
2312
+ }
2310
2313
  this.touch(Date.now(), parentOf3(found.path));
2311
2314
  }
2312
2315
  links() {
@@ -7092,7 +7095,7 @@ function satisfies(version, range2) {
7092
7095
  }
7093
7096
 
7094
7097
  // src/version.ts
7095
- var KERNEL_VERSION = true ? "1.133.4" : "0.0.0-dev";
7098
+ var KERNEL_VERSION = true ? "1.134.0" : "0.0.0-dev";
7096
7099
  var OS_RELEASE = "6.0.0-slicc";
7097
7100
  function procVersion() {
7098
7101
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -10785,6 +10788,88 @@ var FifoTable = class {
10785
10788
  }
10786
10789
  };
10787
10790
 
10791
+ // src/kernel/held-cwd.ts
10792
+ var CWD_SLOTS = 1024;
10793
+ var UNTRACKED = CWD_SLOTS - 1;
10794
+ var under4 = (path, changed) => changed === "/" || path === changed || path.startsWith(`${changed}/`);
10795
+ var CwdTable = class {
10796
+ sab = new SharedArrayBuffer(CWD_SLOTS * 4);
10797
+ view = new Int32Array(this.sab);
10798
+ held = /* @__PURE__ */ new Map();
10799
+ free = [];
10800
+ next = 0;
10801
+ checks = 0;
10802
+ inodeOf;
10803
+ constructor(inodeOf2) {
10804
+ this.inodeOf = inodeOf2;
10805
+ }
10806
+ async hold(path, from) {
10807
+ const shared = from === void 0 ? void 0 : this.held.get(from);
10808
+ if (shared && shared.path === path) return this.share(from);
10809
+ const ino = await this.inodeOf(path).catch(() => void 0);
10810
+ const slot2 = this.free.pop() ?? (this.next < UNTRACKED ? this.next++ : UNTRACKED);
10811
+ if (slot2 === UNTRACKED) return slot2;
10812
+ this.held.set(slot2, {
10813
+ path,
10814
+ ino,
10815
+ refs: 1,
10816
+ dead: false,
10817
+ verified: Atomics.load(this.view, slot2)
10818
+ });
10819
+ return slot2;
10820
+ }
10821
+ share(slot2) {
10822
+ const held = slot2 === void 0 ? void 0 : this.held.get(slot2);
10823
+ if (!held) return UNTRACKED;
10824
+ held.refs++;
10825
+ return slot2;
10826
+ }
10827
+ release(slot2) {
10828
+ const held = slot2 === void 0 ? void 0 : this.held.get(slot2);
10829
+ if (!held || --held.refs > 0) return;
10830
+ this.held.delete(slot2);
10831
+ Atomics.add(this.view, slot2, 1);
10832
+ this.free.push(slot2);
10833
+ }
10834
+ stateOf(slot2) {
10835
+ const held = this.held.get(slot2);
10836
+ return { seen: held?.verified ?? Atomics.load(this.view, slot2), dead: held?.dead === true };
10837
+ }
10838
+ touched(paths, trees = []) {
10839
+ if (this.held.size === 0) return;
10840
+ for (const [slot2, held] of this.held) {
10841
+ if (held.dead) continue;
10842
+ if (paths.some((p) => under4(held.path, p)) || trees.some((t) => under4(held.path, t))) {
10843
+ Atomics.add(this.view, slot2, 1);
10844
+ }
10845
+ }
10846
+ }
10847
+ async check(slot2) {
10848
+ this.checks++;
10849
+ const gen = Atomics.load(this.view, slot2);
10850
+ const held = this.held.get(slot2);
10851
+ if (!held) return { gen, alive: true };
10852
+ if (!held.dead) {
10853
+ const ino = await this.inodeOf(held.path).catch(() => null);
10854
+ held.dead = ino === null || held.ino !== void 0 && ino !== held.ino;
10855
+ held.verified = gen;
10856
+ }
10857
+ return { gen, alive: !held.dead };
10858
+ }
10859
+ };
10860
+ function heldInit(o) {
10861
+ if (!o.cwds || o.cwdSlot === void 0) return {};
10862
+ const state = o.cwdState ?? { seen: 0, dead: false };
10863
+ return { held: { sab: o.cwds, slot: o.cwdSlot, ...state } };
10864
+ }
10865
+ function heldHooks(o) {
10866
+ if (!o.cwdCheck || !o.cwdChdir) return {};
10867
+ return { cwdCheck: o.cwdCheck, cwdChdir: o.cwdChdir };
10868
+ }
10869
+ function inheritedCwd(chdir, parent) {
10870
+ return chdir ? void 0 : parent;
10871
+ }
10872
+
10788
10873
  // src/fs/copy.ts
10789
10874
  async function present2(fs, path) {
10790
10875
  return fs.lstat(path).then(
@@ -14073,8 +14158,8 @@ var EventFd = class _EventFd {
14073
14158
  count;
14074
14159
  semaphore;
14075
14160
  changes = new Notifier();
14076
- constructor(initial, semaphore) {
14077
- this.count = initial;
14161
+ constructor(initial2, semaphore) {
14162
+ this.count = initial2;
14078
14163
  this.semaphore = semaphore;
14079
14164
  }
14080
14165
  async read(max, signal) {
@@ -17823,7 +17908,7 @@ var UNSAFE = /[\r\n\0]/;
17823
17908
  var POSITIONS = {
17824
17909
  http1: (position) => HEADER.test(position),
17825
17910
  smtp: (position) => position === "auth-plain" || position === "auth-login",
17826
- pg: (position) => position === "password-cleartext"
17911
+ pg: (position) => position === "password-cleartext" || position === "scram-sha-256"
17827
17912
  };
17828
17913
  function boundHost(servername) {
17829
17914
  const lower = servername.toLowerCase();
@@ -17838,6 +17923,15 @@ function placeholdersOk(list) {
17838
17923
  if (!Array.isArray(list) || list.length === 0 || list.length > SESSION_PLACEHOLDERS) return false;
17839
17924
  return new Set(list).size === list.length && list.every((p) => typeof p === "string" && SESSION_PLACEHOLDER.test(p));
17840
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
+ }
17841
17935
  function hostOk(host) {
17842
17936
  return typeof host === "string" && HOST.test(host) && boundHost(host) === host;
17843
17937
  }
@@ -17849,7 +17943,7 @@ function sessionAskable(f, now) {
17849
17943
  if (!Number.isInteger(f.port) || f.port < 1 || f.port > 65535) return false;
17850
17944
  const age = now - f.handshakeAt;
17851
17945
  if (!Number.isFinite(age) || age < 0 || age > SESSION_WINDOW_MS) return false;
17852
- 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);
17853
17947
  }
17854
17948
  function sessionRequest(f) {
17855
17949
  return {
@@ -17865,8 +17959,16 @@ function sessionRequest(f) {
17865
17959
  verified: true,
17866
17960
  handshakeAt: f.handshakeAt,
17867
17961
  exit: f.exit,
17868
- placeholders: [...f.placeholders],
17869
- ...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
+ } : {}
17870
17972
  };
17871
17973
  }
17872
17974
  function sessionValues(reply, asked) {
@@ -17874,7 +17976,9 @@ function sessionValues(reply, asked) {
17874
17976
  const { error, values } = reply;
17875
17977
  if (error !== void 0 || typeof values !== "object" || values === null) return void 0;
17876
17978
  const out = {};
17877
- 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) {
17878
17982
  const value2 = values[ph];
17879
17983
  if (typeof value2 === "string" && value2.length > 0 && !UNSAFE.test(value2)) out[ph] = value2;
17880
17984
  }
@@ -18566,6 +18670,104 @@ async function substituteHead(head, ask) {
18566
18670
  `, values };
18567
18671
  }
18568
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
+
18569
18771
  // src/kernel/net/sealed-pg.ts
18570
18772
  var PG_MESSAGE_MAX = 16 * 1024;
18571
18773
  var PROTOCOL_3 = 196608;
@@ -18580,44 +18782,101 @@ function sniffPg(start2) {
18580
18782
  const length2 = int32(bytes, 0);
18581
18783
  return length2 >= 8 && length2 <= PG_MESSAGE_MAX && int32(bytes, 4) === PROTOCOL_3 ? "yes" : "no";
18582
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
+ }
18583
18794
  var PgServer = class {
18584
18795
  buffer = new Uint8Array(0);
18585
18796
  skip = 0;
18586
- lost = false;
18587
18797
  cleartext = false;
18588
- feed(bytes) {
18589
- 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;
18590
18837
  const data = new Uint8Array(this.buffer.length + bytes.length);
18591
18838
  data.set(this.buffer);
18592
18839
  data.set(bytes, this.buffer.length);
18840
+ const out = [];
18593
18841
  let at = 0;
18594
18842
  for (; ; ) {
18595
18843
  const left = data.length - at;
18596
18844
  if (this.skip > 0) {
18597
18845
  const n = Math.min(this.skip, left);
18846
+ out.push(data.subarray(at, at + n));
18598
18847
  this.skip -= n;
18599
18848
  at += n;
18600
18849
  if (this.skip > 0) break;
18601
18850
  continue;
18602
18851
  }
18603
18852
  if (left < 5) break;
18604
- const type = data[at];
18605
18853
  const whole = 1 + int32(data, at + 1);
18606
- if (whole < 5 || type === 82 && whole > PG_MESSAGE_MAX) {
18607
- this.lost = true;
18608
- this.cleartext = false;
18609
- this.buffer = new Uint8Array(0);
18610
- 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;
18611
18859
  }
18612
- if (type !== 82) {
18860
+ if (data[at] !== 82) {
18861
+ if (this.expect) {
18862
+ this.failed = true;
18863
+ break;
18864
+ }
18613
18865
  this.skip = whole;
18614
18866
  continue;
18615
18867
  }
18616
18868
  if (left < whole) break;
18617
- this.cleartext = whole === 9 && int32(data, at + 5) === CLEARTEXT;
18869
+ out.push(this.auth(data.slice(at, at + whole)));
18618
18870
  at += whole;
18619
18871
  }
18620
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;
18621
18880
  }
18622
18881
  };
18623
18882
  function frame3(type, body) {
@@ -18634,21 +18893,76 @@ function pgLength(bytes, started) {
18634
18893
  const length2 = int32(bytes, started ? 1 : 0);
18635
18894
  return started ? 1 + length2 : length2;
18636
18895
  }
18637
- async function pgPassword(message3, server, ask) {
18638
- if (message3[0] !== 112 || !server.cleartext) return { bytes: message3, done: true };
18639
- server.cleartext = false;
18640
- let body = "";
18641
- 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));
18642
18899
  if (!body.endsWith("\0") || body.indexOf("\0") !== body.length - 1)
18643
18900
  return { bytes: message3, done: true };
18644
18901
  const password = body.slice(0, -1);
18645
18902
  const placeholders = placeholdersIn(password);
18646
18903
  if (placeholders.length === 0 || placeholders.length > SESSION_PLACEHOLDERS)
18647
18904
  return { bytes: message3, done: true };
18648
- const values = usable(await ask(placeholders));
18905
+ const values = usable(await asks.cleartext(placeholders));
18649
18906
  if (Object.keys(values).length === 0) return { bytes: message3, done: true };
18650
18907
  return { bytes: frame3(112, `${replaced(password, values)}\0`), values, done: true };
18651
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
+ };
18652
18966
 
18653
18967
  // src/kernel/net/sealed-smtp.ts
18654
18968
  var SMTP_LINE_MAX = 4096;
@@ -18793,17 +19107,21 @@ var SessionWriter = class {
18793
19107
  session = sessionId();
18794
19108
  smtp;
18795
19109
  pgStarted = false;
19110
+ sawPg = false;
18796
19111
  conn;
18797
19112
  s;
18798
- pg;
19113
+ pgClient;
18799
19114
  scope;
18800
19115
  constructor(conn, s, pg, scope) {
18801
19116
  this.conn = conn;
18802
19117
  this.s = s;
18803
- this.pg = pg;
18804
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
+ });
18805
19123
  this.smtp = new SmtpClient(
18806
- (position, placeholders) => this.ask("smtp", position, placeholders)
19124
+ (position, placeholders) => this.ask("smtp", position, { placeholders })
18807
19125
  );
18808
19126
  }
18809
19127
  write(bytes) {
@@ -18814,7 +19132,7 @@ var SessionWriter = class {
18814
19132
  );
18815
19133
  return run2;
18816
19134
  }
18817
- async ask(protocol, position, placeholders, head) {
19135
+ async ask(protocol, position, extra) {
18818
19136
  const s = this.s;
18819
19137
  const values = await s.broker.sessionMaterialize({
18820
19138
  stamp: await s.stamp(),
@@ -18826,8 +19144,7 @@ var SessionWriter = class {
18826
19144
  verified: s.verified,
18827
19145
  handshakeAt: s.handshakeAt,
18828
19146
  exit: s.exit,
18829
- placeholders,
18830
- ...head ? { head } : {}
19147
+ ...extra
18831
19148
  });
18832
19149
  return values;
18833
19150
  }
@@ -18846,6 +19163,7 @@ var SessionWriter = class {
18846
19163
  this.buffer.fill(0);
18847
19164
  this.buffer = joined4;
18848
19165
  if (this.mode === "sniff") this.mode = modeOf(latin12(joined4.subarray(0, 8))) ?? "sniff";
19166
+ if (this.mode === "pg") this.sawPg = true;
18849
19167
  if (this.mode === "pass") await this.release();
18850
19168
  else if (this.mode === "http1") await this.http1();
18851
19169
  else if (this.mode === "smtp") await this.lines();
@@ -18892,11 +19210,7 @@ var SessionWriter = class {
18892
19210
  this.buffer = this.buffer.slice(whole);
18893
19211
  const started = this.pgStarted;
18894
19212
  this.pgStarted = true;
18895
- const out = started ? await pgPassword(
18896
- message3,
18897
- this.pg,
18898
- (placeholders) => this.ask("pg", "password-cleartext", placeholders)
18899
- ).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 };
18900
19214
  if ("values" in out && out.values) this.remember(out.values);
18901
19215
  try {
18902
19216
  await writeAll4(this.conn, out.bytes);
@@ -18928,7 +19242,7 @@ var SessionWriter = class {
18928
19242
  this.buffer = new Uint8Array(0);
18929
19243
  const done5 = await substituteHead(
18930
19244
  latin12(all.subarray(0, end)),
18931
- (position, placeholders, head2) => this.ask("http1", position, placeholders, head2)
19245
+ (position, placeholders, head2) => this.ask("http1", position, { placeholders, head: head2 })
18932
19246
  ).catch(() => void 0);
18933
19247
  const head = done5 ? bytesOf(done5.head) : all.subarray(0, end);
18934
19248
  if (done5) this.remember(done5.values);
@@ -19026,9 +19340,19 @@ function sealedConn(conn, s) {
19026
19340
  const observed = {
19027
19341
  ...conn,
19028
19342
  read: async () => {
19029
- const bytes = await conn.read();
19030
- if (bytes) pg.feed(bytes);
19031
- 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
+ }
19032
19356
  }
19033
19357
  };
19034
19358
  const reader = new ScrubReader(writer ? observed : conn, scope);
@@ -21142,6 +21466,8 @@ var SYSCALL_OPS = /* @__PURE__ */ new Set([
21142
21466
  "fd-list",
21143
21467
  "proc-alarm",
21144
21468
  "proc-umask",
21469
+ "cwd-check",
21470
+ "cwd-chdir",
21145
21471
  "proc-cred",
21146
21472
  "proc-setcred",
21147
21473
  "dl-log",
@@ -22467,6 +22793,14 @@ var WasmProcess = class {
22467
22793
  return { ok: true, kind: "void" };
22468
22794
  case "proc-umask":
22469
22795
  return { ok: true, kind: "json", json: this.setUmask(req.mask) };
22796
+ case "cwd-check":
22797
+ return {
22798
+ ok: true,
22799
+ kind: "json",
22800
+ json: await this.options.cwdCheck?.() ?? { gen: 0, alive: true }
22801
+ };
22802
+ case "cwd-chdir":
22803
+ return { ok: true, kind: "json", json: await this.options.cwdChdir?.(req.path) ?? {} };
22470
22804
  case "proc-cred":
22471
22805
  return { ok: true, kind: "json", json: copyCred(this.cred) };
22472
22806
  case "proc-setcred":
@@ -23016,6 +23350,7 @@ function processInit(opts, sab, umask, cred, lane) {
23016
23350
  umask,
23017
23351
  cred,
23018
23352
  ...opts.changes ? { changes: opts.changes } : {},
23353
+ ...heldInit(opts),
23019
23354
  ...opts.owners ? { owners: true } : {},
23020
23355
  ...opts.links !== void 0 ? { links: true } : {},
23021
23356
  ...opts.ppid !== void 0 ? { ppid: opts.ppid } : {}
@@ -23089,6 +23424,7 @@ function processOptions(opts, header3, hooks, created4) {
23089
23424
  ...opts.identity ? { identity: opts.identity } : {},
23090
23425
  ...opts.onSyscall ? { onSyscall: opts.onSyscall } : {},
23091
23426
  ...opts.settling ? { settling: opts.settling } : {},
23427
+ ...heldHooks(opts),
23092
23428
  spawner: opts.spawner,
23093
23429
  forker: opts.forker,
23094
23430
  ...opts.fork?.dl ? { dl: opts.fork.dl } : {},
@@ -23139,6 +23475,7 @@ function threadInit(opts, program, sab, cred, thread, main) {
23139
23475
  owners: opts.owners === true,
23140
23476
  ...opts.links !== void 0 ? { links: true } : {},
23141
23477
  ...opts.changes ? { changes: opts.changes } : {},
23478
+ ...heldInit(opts),
23142
23479
  ...opts.ppid !== void 0 ? { ppid: opts.ppid } : {},
23143
23480
  thread,
23144
23481
  signals: main
@@ -24095,7 +24432,7 @@ var SEALED_OPS = /* @__PURE__ */ new Set([
24095
24432
  "cancel",
24096
24433
  "materialize"
24097
24434
  ]);
24098
- var encoder8 = new TextEncoder();
24435
+ var encoder9 = new TextEncoder();
24099
24436
  var decoder3 = new TextDecoder("utf-8", { fatal: true });
24100
24437
  function parseSealed(bytes) {
24101
24438
  try {
@@ -24176,7 +24513,7 @@ var SealedChannel = class {
24176
24513
  await this.broker.tickets.record(req, reply, caller.pid);
24177
24514
  if (this.inflight !== flight) return;
24178
24515
  this.inflight = void 0;
24179
- if (reply) this.reply = encoder8.encode(serialized(reply));
24516
+ if (reply) this.reply = encoder9.encode(serialized(reply));
24180
24517
  });
24181
24518
  this.inflight = flight;
24182
24519
  return length2;
@@ -25912,9 +26249,9 @@ function importedMemory(bytes) {
25912
26249
  };
25913
26250
  const limits = () => {
25914
26251
  const flags2 = bytes[at++];
25915
- const initial = u32();
26252
+ const initial2 = u32();
25916
26253
  const maximum = flags2 & 1 ? u32() : void 0;
25917
- return { initial, maximum, shared: (flags2 & 2) !== 0 };
26254
+ return { initial: initial2, maximum, shared: (flags2 & 2) !== 0 };
25918
26255
  };
25919
26256
  while (at < bytes.length) {
25920
26257
  const id2 = bytes[at++];
@@ -26559,7 +26896,7 @@ var LAYOUT = [
26559
26896
  var IN_TREE = /* @__PURE__ */ new Set([SUDO_PATH, CRONTAB_PATH]);
26560
26897
  var LOAD_SAMPLE_MS = 5e3;
26561
26898
  var LOAD_WINDOWS_MS = [6e4, 3e5, 9e5];
26562
- var encoder9 = new TextEncoder();
26899
+ var encoder10 = new TextEncoder();
26563
26900
  var USERS_MODES = ["off", "report", "enforce"];
26564
26901
  function usersMode(mode = "off") {
26565
26902
  if (USERS_MODES.includes(mode)) return mode;
@@ -26770,6 +27107,11 @@ var Launcher = class {
26770
27107
  hostname;
26771
27108
  watchers = new FsWatchers();
26772
27109
  changes = new FileChanges();
27110
+ cwds = new CwdTable(async (path) => {
27111
+ const { dev, ino } = await this.base.stat(path);
27112
+ return `${dev ?? 0}:${ino}`;
27113
+ });
27114
+ cwdSlots = /* @__PURE__ */ new Map();
26773
27115
  pnpmHome;
26774
27116
  pnpmChain;
26775
27117
  pnpmMade;
@@ -26826,7 +27168,10 @@ var Launcher = class {
26826
27168
  this.sealed.tickets.normalise = (path) => physicalPathAsync(this.base, path);
26827
27169
  this.sealed.userOf = async (uid) => (await this.users.lookup(uid))?.name;
26828
27170
  if (this.owners) options.fs.trackOwners?.();
26829
- this.watchers.tap((paths) => this.changes.publish(...paths));
27171
+ this.watchers.tap((paths) => {
27172
+ this.changes.publish(...paths);
27173
+ this.cwds.touched(paths);
27174
+ });
26830
27175
  this.watchers.onReshape(() => {
26831
27176
  for (const nodes of this.openFiles) nodes.reshaped();
26832
27177
  });
@@ -26896,6 +27241,7 @@ var Launcher = class {
26896
27241
  options.fs.onPeer?.(() => this.flushOpen());
26897
27242
  options.fs.remoteChanges?.((change) => {
26898
27243
  this.changes.flush();
27244
+ this.cwds.touched(change.paths, change.trees);
26899
27245
  this.rewritten(change.paths, change.trees);
26900
27246
  });
26901
27247
  const holders = [this.held, this.openFiles];
@@ -27678,11 +28024,12 @@ var Launcher = class {
27678
28024
  }
27679
28025
  const done5 = this.heldUrl(program);
27680
28026
  try {
28027
+ const cwdSlot = await this.cwds.hold(cwd, req.cwdFrom);
27681
28028
  const handle = await this.admitted(
27682
28029
  program.abi !== "js",
27683
28030
  req.fds,
27684
- (fds, quietOom) => this.start({ ...req, fds, quietOom, cwd, program, argv0: target.argv0, args, env })
27685
- );
28031
+ (fds, quietOom) => this.start({ ...req, fds, quietOom, cwd, program, argv0: target.argv0, args, env, cwdSlot })
28032
+ ).finally(() => this.cwds.release(cwdSlot));
27686
28033
  void handle.exited.finally(done5);
27687
28034
  return handle;
27688
28035
  } catch (err) {
@@ -27769,6 +28116,8 @@ var Launcher = class {
27769
28116
  throw new SpawnError("ESRCH");
27770
28117
  }
27771
28118
  const pid = req.pid ?? this.nextPid++;
28119
+ const cwdSlot = this.cwds.share(req.cwdSlot);
28120
+ this.cwdSlots.set(pid, cwdSlot);
27772
28121
  const scrubs = this.treeScrubs(req);
27773
28122
  const stack = this.stackFor(req.tag);
27774
28123
  const terminal = req.fds.stdioTerminal();
@@ -27803,6 +28152,7 @@ var Launcher = class {
27803
28152
  ...this.dac ? { dac: this.dac } : {},
27804
28153
  program: req.program,
27805
28154
  changes: this.changes.sab,
28155
+ ...this.heldFor(pid, cwdSlot),
27806
28156
  argv0: req.argv0,
27807
28157
  args: req.args,
27808
28158
  env: req.env,
@@ -27877,6 +28227,8 @@ var Launcher = class {
27877
28227
  (state) => state === "stopped" ? this.stopped.add(pid) : this.stopped.delete(pid)
27878
28228
  );
27879
28229
  void handle.exited.then(() => {
28230
+ this.cwds.release(this.cwdSlots.get(pid));
28231
+ this.cwdSlots.delete(pid);
27880
28232
  this.freshModules.forget(pid);
27881
28233
  const spent = handle.times?.();
27882
28234
  if (spent) this.spent.set(pid, spent);
@@ -28108,6 +28460,7 @@ var Launcher = class {
28108
28460
  const handle = await this.launch(planned, {
28109
28461
  ...deciding ? { decided: deciding.promise } : {},
28110
28462
  cwd: req.cwd,
28463
+ cwdFrom: inheritedCwd(req.chdir, this.cwdSlots.get(ppid)),
28111
28464
  ...redeemed,
28112
28465
  fds,
28113
28466
  report,
@@ -28169,6 +28522,24 @@ var Launcher = class {
28169
28522
  for (const resolve2 of waiting) resolve2(true);
28170
28523
  }, 0);
28171
28524
  }
28525
+ heldFor(pid, slot2) {
28526
+ return {
28527
+ cwds: this.cwds.sab,
28528
+ cwdSlot: slot2,
28529
+ cwdState: this.cwds.stateOf(slot2),
28530
+ cwdCheck: async () => {
28531
+ const current = this.cwdSlots.get(pid);
28532
+ return { ...await this.cwds.check(current), slot: current };
28533
+ },
28534
+ cwdChdir: (path) => this.chdirHeld(pid, path)
28535
+ };
28536
+ }
28537
+ async chdirHeld(pid, path) {
28538
+ this.cwds.release(this.cwdSlots.get(pid));
28539
+ const slot2 = await this.cwds.hold(path);
28540
+ this.cwdSlots.set(pid, slot2);
28541
+ return { slot: slot2, ...this.cwds.stateOf(slot2) };
28542
+ }
28172
28543
  forker(ppid, parent) {
28173
28544
  const { exec: _exec, pgid: _pgid, group: _group, pid: _pid, scrub: _scrub, ...image } = parent;
28174
28545
  return async (state, given) => {
@@ -28176,6 +28547,7 @@ var Launcher = class {
28176
28547
  ...image,
28177
28548
  quietOom,
28178
28549
  cwd: state.cwd ?? parent.cwd,
28550
+ cwdSlot: this.cwdSlots.get(ppid),
28179
28551
  fds,
28180
28552
  ppid,
28181
28553
  fork: state,
@@ -28799,7 +29171,7 @@ var Launcher = class {
28799
29171
  },
28800
29172
  account
28801
29173
  );
28802
- const report = (message3) => options.onData(encoder9.encode(`${message3}\r
29174
+ const report = (message3) => options.onData(encoder10.encode(`${message3}\r
28803
29175
  `));
28804
29176
  const handle = await this.launch(planned, {
28805
29177
  env,
@@ -28837,7 +29209,7 @@ var Launcher = class {
28837
29209
  };
28838
29210
  const stdout = collect(out, options.onStdout);
28839
29211
  const stderr = collect(err, options.onStderr);
28840
- const report = (message3) => stderr(encoder9.encode(`${message3}
29212
+ const report = (message3) => stderr(encoder10.encode(`${message3}
28841
29213
  `));
28842
29214
  if (!planned) {
28843
29215
  const directory = await this.directory(file, this.fs.resolvePath(cwd, file));