@ai-ecoverse/slicc-kernel 1.125.0 → 1.125.2

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
@@ -413,7 +413,7 @@ The module's default export (or its `main` export) is called with a context and
413
413
  | `tls: { path: 'transport' }` | A1 | A1 |
414
414
  | `connect({ socket: conn, host, tls })` (STARTTLS) | **A2** | `EOPNOTSUPP` |
415
415
 
416
- - **A2, the handshake in the kernel** ([#922](https://github.com/ai-ecoverse/slicc-kernel/issues/922)): the kernel dials the destination through the uplink as raw TCP and runs a TLS client there, with [`@ai-ecoverse/wasm-tls-engine`](https://www.npmjs.com/package/@ai-ecoverse/wasm-tls-engine) (4.2.0-3 or later, loaded on the first A2 connect). The connection is then an ordinary uplink socket that carries the decrypted stream, so any protocol works: SMTP, IMAP, Postgres, MQTT, HTTP/2.
416
+ - **A2, the handshake in the kernel** ([#922](https://github.com/ai-ecoverse/slicc-kernel/issues/922)): the kernel dials the destination through the uplink as raw TCP and runs a TLS client there, with [`@ai-ecoverse/wasm-tls-engine`](https://www.npmjs.com/package/@ai-ecoverse/wasm-tls-engine) (4.2.0-4 or later, loaded on the first A2 connect). The connection is then an ordinary uplink socket that carries the decrypted stream, so any protocol works: SMTP, IMAP, Postgres, MQTT, HTTP/2.
417
417
  - **Verification** is required. The chain must reach a trusted root, the leaf must name `servername` (default `host`), and every certificate must be within its validity by the page's clock, with serverAuth usage. The trusted roots are Mozilla's set the engine package ships (`dist/roots.der`, its date in the package's `slicc.tls.roots`), read on the first A2 connect without a `ca`. A `ca` (PEM text, DER bytes, or a list of them) **replaces** them, as in Node.
418
418
  - **A refusal** rejects the connect with Node's code: `ERR_TLS_CERT_ALTNAME_INVALID`, `UNABLE_TO_GET_ISSUER_CERT_LOCALLY`, `CERT_HAS_EXPIRED`, `CERT_NOT_YET_VALID` or `INVALID_PURPOSE`, with the engine's reason as `detail`. A failed handshake otherwise is `ERR_SSL_HANDSHAKE_FAILURE`.
419
419
  - **`rejectUnauthorized: false`** finishes the handshake whatever the chain says and reports `authorized: false` with `authorizationError`.
@@ -422,12 +422,21 @@ The module's default export (or its `main` export) is called with a context and
422
422
  - `peerCertificates` is the server's chain as DER, leaf first.
423
423
  - `cipher` is the negotiated suite as Node's `getCipher()` gives it: `{ name, standardName, version }`, where `name` is OpenSSL's (`ECDHE-RSA-AES128-GCM-SHA256`) and `standardName` IANA's. As in Node, `version` is the suite's own version, not the session's: `TLSv1.0` for a CBC-SHA suite on a TLS 1.2 session.
424
424
  - `clientCertificate` says whether a client certificate was offered. `sni` says whether the server name was sent: it's false with `sni: false` and for an IP-literal `servername`, which TLS never sends.
425
- - `hostnameChecked` says whether the kernel checked the leaf against `servername`. `hostnameMatches` says whether it names it (absent with `rejectUnauthorized: false`).
425
+ - `hostnameChecked` says whether the kernel checked the leaf against `servername`. `hostnameMatches` says whether it names it.
426
+ - With `rejectUnauthorized: false`, `chainError` says what is wrong with the chain apart from the name, with Node's names, and is absent when the chain is fine:
427
+ - a self-signed leaf alone is `DEPTH_ZERO_SELF_SIGNED_CERT`;
428
+ - an untrusted chain ending in a self-signed root is `SELF_SIGNED_CERT_IN_CHAIN`;
429
+ - a lone leaf whose issuer is unknown is `UNABLE_TO_VERIFY_LEAF_SIGNATURE`;
430
+ - an untrusted longer chain is `UNABLE_TO_GET_ISSUER_CERT_LOCALLY`;
431
+ - otherwise it's the reason's code, such as `CERT_HAS_EXPIRED`.
432
+
433
+ It's never `ERR_TLS_CERT_ALTNAME_INVALID`; that's `hostnameMatches: false`. `authorized` and `authorizationError` are as before.
426
434
  - **A client certificate** ([#1004](https://github.com/ai-ecoverse/slicc-kernel/issues/1004)): `cert` (PEM text, DER bytes or a list: the leaf first, then its intermediates) and `key` (PEM, PKCS#1, SEC1 or PKCS#8, or DER), with `passphrase` for an encrypted key, as in Node.
427
435
  - The key goes to the engine before anything is dialled, and the kernel keeps no copy of it (nor of the passphrase) once the engine has it.
428
436
  - Before dialling, `cert` without `key` (or the reverse) is `EINVAL`. A key that doesn't match the leaf is `ERR_OSSL_X509_KEY_VALUES_MISMATCH`, a wrong passphrase `ERR_OSSL_BAD_DECRYPT`, a missing one `ERR_OSSL_CRYPTO_INTERRUPTED_OR_CANCELLED`, and a key the engine can't read `ERR_OSSL_UNSUPPORTED`.
429
437
  - `pfx` is `ENOTSUP`: pass `cert` and `key`.
430
438
  - A server that requires a certificate and gets none refuses with an alert. On TLS 1.2 that fails the connect (`ERR_SSL_HANDSHAKE_FAILURE`). On TLS 1.3 the client's side of the handshake is already done, so the next read or write fails with `ERR_SSL_FATAL_ALERT`, as Node's fails after `secureConnect`.
439
+ - **A fatal alert from the server**, at the handshake or after it, is in the error: its `detail` ends in ` (alert <n>)`, and a JS program's error has `alert: n`, the alert's description number (116 certificate_required, 40 handshake_failure).
431
440
  - **`sni: false`** sends no server name. The leaf is still checked against `servername` exactly as with SNI.
432
441
  - **`checkHostname: false`** checks the chain (trust, validity, usage) but **not that the leaf names `servername`**. The connection reports `hostnameChecked: false`, and `hostnameMatches` says what the skipped check found.
433
442
  - **The caller must then check the server's identity itself**, as slicc-jsh does with Node's `checkServerIdentity` and `peerCertificates[0]`; pass it only when the program supplied one.
@@ -1034,7 +1043,7 @@ The kernel is ported from SLICC's `packages/webapp/src/kernel/` with the browser
1034
1043
 
1035
1044
  - `src/kernel/`: the kernel side, per process (`host.ts` starts the worker and answers its syscalls in `process.ts`) and shared tables (descriptors, pipes, children, jobs, signals, terminals and pseudo-terminals, `select`), and process credentials (`cred.ts`).
1036
1045
  - `src/process/`: the runtime inside each process worker. It evaluates the Emscripten glue, mounts the live VFS, routes descriptors through the kernel and implements `fork` by copying the whole linear memory into a new worker (Asyncify). `fork` is the only call allowed to suspend through Asyncify: an `fsync` that Emscripten made asynchronous is answered synchronously by the file's own stream instead. `src/process/wasi/` runs WASI and WASIX programs.
1037
- - `src/realm/`: the synchronous bridge (`SharedArrayBuffer` + `Atomics.wait`) and the live Emscripten filesystem on top of it. When a program's file call gets no answer, the bridge treats it like an NFS mount (#990). A read-only call (`read`, `pread`, `stat`, `lstat`, `readdir`, `readlink`, `exists`, `access`, `statfs`) fails with `EIO` once nothing has come back for 25 s; the clock starts again with every chunk of a long answer, so a slow transfer that keeps answering never fails (the host keeps a long answer for 30 s after each chunk it hands over, not after the first), and a late answer is dropped, which is harmless because the call changed nothing. A call that changes the file system (writes, `rename`, `unlink`, `mkdir`, creates, `chmod`, holds…) waits for its answer like a hard mount, however long the backend is gone, so it never returns an error for an effect that lands later. Only a signal that ends the process (`SIGKILL`) or the kernel shutting down ends that wait. JavaScript programs' synchronous `ctx.sync.fs` calls go through their own lane, which waits without a deadline for every call, reads included, so a stalled read hangs there instead of failing with `EIO` (#1033).
1046
+ - `src/realm/`: the synchronous bridge (`SharedArrayBuffer` + `Atomics.wait`) and the live Emscripten filesystem on top of it. When a program's file call gets no answer, the bridge treats it like an NFS mount (#990). A read-only call (`read`, `pread`, `stat`, `lstat`, `readdir`, `readlink`, `exists`, `access`, `statfs`) fails with `EIO` once nothing has come back for 25 s; the clock starts again with every chunk of a long answer, so a slow transfer that keeps answering never fails (the host keeps a long answer for 30 s after each chunk it hands over, not after the first), and a late answer is dropped, which is harmless because the call changed nothing. A call that changes the file system (writes, `rename`, `unlink`, `mkdir`, creates, `chmod`, holds…) waits for its answer like a hard mount, however long the backend is gone, so it never returns an error for an effect that lands later. Only a signal that ends the process (`SIGKILL`) or the kernel shutting down ends that wait. JavaScript programs' synchronous `ctx.sync.fs` calls get the same treatment on their own lane (#1033): a read-only call (`readFile`, `stat`, `lstat`, `readdir`, `readlink`, `exists`, `statfs`) throws `EIO` after 25 s without an answer, and every other call, as well as descriptor calls such as a read from a pipe or a terminal, waits for its answer.
1038
1047
  - `src/fs/`: the OPFS filesystem and the virtual command directories.
1039
1048
  - `src/launcher.ts`, `src/commands.ts`, `src/serve.ts`, `src/index.ts`, `src/users.ts`: command resolution, the kernel worker protocol, the page API and the user database; `src/node.ts`, `src/node-process-worker.ts` and `src/node/` the headless Node entry. An embedder that uses `Launcher` directly, without `createKernel`, calls `await launcher.prepare()` first: it creates `/tmp` and `/home` and writes the CA certificate.
1040
1049
  - `src/kernel/net/`: the proxy, HTTP/1.1, TLS termination and the local CA, and the bridge to the page's transport; `src/transport.ts` and `src/local-proxy-transport.ts` are the page side.