Add fifth feature word (STOCK_V5 / bits5) with ADR and capability docs.
Protocol: canonical seed RPC registry (seed-rpc-methods.js), bits5 on capabilities, typed seed RPC errors, richer replication_queue and staging_slot hints. Booter: /proc host_os (bare-module on Bare, node:os on Node), sync_window, debug.json, net_summary transport stats, HDMS hints/correlation, warm profile reload, subprocess bridge snapshot helpers, boot policy v5 hooks, BARE_OS_BIN_WORKER_ALLOW pattern groups, VFS symlink/union alignment, OTel JSONL schema version 2 in var-log. Seeder: pass staging/replication hints into seed channel; mirror kernel init and boot policy example. Kernel: enforce requireFeatureBits5 / requireInitJsSha256 when configured; selftests for new proc surfaces. CI/pretest: verify-doc-links, verify-man-coverage, verify-compat-matrix; extend roadmap/ctx/dts verifiers. Add otel-bare-os-jsonl schema. Docs: Wave 5 roadmap, kernel-extensions, handbook/devguide updates; bare-module manifest tier/risk sample; bare-libs README.
This commit is contained in:
@@ -10,9 +10,9 @@ Shared **wire format and constants** for the Bare operating system monorepo: Hyp
|
||||
| `topicKey()` | 32-byte topic for `swarm.join()` |
|
||||
| `BLOCK_SIZE`, `MBR_MAGIC` | 512-byte MBR, magic `BIOS` at offset 0 |
|
||||
| `buildMbr` / `parseMbr` | Pack/unpack primary + optional failover Hyperdrive keys |
|
||||
| `setupSeedChannel` | Wire Protomux messages 0–6 for RAM block reads, gossip bitfield, manifest path **search**, **RPC** (incl. `bare_os.capabilities` with **`bits`/`bits2`/`bits3`/`bits4`**, `bare_os.replication_status`, `bare_os.replication_queue`, `bare_os.capability_attestation`, `bare_os.mbr_layout`, `bare_os.manifest_hints`, `bare_os.peer_health`, `bare_os.staging_slot`, `bare_os.snapshot_hints`, `bare_os.peer_firewall_stats`, `bare_os.gossip`), and `drive.replicate` |
|
||||
| `setupSeedChannel` | Wire Protomux messages 0–6 for RAM block reads, gossip bitfield, manifest path **search**, **RPC** (incl. `bare_os.capabilities` with **`bits`/`bits2`/`bits3`/`bits4`/`bits5`**, typed errors for unknown RPC methods, `bare_os.replication_status`, `bare_os.replication_queue`, `bare_os.capability_attestation`, `bare_os.mbr_layout`, `bare_os.manifest_hints`, `bare_os.peer_health`, `bare_os.staging_slot`, `bare_os.snapshot_hints`, `bare_os.peer_firewall_stats`, `bare_os.gossip`), and `drive.replicate` |
|
||||
|
||||
Subpath exports: `bare-os-protocol/constants.js`, `bare-os-protocol/messages` (compact-encoding schemas), `bare-os-protocol/kernel-feature-bits.js` (documented booter capability words **`STOCK_V1`** / **`STOCK_V2`** / **`STOCK_V3`** / **`STOCK_V4`**; surfaced in **`/proc/bare_os_features`** and **`/proc/bare_os/`**), `bare-os-protocol/protocol-meta.js` (**`BARE_OS_PROTOCOL_PACKAGE_VERSION`** for the seed handshake).
|
||||
Subpath exports: `bare-os-protocol/constants.js`, `bare-os-protocol/messages` (compact-encoding schemas), `bare-os-protocol/kernel-feature-bits.js` (documented booter capability words **`STOCK_V1`** … **`STOCK_V5`**; surfaced in **`/proc/bare_os_features`** and **`/proc/bare_os/`**), `bare-os-protocol/lib/seed-rpc-methods.js` (authoritative **`bare_os.*`** RPC name list for **`kernel_info`**), `bare-os-protocol/protocol-meta.js` (**`BARE_OS_PROTOCOL_PACKAGE_VERSION`** for the seed handshake).
|
||||
|
||||
## Consumers
|
||||
|
||||
|
||||
@@ -9,6 +9,11 @@ export {
|
||||
} from './constants.js'
|
||||
|
||||
export { setupSeedChannel } from './lib/channel.js'
|
||||
export {
|
||||
BARE_OS_SEED_RPC_METHODS,
|
||||
BARE_OS_SEED_RPC_METHOD_SHORT_NAMES,
|
||||
BARE_OS_SEED_RPC_METHOD_SHORT_NAME_SET
|
||||
} from './lib/seed-rpc-methods.js'
|
||||
export { BARE_OS_PROTOCOL_PACKAGE_VERSION } from './lib/protocol-meta.js'
|
||||
export {
|
||||
BARE_OS_KERNEL_FEATURE_BITS_DOC,
|
||||
@@ -93,5 +98,22 @@ export {
|
||||
BARE_OS_FEATURE4_INITD_CONDITION_DIRECTORY,
|
||||
BARE_OS_FEATURE4_DELEGATE_FAIRNESS_METRICS,
|
||||
BARE_OS_FEATURE4_BIN_WORKER_ACTIVE,
|
||||
BARE_OS_FEATURE4_SUBPROCESS_JOB_SURFACE
|
||||
BARE_OS_FEATURE4_SUBPROCESS_JOB_SURFACE,
|
||||
BARE_OS_KERNEL_FEATURES_STOCK_V5,
|
||||
BARE_OS_FEATURE5_HOST_BARE_OS_PROC,
|
||||
BARE_OS_FEATURE5_SUBPROCESS_BRIDGE_SNAPSHOT_V2,
|
||||
BARE_OS_FEATURE5_NET_SUMMARY_TRANSPORT,
|
||||
BARE_OS_FEATURE5_BOOT_POLICY_V5,
|
||||
BARE_OS_FEATURE5_REPLICATION_SYNC_WINDOWS,
|
||||
BARE_OS_FEATURE5_VFS_UNION_READLINK,
|
||||
BARE_OS_FEATURE5_KERNEL_PROFILE_WARM,
|
||||
BARE_OS_FEATURE5_HDMS_OPS_HINTS_V2,
|
||||
BARE_OS_FEATURE5_TELEMETRY_OTEL_V2,
|
||||
BARE_OS_FEATURE5_BIN_WORKER_PATTERN_ALLOW,
|
||||
BARE_OS_FEATURE5_STAGING_ROLLBACK_HINTS,
|
||||
BARE_OS_FEATURE5_KERNEL_DEBUG_PROC,
|
||||
BARE_OS_FEATURE5_BARE_MANIFEST_RISK,
|
||||
BARE_OS_FEATURE5_REPLICATION_QUEUE_METRICS_V2,
|
||||
BARE_OS_FEATURE5_SEED_RPC_TYPED_ERRORS,
|
||||
BARE_OS_FEATURE5_REPO_DOC_CI
|
||||
} from './lib/kernel-feature-bits.js'
|
||||
|
||||
@@ -6,8 +6,13 @@ import {
|
||||
BARE_OS_KERNEL_FEATURES_STOCK_V1,
|
||||
BARE_OS_KERNEL_FEATURES_STOCK_V2,
|
||||
BARE_OS_KERNEL_FEATURES_STOCK_V3,
|
||||
BARE_OS_KERNEL_FEATURES_STOCK_V4
|
||||
BARE_OS_KERNEL_FEATURES_STOCK_V4,
|
||||
BARE_OS_KERNEL_FEATURES_STOCK_V5
|
||||
} from './kernel-feature-bits.js'
|
||||
import {
|
||||
BARE_OS_SEED_RPC_METHODS,
|
||||
BARE_OS_SEED_RPC_METHOD_SHORT_NAME_SET
|
||||
} from './seed-rpc-methods.js'
|
||||
import { BARE_OS_PROTOCOL_PACKAGE_VERSION } from './protocol-meta.js'
|
||||
import {
|
||||
msgDataEncoding,
|
||||
@@ -31,6 +36,9 @@ import {
|
||||
* attestationJson?: string,
|
||||
* snapshotHintsJson?: string,
|
||||
* peerFirewallStatsJson?: string,
|
||||
* replicationQueueDepthHint?: number,
|
||||
* replicationSnapshotNoteJson?: string,
|
||||
* stagingPreviousSlot?: string,
|
||||
* drive?: { core?: { length?: number }, id?: Uint8Array }
|
||||
* }} [opts]
|
||||
*/
|
||||
@@ -50,6 +58,9 @@ export function setupSeedChannel(mux, localRAM, replicateDrive, opts = {}) {
|
||||
const stagingPendingSlot = String(
|
||||
opts.stagingPendingSlot ?? opts.stagingPending ?? ''
|
||||
).trim()
|
||||
const stagingPreviousSlot = String(opts.stagingPreviousSlot ?? '')
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
const searchMax =
|
||||
typeof opts.searchMaxMatches === 'number' && opts.searchMaxMatches > 0
|
||||
? Math.min(opts.searchMaxMatches, 2000)
|
||||
@@ -95,6 +106,30 @@ export function setupSeedChannel(mux, localRAM, replicateDrive, opts = {}) {
|
||||
chan.addMessage({
|
||||
encoding: msgRpcReqEncoding,
|
||||
onmessage(m) {
|
||||
if (m.module !== 'bare_os') {
|
||||
chan.messages[6].send({
|
||||
id: m.id,
|
||||
success: false,
|
||||
result: '',
|
||||
error:
|
||||
m.module == null || m.module === ''
|
||||
? 'bare_os.rpc_missing_module'
|
||||
: 'bare_os.rpc_wrong_module'
|
||||
})
|
||||
return
|
||||
}
|
||||
{
|
||||
const meth = String(m.method ?? '').trim()
|
||||
if (!BARE_OS_SEED_RPC_METHOD_SHORT_NAME_SET.has(meth)) {
|
||||
chan.messages[6].send({
|
||||
id: m.id,
|
||||
success: false,
|
||||
result: '',
|
||||
error: 'bare_os.rpc_unknown_method'
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
if (m.module === 'bare_os' && m.method === 'version') {
|
||||
chan.messages[6].send({
|
||||
id: m.id,
|
||||
@@ -126,22 +161,7 @@ export function setupSeedChannel(mux, localRAM, replicateDrive, opts = {}) {
|
||||
success: true,
|
||||
result: JSON.stringify({
|
||||
protocol: PROTOCOL_NAME,
|
||||
rpc: [
|
||||
'bare_os.version',
|
||||
'bare_os.health',
|
||||
'bare_os.kernel_info',
|
||||
'bare_os.capabilities',
|
||||
'bare_os.gossip',
|
||||
'bare_os.replication_status',
|
||||
'bare_os.manifest_hints',
|
||||
'bare_os.peer_health',
|
||||
'bare_os.staging_slot',
|
||||
'bare_os.replication_queue',
|
||||
'bare_os.capability_attestation',
|
||||
'bare_os.mbr_layout',
|
||||
'bare_os.snapshot_hints',
|
||||
'bare_os.peer_firewall_stats'
|
||||
],
|
||||
rpc: BARE_OS_SEED_RPC_METHODS,
|
||||
note: 'Kernel and image semver are resolved at boot on the booter; this channel is seeder-local.'
|
||||
}),
|
||||
error: ''
|
||||
@@ -159,6 +179,7 @@ export function setupSeedChannel(mux, localRAM, replicateDrive, opts = {}) {
|
||||
bits2: BARE_OS_KERNEL_FEATURES_STOCK_V2 >>> 0,
|
||||
bits3: BARE_OS_KERNEL_FEATURES_STOCK_V3 >>> 0,
|
||||
bits4: BARE_OS_KERNEL_FEATURES_STOCK_V4 >>> 0,
|
||||
bits5: BARE_OS_KERNEL_FEATURES_STOCK_V5 >>> 0,
|
||||
protocolPackageVersion: BARE_OS_PROTOCOL_PACKAGE_VERSION,
|
||||
role: 'seeder',
|
||||
protocol: PROTOCOL_NAME
|
||||
@@ -239,6 +260,9 @@ export function setupSeedChannel(mux, localRAM, replicateDrive, opts = {}) {
|
||||
protocol: PROTOCOL_NAME,
|
||||
activeSlot: stagingActiveSlot,
|
||||
pendingSlot: stagingPendingSlot || null,
|
||||
previousSlot: stagingPreviousSlot || null,
|
||||
rollbackHint:
|
||||
'pending slot is rollback candidate when switching A/B; verify image before activate',
|
||||
atMs: Date.now()
|
||||
}),
|
||||
error: ''
|
||||
@@ -254,6 +278,24 @@ export function setupSeedChannel(mux, localRAM, replicateDrive, opts = {}) {
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
const depthHint =
|
||||
typeof opts.replicationQueueDepthHint === 'number' &&
|
||||
opts.replicationQueueDepthHint >= 0
|
||||
? Math.floor(opts.replicationQueueDepthHint)
|
||||
: manifestPaths.length
|
||||
let snapshotNote = ''
|
||||
const snapRaw = String(opts.replicationSnapshotNoteJson ?? '').trim()
|
||||
if (snapRaw) {
|
||||
try {
|
||||
const o = JSON.parse(snapRaw)
|
||||
snapshotNote =
|
||||
o && typeof o === 'object' && typeof o.note === 'string'
|
||||
? o.note.slice(0, 256)
|
||||
: 'snapshot-hint-json'
|
||||
} catch {
|
||||
snapshotNote = 'invalid replicationSnapshotNoteJson'
|
||||
}
|
||||
}
|
||||
chan.messages[6].send({
|
||||
id: m.id,
|
||||
success: true,
|
||||
@@ -263,7 +305,11 @@ export function setupSeedChannel(mux, localRAM, replicateDrive, opts = {}) {
|
||||
manifestPathCount: manifestPaths.length,
|
||||
localRamBlockCount: localRAM.size,
|
||||
hypercoreLengthHint: coreLength,
|
||||
note: 'hypercoreLengthHint is seeder-local; not a full replication queue.',
|
||||
queueDepthEstimate: depthHint,
|
||||
snapshotWorkflowNote:
|
||||
snapshotNote ||
|
||||
'Align long replication with corestore-snapshot-style cutover; guest does not verify crypto.',
|
||||
note: 'hypercoreLengthHint and queueDepthEstimate are seeder-local hints only.',
|
||||
atMs: Date.now()
|
||||
}),
|
||||
error: ''
|
||||
@@ -373,7 +419,7 @@ export function setupSeedChannel(mux, localRAM, replicateDrive, opts = {}) {
|
||||
id: m.id,
|
||||
success: false,
|
||||
result: '',
|
||||
error: 'RPC not implemented on seeder'
|
||||
error: 'bare_os.rpc_internal_unreachable'
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/** Protocol document version for this bitmask file (bump when bit semantics or governance changes). */
|
||||
export const BARE_OS_KERNEL_FEATURE_BITS_DOC = 6
|
||||
export const BARE_OS_KERNEL_FEATURE_BITS_DOC = 7
|
||||
|
||||
/**
|
||||
* Second capability word (bits 0–31, always use `>>> 0` when masking).
|
||||
@@ -226,6 +226,61 @@ export const BARE_OS_KERNEL_FEATURES_STOCK_V4 =
|
||||
BARE_OS_FEATURE4_BIN_WORKER_ACTIVE |
|
||||
BARE_OS_FEATURE4_SUBPROCESS_JOB_SURFACE
|
||||
|
||||
/**
|
||||
* Fifth capability word (bits 0–31, use `>>> 0`). Wave 5 — ADR 001 §8.
|
||||
*/
|
||||
/** Word5 bit 0: `/proc/bare_os/host_os.json` (`BARE_OS_HOST_BARE_OS_PROC` / `BARE_OS_HOST_OS_JSON`). */
|
||||
export const BARE_OS_FEATURE5_HOST_BARE_OS_PROC = 1 << 0
|
||||
/** Word5 bit 1: `bareOsReadSubprocessBridgeSnapshot` + `BARE_OS_SUBPROCESS_BRIDGE_META_JSON`. */
|
||||
export const BARE_OS_FEATURE5_SUBPROCESS_BRIDGE_SNAPSHOT_V2 = 1 << 1
|
||||
/** Word5 bit 2: Transport counters in net summary (`BARE_OS_NET_TRANSPORT_STATS_JSON`). */
|
||||
export const BARE_OS_FEATURE5_NET_SUMMARY_TRANSPORT = 1 << 2
|
||||
/** Word5 bit 3: Boot policy v5 (`requireFeatureBits5`, `requireInitJsSha256`). */
|
||||
export const BARE_OS_FEATURE5_BOOT_POLICY_V5 = 1 << 3
|
||||
/** Word5 bit 4: Replication sync windows + `/proc/bare_os/sync_window.json`. */
|
||||
export const BARE_OS_FEATURE5_REPLICATION_SYNC_WINDOWS = 1 << 4
|
||||
/** Word5 bit 5: Union readlink shadow lookup on personal drive. */
|
||||
export const BARE_OS_FEATURE5_VFS_UNION_READLINK = 1 << 5
|
||||
/** Word5 bit 6: Warm profile reload (`BARE_OS_KERNEL_PROFILE_WARM`, `bareOsRequestKernelProfileReload`). */
|
||||
export const BARE_OS_FEATURE5_KERNEL_PROFILE_WARM = 1 << 6
|
||||
/** Word5 bit 7: HDMS hints v2 (`BARE_OS_HDMS_SUPPORT_CORRELATION_ID`). */
|
||||
export const BARE_OS_FEATURE5_HDMS_OPS_HINTS_V2 = 1 << 7
|
||||
/** Word5 bit 8: OTel JSONL schema v2 lines. */
|
||||
export const BARE_OS_FEATURE5_TELEMETRY_OTEL_V2 = 1 << 8
|
||||
/** Word5 bit 9: `BARE_OS_BIN_WORKER_ALLOW` pattern groups (`textproc:*`, …). */
|
||||
export const BARE_OS_FEATURE5_BIN_WORKER_PATTERN_ALLOW = 1 << 9
|
||||
/** Word5 bit 10: Staging rollback hints (`BARE_OS_SEED_STAGING_PREVIOUS_SLOT`). */
|
||||
export const BARE_OS_FEATURE5_STAGING_ROLLBACK_HINTS = 1 << 10
|
||||
/** Word5 bit 11: `/proc/bare_os/debug.json` when `BARE_OS_KERNEL_DEBUG=1`. */
|
||||
export const BARE_OS_FEATURE5_KERNEL_DEBUG_PROC = 1 << 11
|
||||
/** Word5 bit 12: Manifest / catalog `risk` metadata for `ctx.bare`. */
|
||||
export const BARE_OS_FEATURE5_BARE_MANIFEST_RISK = 1 << 12
|
||||
/** Word5 bit 13: Replication queue metrics v2 on seeder RPC. */
|
||||
export const BARE_OS_FEATURE5_REPLICATION_QUEUE_METRICS_V2 = 1 << 13
|
||||
/** Word5 bit 14: Typed seed RPC errors (`bare_os.rpc_unknown_method`). */
|
||||
export const BARE_OS_FEATURE5_SEED_RPC_TYPED_ERRORS = 1 << 14
|
||||
/** Word5 bit 15: Repo doc CI scripts (man coverage, compat matrix, doc links). */
|
||||
export const BARE_OS_FEATURE5_REPO_DOC_CI = 1 << 15
|
||||
|
||||
/** Stock booter fifth word (wave 5). */
|
||||
export const BARE_OS_KERNEL_FEATURES_STOCK_V5 =
|
||||
BARE_OS_FEATURE5_HOST_BARE_OS_PROC |
|
||||
BARE_OS_FEATURE5_SUBPROCESS_BRIDGE_SNAPSHOT_V2 |
|
||||
BARE_OS_FEATURE5_NET_SUMMARY_TRANSPORT |
|
||||
BARE_OS_FEATURE5_BOOT_POLICY_V5 |
|
||||
BARE_OS_FEATURE5_REPLICATION_SYNC_WINDOWS |
|
||||
BARE_OS_FEATURE5_VFS_UNION_READLINK |
|
||||
BARE_OS_FEATURE5_KERNEL_PROFILE_WARM |
|
||||
BARE_OS_FEATURE5_HDMS_OPS_HINTS_V2 |
|
||||
BARE_OS_FEATURE5_TELEMETRY_OTEL_V2 |
|
||||
BARE_OS_FEATURE5_BIN_WORKER_PATTERN_ALLOW |
|
||||
BARE_OS_FEATURE5_STAGING_ROLLBACK_HINTS |
|
||||
BARE_OS_FEATURE5_KERNEL_DEBUG_PROC |
|
||||
BARE_OS_FEATURE5_BARE_MANIFEST_RISK |
|
||||
BARE_OS_FEATURE5_REPLICATION_QUEUE_METRICS_V2 |
|
||||
BARE_OS_FEATURE5_SEED_RPC_TYPED_ERRORS |
|
||||
BARE_OS_FEATURE5_REPO_DOC_CI
|
||||
|
||||
/** Bit 0: IPC fan-out / pub-sub style channels (booter `bareOsIpc`). */
|
||||
export const BARE_OS_FEATURE_IPC_FANOUT = 1 << 0
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Single source of truth for `bare_os.*` seed RPC method names (short form, without `bare_os.` prefix).
|
||||
* Used by `channel.js` for `kernel_info` and unknown-method handling.
|
||||
*/
|
||||
export const BARE_OS_SEED_RPC_METHOD_SHORT_NAMES = [
|
||||
'version',
|
||||
'health',
|
||||
'kernel_info',
|
||||
'capabilities',
|
||||
'replication_status',
|
||||
'gossip',
|
||||
'manifest_hints',
|
||||
'peer_health',
|
||||
'staging_slot',
|
||||
'replication_queue',
|
||||
'capability_attestation',
|
||||
'mbr_layout',
|
||||
'snapshot_hints',
|
||||
'peer_firewall_stats'
|
||||
]
|
||||
|
||||
/** @type {Set<string>} */
|
||||
export const BARE_OS_SEED_RPC_METHOD_SHORT_NAME_SET = new Set(
|
||||
BARE_OS_SEED_RPC_METHOD_SHORT_NAMES
|
||||
)
|
||||
|
||||
/** Full dotted names for documentation / tests. */
|
||||
export const BARE_OS_SEED_RPC_METHODS = BARE_OS_SEED_RPC_METHOD_SHORT_NAMES.map(
|
||||
(m) => 'bare_os.' + m
|
||||
)
|
||||
@@ -8,6 +8,11 @@ import {
|
||||
BLOCK_SIZE,
|
||||
TOPIC_STRING
|
||||
} from './constants.js'
|
||||
import {
|
||||
BARE_OS_SEED_RPC_METHOD_SHORT_NAMES,
|
||||
BARE_OS_SEED_RPC_METHODS
|
||||
} from './lib/seed-rpc-methods.js'
|
||||
import { BARE_OS_KERNEL_FEATURES_STOCK_V5 } from './lib/kernel-feature-bits.js'
|
||||
import { msgDataEncoding, msgSearchReqEncoding } from './lib/messages.js'
|
||||
test('topicKey is deterministic 32-byte hash', (t) => {
|
||||
const a = topicKey()
|
||||
@@ -60,3 +65,14 @@ test('msgSearchReqEncoding roundtrip', (t) => {
|
||||
test('TOPIC_STRING is bare-os-v1', (t) => {
|
||||
t.is(TOPIC_STRING, 'bare-os-v1')
|
||||
})
|
||||
|
||||
test('seed RPC method list matches kernel_info surface', (t) => {
|
||||
t.ok(BARE_OS_SEED_RPC_METHOD_SHORT_NAMES.includes('capabilities'))
|
||||
t.ok(BARE_OS_SEED_RPC_METHOD_SHORT_NAMES.includes('replication_queue'))
|
||||
t.is(BARE_OS_SEED_RPC_METHODS.length, BARE_OS_SEED_RPC_METHOD_SHORT_NAMES.length)
|
||||
t.ok(BARE_OS_SEED_RPC_METHODS.every((m) => m.startsWith('bare_os.')))
|
||||
})
|
||||
|
||||
test('STOCK_V5 is non-zero wave-5 advertisement', (t) => {
|
||||
t.ok((BARE_OS_KERNEL_FEATURES_STOCK_V5 >>> 0) > 0)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user