@ai-ecoverse/slicc-kernel 1.93.0 → 1.93.1

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
@@ -161,6 +161,8 @@ Page-only: neither is on an attached client (`attachKernel`, `connect()`), so no
161
161
  - A change is a write, a truncate, a rename, a removal, or a change of mode, owner or times of the file or of any directory above it. A change to a parent directory's own metadata counts too, and creating or removing a sibling changes it when the change comes from another kernel.
162
162
  - It sees changes made through any slicc kernel on the origin, in this tab or another one: the kernels tell each other which files are watched and report writes to those. `watch` resolves once every other live kernel on the origin has the watch (a kernel that doesn't answer within 500 ms is not waited for), so a write made after it resolves is reported. A kernel that ends with watches still on is forgotten (by its Web Lock) at the next reported write or unanswered announcement. This needs the shared metadata (the default): with `metadata: false` a kernel sees only its own changes. It doesn't see writes made with the OPFS API outside a kernel, such as a page script or an installer writing the root directly. After such a write the page should attest again itself (and may also attest on tab focus, as a safety net).
163
163
  - The cost when no kernel on the origin watches anything is one empty-set check per write.
164
+ - **A kernel that starts late:** a kernel learns the other kernels' watched files only when they answer its greeting, one message round trip (usually milliseconds) after it starts. A write it makes before then isn't reported. A consumer that must not miss a change checks again (attests) after its first report.
165
+ - **Trust:** the kernels coordinate over a `BroadcastChannel`, which every same-origin context can post to. A script on the origin can fake an acknowledgement, so `watch` resolves before another kernel really has it, clear a kernel's watched files, or report changes that didn't happen. That is the same boundary as a direct OPFS write, which `watch` doesn't see either. Treat `watch` as an invalidation signal only, never as proof: attest again before each use that matters, as the vault and bios do.
164
166
 
165
167
  ### `attachKernel(port, options?) → Promise<KernelClient>`
166
168
 
@@ -618,7 +620,7 @@ Lowering a soft resource limit (`ulimit -S -n 64`) still fails with `EPERM` in E
618
620
  Every process has credentials in the kernel, as on Linux: real, effective and saved user and group ids, and supplementary groups. A process gets them from the user it was started as (`run`, `openTerminal`, a client's `spawn`, or the client's own user; root by default) and keeps its parent's across fork, spawn and exec. Setuid and setgid bits are never honoured on exec. Files may have owners (see [File owners](#file-owners)), checked against the credentials with `users: 'enforce'` (see [Permissions](#permissions)); the credentials also decide who may signal whom, and what `/proc` and `ps` show.
619
621
 
620
622
  - **The database:** `/etc/passwd` and `/etc/group` are real files. On first start the kernel writes them when they're missing, with `root` (uid 0, home `/root`, created `0700`) and `nobody` (65534), and the groups `root`, `sudo` (27), `users` (100) and `nogroup` (65534); files already there are kept as they are. The kernel reads them for every lookup, so an edit counts at once. [`kernel.users`](#kernelusers) adds and removes users.
621
- - **Environment:** a process started as a user gets `HOME`, `USER`, `LOGNAME`, `PNPM_HOME`, `NPM_CONFIG_PREFIX` and `PATH`. A user's `PNPM_HOME` is `~/.local/share/pnpm` and its npm prefix `~/.local`; root's are `/usr/local/share/pnpm` (or the embedder's `env.PNPM_HOME`) and `/usr/local`. `PATH` is `$PNPM_HOME/bin:/usr/local/bin:/usr/bin:/bin`.
623
+ - **Environment:** a process started as a user gets `HOME`, `USER`, `LOGNAME`, `PNPM_HOME`, `NPM_CONFIG_PREFIX` and `PATH`. A user's `PNPM_HOME` is `~/.local/share/pnpm` and its npm prefix `~/.local`; root's are `/usr/local/share/pnpm` (or the embedder's `env.PNPM_HOME`) and `/usr/local`. `PATH` is `$PNPM_HOME/bin:/usr/local/bin:/usr/bin:/bin`. pnpm makes only `$PNPM_HOME/bin`, so the kernel makes root's `PNPM_HOME` when it is missing, just before a process starts: once at boot, and again after any mount or unmount, a removable medium inserted, a `hostfs` folder coming back, or a change at that directory or above it (removing it, say), and after a failed try (no medium yet). With owners on, the directories it makes there get root's owner and `0755`, as the boot layout does. A process already running when a medium arrives gets it at its next child launch. Writes inside it cost nothing extra.
622
624
  - **Commands per user:** root's global packages (`pnpm add -g` as root) are commands every user finds in `/usr/bin`. A user's own global packages are commands for that user only: they show up in the user's `~/.local/share/pnpm/bin`, first on its `PATH`, and a program the user starts finds them by name before the system's; another user, root included, doesn't. A user's packages can map file suffixes (`binfmt`) for that user too. The kernel picks up an install, a removal and a new user as they happen.
623
625
  - **Changing credentials:** POSIX `setresuid`/`setresgid` rules. Root (effective uid 0) may set any id and the group list; anyone else may only swap among their own real, effective and saved ids, and gets `EPERM` otherwise.
624
626
  - **Signals:** a process may signal another if its effective uid is 0, or if its real or effective uid is the target's real or saved uid; otherwise `kill` fails with `EPERM`. A group kill signals the members it may, and fails with `EPERM` only when it may signal none.
@@ -11569,7 +11569,7 @@ function mountTable(mounts = []) {
11569
11569
  }
11570
11570
 
11571
11571
  // src/version.ts
11572
- var KERNEL_VERSION = true ? "1.93.0" : "0.0.0-dev";
11572
+ var KERNEL_VERSION = true ? "1.93.1" : "0.0.0-dev";
11573
11573
  var OS_RELEASE = "6.0.0-slicc";
11574
11574
  function procVersion() {
11575
11575
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -19249,6 +19249,9 @@ var Launcher = class {
19249
19249
  hostname;
19250
19250
  watchers = new FsWatchers();
19251
19251
  pnpmHome;
19252
+ pnpmChain;
19253
+ pnpmMade;
19254
+ pnpmEpoch = 0;
19252
19255
  mounts;
19253
19256
  createDriverWorker;
19254
19257
  media;
@@ -19299,7 +19302,10 @@ var Launcher = class {
19299
19302
  this.mounts = new MountTable({
19300
19303
  open: (type, spec) => this.driver(type, spec),
19301
19304
  busy: (target) => [...this.openFiles].some((nodes) => nodes.holds(target)) || heldUnder(this.held, target),
19302
- changed: this.watchers.changed.bind(this.watchers),
19305
+ changed: (...paths) => {
19306
+ if (paths.some((path) => this.pnpmChain.has(path))) this.pnpmStale();
19307
+ this.watchers.changed(...paths);
19308
+ },
19303
19309
  owners: this.owners
19304
19310
  });
19305
19311
  this.mounted = this.mounts.wrap(options.fs);
@@ -19312,6 +19318,7 @@ var Launcher = class {
19312
19318
  this.fstabRetries = options.fstabRetries ?? FSTAB_RETRIES;
19313
19319
  this.processMounts = options.processMounts ?? true;
19314
19320
  this.pnpmHome = options.env?.PNPM_HOME ?? SYSTEM_PNPM_HOME;
19321
+ this.pnpmChain = new Set(chain(normalizePath(this.pnpmHome)));
19315
19322
  this.modulesDir = options.modules ?? "/node_modules";
19316
19323
  this.appended = appendedRoots(options.commands);
19317
19324
  this.cdp = new CdpHosts(options.cdp);
@@ -19918,6 +19925,7 @@ var Launcher = class {
19918
19925
  delete env[TICKET_ENV];
19919
19926
  env.HOSTNAME = this.hostname;
19920
19927
  let program;
19928
+ await this.pnpmReady();
19921
19929
  try {
19922
19930
  const caller = { pid: req.ppid ?? 0, uid: req.cred.euid, tag: req.tag };
19923
19931
  if (this.integrity) await this.checkedSources(planned, caller);
@@ -20562,8 +20570,7 @@ var Launcher = class {
20562
20570
  this.fs
20563
20571
  );
20564
20572
  void this.unlinked.sweep(entry.target);
20565
- if (this.pnpmHome.startsWith(`${entry.target.replace(/\/$/, "")}/`))
20566
- await this.provisionPnpmHome();
20573
+ this.pnpmStale();
20567
20574
  return entry;
20568
20575
  }
20569
20576
  async ownTmp() {
@@ -20611,8 +20618,18 @@ var Launcher = class {
20611
20618
  if (path === "/") return path;
20612
20619
  return joinName(await realDir(this.base, parentOf4(path)), baseName(path));
20613
20620
  }
20614
- async provisionPnpmHome() {
20615
- await this.base.mkdir(this.pnpmHome, { recursive: true }).catch(() => void 0);
20621
+ pnpmReady() {
20622
+ if (this.pnpmMade !== void 0) return this.pnpmMade;
20623
+ const epoch = this.pnpmEpoch;
20624
+ const made2 = this.base.mkdir(this.pnpmHome, { recursive: true }).then(() => this.owners ? this.stampLayout() : void 0).catch(() => {
20625
+ if (this.pnpmEpoch === epoch) this.pnpmMade = void 0;
20626
+ });
20627
+ this.pnpmMade = made2;
20628
+ return made2;
20629
+ }
20630
+ pnpmStale() {
20631
+ this.pnpmEpoch++;
20632
+ this.pnpmMade = void 0;
20616
20633
  }
20617
20634
  mountedBy(spec, cred) {
20618
20635
  if (!this.owners || cred.euid === 0 && cred.egid === 0) return spec;
@@ -20646,6 +20663,7 @@ var Launcher = class {
20646
20663
  umount(target, detach = false) {
20647
20664
  const at = normalizePath(target);
20648
20665
  this.mounts.umount(at, detach);
20666
+ this.pnpmStale();
20649
20667
  if (!detach) return;
20650
20668
  for (const nodes of this.openFiles) nodes.revoke(at);
20651
20669
  for (const holds of this.held) holds.revoke(at);
@@ -20711,7 +20729,7 @@ var Launcher = class {
20711
20729
  await this.resolvePrefixes();
20712
20730
  for (const dir of SHARED_DIRS) await this.base.mkdir(dir, { recursive: true });
20713
20731
  if (this.owners) await this.ownTmp();
20714
- await this.provisionPnpmHome();
20732
+ await this.pnpmReady();
20715
20733
  await this.users.ensure();
20716
20734
  if (this.owners) await this.stampLayout();
20717
20735
  if (this.owners) await this.sudoer.provision();