2026-11-12 15:19:43 +00:00
2026-11-12 15:04:11 +00:00
2026-11-12 15:19:43 +00:00
2026-11-12 15:04:11 +00:00
2026-11-12 15:19:43 +00:00
2026-11-12 15:04:11 +00:00
2026-11-12 15:19:43 +00:00

@serve.zone/witness

@serve.zone/witness is the serve.zone witness (AGL-1195): a small service at a third site that keeps one compare-and-set record per controller. The record decides which controller site is active in which epoch and whether the active has a standby in sync with it. Cloudly is its only caller and speaks the witness contract of @serve.zone/interfaces (requests.witness, data.IWitnessRecord) with TypedRequest over HTTPS.

Issue Reporting and Security

For reporting bugs, issues, or security vulnerabilities, please visit community.foss.global/. This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a code.foss.global/ account to submit Pull Requests directly.

Install

pnpm add @serve.zone/witness

The package installs the witness command. It runs on Node.js.

Running the witness

witness serve starts the HTTPS endpoint and the embedded storage engine. It stops on SIGINT or SIGTERM (exit 0) and when the storage engine exits on its own (exit 1), so a supervisor restarts it.

Variable Used by Meaning
WITNESS_DATA_DIR every command Normalized absolute directory of the witness state
WITNESS_TLS_CERT_PATH serve PEM certificate chain of the witness's https origin
WITNESS_TLS_KEY_PATH serve PEM private key of that certificate
WITNESS_LISTEN_HOST serve Interface address to bind; default 0.0.0.0
WITNESS_PORT serve TCP port; default 443

Below WITNESS_DATA_DIR the witness keeps nosqldb/, the NoSQLDB storage root, and run/nosqldb.sock, the engine's socket in a directory of mode 0700, so only the witness's own user reaches the engine. The witness reads its certificate at start; a renewed certificate takes effect at the next start.

Pairing codes

A controller pairs with the witness by redeeming a one-time code the witness operator makes on the witness host for exactly one controller id:

witness pairing-code --controller <controllerId> [--lifetime-minutes <1-60>]

The command connects to the engine of the running witness serve, stores only the SHA-256 of a new code, and prints the code once as a JSON line on stdout: {"controllerId":…,"pairingCode":…,"expiresAt":…}. @lossless.org/client 2.10.0 also prints its own Connected to database and disconnected from database lines on stdout around it; the answer is the line that is JSON. A code lives 10 minutes unless --lifetime-minutes says otherwise, pairs once, and pairs only its controller id. Pass the code to the controller's operator over a channel you trust; whoever holds it can pair that controller id until it expires.

The contract it serves

The witness answers the five requests.witness requests at data.witnessContract.typedRequestPath (/typedrequest) and nothing else: no static content, health route, sitemap, feed or WebSocket. The interfaces readme ("Witness") is the reference for the requests, the record and the refusals; this package never restates the contract, it imports it.

  • pairWitnessController consumes the code and creates the record in one transaction, so a controller whose answer was lost reads the record with its own bearer: the record is there exactly when the code was consumed.
  • enrollWitnessMember and compareAndSetWitnessRecord are compare-and-sets on {controllerId, revision} (atomicFindOneAndUpdate), each raising the revision by one. Of two changes naming one revision, at most one is stored; the other is refused revision-stale.
  • getWitnessRecord answers the record to a member.
  • getWitnessHealth answers { ready, witnessVersion, interfacesVersion } without authentication and names no controller. ready is true while the embedded storage engine runs and answers a bounded read; it does not probe a write. A write the storage cannot make is answered on that write, as witness-unavailable or outcome-unknown.

Every request passes its gates in the contract's order: the contract's validator (request-invalid), then the pairing code or the authentication, then revision-stale, then the first refusal of data.judgeWitnessChange or data.judgeWitnessMemberEnrollment. A refusal is a TypedResponseError whose errorData is data.createWitnessRefusalErrorData(code).

Credentials

The witness never holds a bearer. Each site creates its own and hands over only bearerSha256; the witness compares the SHA-256 of a presented bearer with the stored one in constant time. An unknown controller, a non-member site and a bad bearer all answer the same credential-invalid with the same text; the witness log records which case it was. No answer, refusal or log line carries a bearer or a pairing code.

Durability

Storage is a LocalNoSqlDb from @lossless.org/nosqldb, embedded in the witness process, with the models of @lossless.org/client/nosqldb. NoSQLDB acknowledges a write on file storage only after its write-ahead log is fsynced, and the witness answers a change only after that acknowledgement. NoSQLDB's own conditions apply: XFS, or ext4 with data=ordered, and a device that does not lose acknowledged bytes (see the NoSQLDB readme, "Storage Engine Reliability"). A change whose storage call fails is refused outcome-unknown: it may have been stored, and the caller reads the record before it acts.

Programmatic use

import { Witness, readWitnessServeConfig } from '@serve.zone/witness';

const witness = new Witness(readWitnessServeConfig(process.env));
await witness.start();
const { pairingCode } = await witness.issuePairingCode('controller-0123456789abcdef');
await witness.stop();

Witness options extend the serve configuration with logSink (structured log entries; default one JSON line each on stdout and stderr), clock (the witness clock pairing codes expire against) and onStorageFailure. runCli(argv, io) runs the CLI and resolves with its exit code.

Not yet

Forced promotion and member removal come later as additive contract requests (Linus ruling 73 Q2, Q9). A single executable build via tsrepo sea is not set up yet.

This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the repository license file.

Please note: The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.

Trademarks

This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.

Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.

Company Information

Task Venture Capital GmbH
Registered at District Court Bremen HRB 35230 HB, Germany

For any legal inquiries or further information, please contact us via email at hello@task.vc.

By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.

S
Description
the serve.zone witness: a compare-and-set register that decides which site's controller is active
Readme MIT
142 KiB
0 Stars 3 Watchers 0 Forks
Languages
TypeScript 99.8%
JavaScript 0.2%