OverviewFilesCommitsIssuesDocsReleasesPeers

P2P-Hiverelay / packages / blind-daemon / store-session.js

793 lines · javascript ref:
import fs from 'node:fs/promises'
import { constants as FS_CONSTANTS } from 'node:fs'
import path from 'node:path'
import {
  releaseExclusiveFileLock,
  tryExclusiveFileLock
} from '@hiverelay/blind-peercred'

const CONTROL_DIRECTORY = 'control'
const WRITER_LOCK_FILE = 'writer.lock.v1'
const RUNTIME_BINDING_FILE = 'runtime-binding.v1'
const GENESIS_INTENT_FILE = 'genesis-intent.v1'
const STORE_GENERATION_HEAD_FILE = 'blind-store-generation-head-v1.json'
const STORE_GENERATION_RECORD = /^blind-store-generation-record-[0-9]{16}-v1\.json$/
const STORE_GENERATION_TEMP = /^\.blind-store-generation-.*\.tmp-[0-9]+$/
const MANIFEST_SLOT_FILES = Object.freeze(['manifest-a.v1', 'manifest-b.v1'])
const ROOT_NAMES = new Set([CONTROL_DIRECTORY, RUNTIME_BINDING_FILE, 'blobs', 'staging'])
const CONTROL_NAMES = new Set([
  WRITER_LOCK_FILE, 'wal.v2', GENESIS_INTENT_FILE, STORE_GENERATION_HEAD_FILE, ...MANIFEST_SLOT_FILES
])
const MANIFEST_TEMP = /^\.manifest-[ab]\.v1\.[0-9a-f]{32}\.tmp$/
const GENESIS_INTENT_TEMP = /^\.genesis-intent\.v1\.[0-9a-f]{32}\.tmp$/
const CHECKPOINT_FINAL = /^(checkpoint|snapshot)-([0-9a-f]{64})\.v1$/
const CHECKPOINT_TEMP = /^\.(checkpoint|snapshot)-([0-9a-f]{64})\.v1\.([0-9a-f]{32})\.tmp$/
const WAL_SEGMENT_FINAL = /^wal-([0-9a-f]{16})-([0-9a-f]{16})\.v2$/
const ACTIVE_SESSION_ROOTS = new Set()
const STORE_SESSION_PRIVATE = new WeakMap()
const STORE_SESSION_CONTEXTS = new WeakMap()
const STORE_SESSION_TRANSACTION_LEASES = new WeakSet()
const STORE_SESSION_TRANSACTION_LEASE_STATE = new WeakMap()

export const BLIND_STORE_ROOT_CLASSIFICATION = Object.freeze({
  PRISTINE: 'pristine',
  GENESIS_INCOMPLETE: 'genesis-incomplete',
  CURRENT_MANIFESTED: 'current-manifested',
  LEGACY_AMBIGUOUS: 'legacy-ambiguous'
})

export const BLIND_STORE_SESSION_INTEGRATION_STATUS = Object.freeze({
  productionRuntimeReady: false,
  transactionStoreLockOwnership: 'STORE_SESSION_TRANSACTION_LEASE',
  blocker: 'TWO_SLOT_MANIFEST_RUNTIME_INTEGRATION_UNASSEMBLED'
})

export class BlindStoreSessionError extends Error {
  constructor (message, code = 'BLIND_STORE_SESSION_INVALID') {
    super(message)
    this.name = 'BlindStoreSessionError'
    this.code = code
  }
}

function canonicalRoot (root) {
  if (typeof root !== 'string' || root.includes('\0') || !path.isAbsolute(root) || path.normalize(root) !== root) {
    throw new TypeError('store session root must be a canonical absolute path')
  }
  return root
}

function sameNames (left, right) {
  return left.length === right.length && left.every((name, index) => name === right[index])
}

function stateFor (stat) {
  return Object.freeze({
    dev: stat.dev,
    ino: stat.ino,
    mode: stat.mode,
    uid: stat.uid,
    gid: stat.gid,
    nlink: stat.nlink,
    size: stat.size,
    mtimeMs: stat.mtimeMs,
    ctimeMs: stat.ctimeMs,
    kind: stat.isDirectory() ? 'directory' : stat.isFile() ? 'file' : stat.isSymbolicLink() ? 'symlink' : 'other'
  })
}

function sameState (left, right) {
  return left.dev === right.dev && left.ino === right.ino && left.mode === right.mode &&
    left.uid === right.uid && left.gid === right.gid && left.nlink === right.nlink &&
    left.size === right.size && left.mtimeMs === right.mtimeMs && left.ctimeMs === right.ctimeMs &&
    left.kind === right.kind
}

function privateDirectory (stat) {
  return stat.isDirectory() && !stat.isSymbolicLink() &&
    (typeof process.getuid !== 'function' || stat.uid === process.getuid()) &&
    (stat.mode & 0o700) === 0o700 && (stat.mode & 0o077) === 0
}

function privateFile (stat, expectedLinks = 1) {
  return stat.isFile() && !stat.isSymbolicLink() && (expectedLinks == null || stat.nlink === expectedLinks) &&
    (typeof process.getuid !== 'function' || stat.uid === process.getuid()) &&
    (stat.mode & 0o600) === 0o600 && (stat.mode & 0o077) === 0
}

async function inspectRootDirectory (root) {
  const before = await fs.lstat(root)
  if (!privateDirectory(before) || await fs.realpath(root) !== root) {
    throw new BlindStoreSessionError(
      'store root must be a canonical daemon-owned private directory',
      'BLIND_STORE_ROOT_INVALID'
    )
  }
  const names = (await fs.readdir(root)).sort()
  const after = await fs.lstat(root)
  const namesAfter = (await fs.readdir(root)).sort()
  if (!sameState(stateFor(before), stateFor(after)) || !sameNames(names, namesAfter)) {
    throw new BlindStoreSessionError('store root changed while it was classified', 'BLIND_STORE_LAYOUT_CHANGED')
  }
  return { state: stateFor(after), names }
}

async function inspectPrivateDirectory (directory, label) {
  let before
  try {
    before = await fs.lstat(directory)
  } catch (error) {
    return { ok: false, reason: `${label} is missing`, error }
  }
  if (!privateDirectory(before)) return { ok: false, reason: `${label} is not a private regular directory` }
  let real
  try {
    real = await fs.realpath(directory)
  } catch (error) {
    return { ok: false, reason: `${label} realpath failed`, error }
  }
  if (real !== directory) return { ok: false, reason: `${label} traverses a symlinked path` }
  let names
  let namesAfter
  let after
  try {
    names = (await fs.readdir(directory)).sort()
    after = await fs.lstat(directory)
    namesAfter = (await fs.readdir(directory)).sort()
  } catch (error) {
    return { ok: false, reason: `${label} changed while it was inspected`, error }
  }
  if (!sameState(stateFor(before), stateFor(after)) || !sameNames(names, namesAfter)) {
    throw new BlindStoreSessionError(`${label} changed while it was classified`, 'BLIND_STORE_LAYOUT_CHANGED')
  }
  return { ok: true, state: stateFor(after), names }
}

async function inspectEntry (target, expectedKind, label, options = {}) {
  let before
  let after
  try {
    before = await fs.lstat(target)
    after = await fs.lstat(target)
  } catch (error) {
    return { ok: false, reason: `${label} is missing or unstable`, error }
  }
  const beforeState = stateFor(before)
  const afterState = stateFor(after)
  if (!sameState(beforeState, afterState)) {
    throw new BlindStoreSessionError(`${label} changed while it was classified`, 'BLIND_STORE_LAYOUT_CHANGED')
  }
  const ok = expectedKind === 'directory'
    ? privateDirectory(after)
    : privateFile(after, options.expectedLinks === undefined ? 1 : options.expectedLinks)
  if (ok && options.expectedSize != null && after.size !== options.expectedSize) {
    return { ok: false, state: afterState, reason: `${label} does not have its exact required byte length` }
  }
  return ok
    ? { ok: true, state: afterState }
    : { ok: false, state: afterState, reason: `${label} is not a private single-link ${expectedKind}` }
}

function checkpointArtifact (name) {
  let match = CHECKPOINT_FINAL.exec(name)
  if (match) return Object.freeze({ kind: match[1], hash: match[2], role: 'final' })
  match = CHECKPOINT_TEMP.exec(name)
  if (match) return Object.freeze({ kind: match[1], hash: match[2], role: 'temporary' })
  return null
}

function walSegmentArtifact (name) {
  const match = WAL_SEGMENT_FINAL.exec(name)
  if (!match) return null
  return Object.freeze({ kind: 'wal-segment', firstSequence: match[1], lastSequence: match[2], role: 'final' })
}

function classification (kind, root, rootState, rootNames, details = {}) {
  return Object.freeze({
    kind,
    root,
    rootState,
    rootNames: Object.freeze([...rootNames]),
    reason: details.reason || null,
    controlState: details.controlState || null,
    controlNames: Object.freeze([...(details.controlNames || [])]),
    entryStates: Object.freeze([...(details.entryStates || [])])
  })
}

function classificationFingerprint (value) {
  const state = item => item == null
    ? '-'
    : [item.dev, item.ino, item.mode, item.uid, item.gid, item.nlink, item.size,
        item.mtimeMs, item.ctimeMs, item.kind].join(':')
  return [
    value.kind,
    state(value.rootState),
    value.rootNames.join(','),
    state(value.controlState),
    value.controlNames.join(','),
    value.entryStates.map(entry => `${entry.name}:${state(entry.state)}`).join(',')
  ].join('|')
}

export async function classifyBlindStoreRoot (configuredRoot) {
  const root = canonicalRoot(configuredRoot)
  const inspectedRoot = await inspectRootDirectory(root)
  if (inspectedRoot.names.length === 0) {
    return classification(BLIND_STORE_ROOT_CLASSIFICATION.PRISTINE,
      root, inspectedRoot.state, inspectedRoot.names)
  }
  const unknownRootName = inspectedRoot.names.find(name => !ROOT_NAMES.has(name))
  if (unknownRootName) {
    return classification(BLIND_STORE_ROOT_CLASSIFICATION.LEGACY_AMBIGUOUS,
      root, inspectedRoot.state, inspectedRoot.names, { reason: `unrecognized root entry ${unknownRootName}` })
  }
  if (!inspectedRoot.names.includes(CONTROL_DIRECTORY)) {
    if (sameNames(inspectedRoot.names, [RUNTIME_BINDING_FILE])) {
      const runtimeBinding = await inspectEntry(
        path.join(root, RUNTIME_BINDING_FILE),
        'file',
        'store runtime binding',
        { expectedSize: 213 }
      )
      if (runtimeBinding.ok) {
        return classification(BLIND_STORE_ROOT_CLASSIFICATION.PRISTINE,
          root, inspectedRoot.state, inspectedRoot.names, {
            entryStates: [Object.freeze({ name: RUNTIME_BINDING_FILE, state: runtimeBinding.state })]
          })
      }
    }
    return classification(BLIND_STORE_ROOT_CLASSIFICATION.LEGACY_AMBIGUOUS,
      root, inspectedRoot.state, inspectedRoot.names, { reason: 'nonempty store has no control directory' })
  }

  const entryStates = []
  for (const name of inspectedRoot.names) {
    if (name === CONTROL_DIRECTORY) continue
    const expectedKind = name === RUNTIME_BINDING_FILE ? 'file' : 'directory'
    const inspected = await inspectEntry(
      path.join(root, name),
      expectedKind,
      `store root entry ${name}`,
      name === RUNTIME_BINDING_FILE ? { expectedSize: 213 } : {}
    )
    if (!inspected.ok) {
      return classification(BLIND_STORE_ROOT_CLASSIFICATION.LEGACY_AMBIGUOUS,
        root, inspectedRoot.state, inspectedRoot.names, { reason: inspected.reason, entryStates })
    }
    entryStates.push(Object.freeze({ name, state: inspected.state }))
  }

  const controlDirectory = path.join(root, CONTROL_DIRECTORY)
  const control = await inspectPrivateDirectory(controlDirectory, 'store control directory')
  if (!control.ok) {
    return classification(BLIND_STORE_ROOT_CLASSIFICATION.LEGACY_AMBIGUOUS,
      root, inspectedRoot.state, inspectedRoot.names, { reason: control.reason, entryStates })
  }
  const unknownControlName = control.names.find(name =>
    !CONTROL_NAMES.has(name) && !STORE_GENERATION_RECORD.test(name) && !STORE_GENERATION_TEMP.test(name) &&
    !MANIFEST_TEMP.test(name) &&
    !GENESIS_INTENT_TEMP.test(name) && !checkpointArtifact(name) && !walSegmentArtifact(name))
  if (unknownControlName) {
    return classification(BLIND_STORE_ROOT_CLASSIFICATION.LEGACY_AMBIGUOUS,
      root, inspectedRoot.state, inspectedRoot.names, {
        reason: `unrecognized control entry ${unknownControlName}`,
        controlState: control.state,
        controlNames: control.names,
        entryStates
      })
  }
  for (const name of control.names) {
    const inspected = await inspectEntry(
      path.join(controlDirectory, name),
      'file',
      `store control entry ${name}`
    )
    if (!inspected.ok) {
      return classification(BLIND_STORE_ROOT_CLASSIFICATION.LEGACY_AMBIGUOUS,
        root, inspectedRoot.state, inspectedRoot.names, {
          reason: inspected.reason,
          controlState: control.state,
          controlNames: control.names,
          entryStates
        })
    }
    entryStates.push(Object.freeze({ name: `${CONTROL_DIRECTORY}/${name}`, state: inspected.state }))
  }
  if (!control.names.includes(WRITER_LOCK_FILE)) {
    if (control.names.length === 0) {
      return classification(BLIND_STORE_ROOT_CLASSIFICATION.GENESIS_INCOMPLETE,
        root, inspectedRoot.state, inspectedRoot.names, {
          reason: 'pristine bootstrap created its control directory but not its writer lock',
          controlState: control.state,
          controlNames: control.names,
          entryStates
        })
    }
    return classification(BLIND_STORE_ROOT_CLASSIFICATION.LEGACY_AMBIGUOUS,
      root, inspectedRoot.state, inspectedRoot.names, {
        reason: 'manifested store has no existing writer lock',
        controlState: control.state,
        controlNames: control.names,
        entryStates
      })
  }
  if (!MANIFEST_SLOT_FILES.some(name => control.names.includes(name))) {
    const hasGenesisIntent = control.names.includes(GENESIS_INTENT_FILE)
    const hasGenesisIntentTemporary = control.names.some(name => GENESIS_INTENT_TEMP.test(name))
    const hasBootstrapData = control.names.some(name =>
      name === 'wal.v2' || walSegmentArtifact(name) != null || checkpointArtifact(name) != null
    ) || inspectedRoot.names.some(name => name === 'blobs' || name === 'staging')
    if (!hasBootstrapData || hasGenesisIntent || hasGenesisIntentTemporary) {
      return classification(BLIND_STORE_ROOT_CLASSIFICATION.GENESIS_INCOMPLETE,
        root, inspectedRoot.state, inspectedRoot.names, {
          reason: 'authorized crash-resumable genesis has not installed a manifest slot',
          controlState: control.state,
          controlNames: control.names,
          entryStates
        })
    }
    return classification(BLIND_STORE_ROOT_CLASSIFICATION.LEGACY_AMBIGUOUS,
      root, inspectedRoot.state, inspectedRoot.names, {
        reason: 'control directory has no manifest slot',
        controlState: control.state,
        controlNames: control.names,
        entryStates
      })
  }
  return classification(BLIND_STORE_ROOT_CLASSIFICATION.CURRENT_MANIFESTED,
    root, inspectedRoot.state, inspectedRoot.names, {
      controlState: control.state,
      controlNames: control.names,
      entryStates
    })
}

async function syncDirectory (directory) {
  const handle = await fs.open(directory, FS_CONSTANTS.O_RDONLY)
  try {
    await handle.sync()
  } finally {
    await handle.close()
  }
}

async function assertOpenedLock (handle, lockPath) {
  const [opened, linked] = await Promise.all([handle.stat(), fs.lstat(lockPath)])
  if (!privateFile(opened) || !privateFile(linked) || opened.dev !== linked.dev || opened.ino !== linked.ino) {
    throw new BlindStoreSessionError('writer lock path and opened inode disagree', 'BLIND_STORE_LOCK_INVALID')
  }
  return stateFor(opened)
}

function sessionPrivate (session) {
  const state = STORE_SESSION_PRIVATE.get(session)
  if (!state) throw new BlindStoreSessionError('store session identity is invalid', 'BLIND_STORE_SESSION_INVALID')
  return state
}

function releaseTransactionLease (lease) {
  if (!STORE_SESSION_TRANSACTION_LEASES.has(lease)) return
  const leaseState = STORE_SESSION_TRANSACTION_LEASE_STATE.get(lease)
  if (leaseState.released) return
  leaseState.released = true
  STORE_SESSION_TRANSACTION_LEASES.delete(lease)
  const state = sessionPrivate(leaseState.session)
  if (state.activeTransactionLease === leaseState) state.activeTransactionLease = null
  leaseState.resolveReleased()
}

function mintTransactionLease (leaseState) {
  const lease = Object.freeze({
    root: leaseState.root,
    generation: leaseState.generation,
    release: () => releaseTransactionLease(lease)
  })
  STORE_SESSION_TRANSACTION_LEASES.add(lease)
  STORE_SESSION_TRANSACTION_LEASE_STATE.set(lease, leaseState)
  leaseState.lease = lease
  return lease
}

export async function verifyBlindStoreSessionTransactionLease (lease, expectedRoot) {
  const root = canonicalRoot(expectedRoot)
  if (!lease || typeof lease !== 'object' || !STORE_SESSION_TRANSACTION_LEASES.has(lease)) {
    throw new BlindStoreSessionError('store session transaction lease is forged or inactive', 'BLIND_STORE_TRANSACTION_LEASE_INVALID')
  }
  const leaseState = STORE_SESSION_TRANSACTION_LEASE_STATE.get(lease)
  if (!leaseState || leaseState.released || lease.root !== root || leaseState.root !== root) {
    throw new BlindStoreSessionError('store session transaction lease root or lifetime is invalid', 'BLIND_STORE_TRANSACTION_LEASE_INVALID')
  }
  const session = leaseState.session
  const state = sessionPrivate(session)
  if (session.root !== root || session.writerLockPath !== leaseState.writerLockPath) {
    throw new BlindStoreSessionError('store session transaction lease identity no longer matches its root', 'BLIND_STORE_TRANSACTION_LEASE_INVALID')
  }
  if (state.activeTransactionLease !== leaseState || state.generation !== leaseState.generation ||
      lease.generation !== leaseState.generation) {
    throw new BlindStoreSessionError('store session transaction lease generation is stale', 'BLIND_STORE_TRANSACTION_LEASE_INVALID')
  }
  if (state.closing || state.closed || !state.opened || !state.lockHeld || !state.writerLockHandle) {
    throw new BlindStoreSessionError('store session transaction lease has no open writer authority', 'BLIND_STORE_SESSION_CLOSING')
  }
  const observed = await assertOpenedLock(state.writerLockHandle, leaseState.writerLockPath)
  if (observed.dev !== leaseState.lockState.dev || observed.ino !== leaseState.lockState.ino) {
    throw new BlindStoreSessionError('writer lock inode changed during transaction lease verification', 'BLIND_STORE_LOCK_INVALID')
  }
  if (state.activeTransactionLease !== leaseState || state.generation !== leaseState.generation ||
      state.closing || state.closed || !state.opened || !state.lockHeld) {
    throw new BlindStoreSessionError('store session changed while its transaction lease was verified', 'BLIND_STORE_SESSION_CLOSING')
  }
  return true
}

/**
 * Atomically replace a caller-held transaction lease with a successor lease.
 * The old object becomes unverifiable and its release closure becomes inert;
 * the StoreSession continues waiting on the same underlying lease lifetime.
 */
export async function transferBlindStoreSessionTransactionLease (lease, expectedRoot) {
  const root = canonicalRoot(expectedRoot)
  await verifyBlindStoreSessionTransactionLease(lease, root)
  const leaseState = STORE_SESSION_TRANSACTION_LEASE_STATE.get(lease)
  const state = sessionPrivate(leaseState.session)
  if (!leaseState.transferable || leaseState.lease !== lease || leaseState.released ||
      state.activeTransactionLease !== leaseState || !STORE_SESSION_TRANSACTION_LEASES.has(lease)) {
    throw new BlindStoreSessionError(
      'store session transaction lease cannot be transferred again',
      'BLIND_STORE_TRANSACTION_LEASE_TRANSFER_INVALID'
    )
  }
  leaseState.transferable = false
  STORE_SESSION_TRANSACTION_LEASES.delete(lease)
  return mintTransactionLease(leaseState)
}

/**
 * Borrow the writer authority already held by a StoreSession. The returned
 * lease is branded inside this module; callers cannot manufacture either the
 * context or a second concurrent lease by copying their visible fields.
 */
export async function acquireBlindStoreSessionTransactionLease (context, expectedRoot) {
  const root = canonicalRoot(expectedRoot)
  if (!context || typeof context !== 'object') {
    throw new BlindStoreSessionError('store session lock context is invalid', 'BLIND_STORE_SESSION_CONTEXT_INVALID')
  }
  const contextState = STORE_SESSION_CONTEXTS.get(context)
  if (!contextState || contextState.context !== context) {
    throw new BlindStoreSessionError('store session lock context is forged or unknown', 'BLIND_STORE_SESSION_CONTEXT_INVALID')
  }
  if (contextState.root !== root || context.root !== root) {
    throw new BlindStoreSessionError('store session lock context belongs to a different root', 'BLIND_STORE_SESSION_ROOT_MISMATCH')
  }
  const session = contextState.session
  const state = sessionPrivate(session)
  if (state.context !== context || state.generation !== contextState.generation ||
      context.generation !== contextState.generation) {
    throw new BlindStoreSessionError('store session lock context generation is stale', 'BLIND_STORE_SESSION_CONTEXT_STALE')
  }
  if (state.closing || state.closed || session.closing || session.closed) {
    throw new BlindStoreSessionError('store session is closing or closed', 'BLIND_STORE_SESSION_CLOSING')
  }
  if (!state.opened || !session.opened || !state.lockHeld || !state.writerLockHandle) {
    throw new BlindStoreSessionError('store session is not open with its writer lock', 'BLIND_STORE_SESSION_NOT_OPEN')
  }
  if (session.root !== root || session.writerLockPath !== contextState.writerLockPath) {
    throw new BlindStoreSessionError('store session identity no longer matches its context', 'BLIND_STORE_SESSION_CONTEXT_STALE')
  }
  if (state.activeTransactionLease) {
    throw new BlindStoreSessionError('store session already has an active transaction lease', 'BLIND_STORE_TRANSACTION_LEASE_ACTIVE')
  }

  let resolveReleased
  const released = new Promise(resolve => { resolveReleased = resolve })
  const leaseState = {
    session,
    root,
    generation: state.generation,
    writerLockPath: contextState.writerLockPath,
    lockState: contextState.lockState,
    transferable: true,
    released: false,
    releasedPromise: released,
    resolveReleased
  }
  const lease = mintTransactionLease(leaseState)
  state.activeTransactionLease = leaseState

  try {
    await verifyBlindStoreSessionTransactionLease(lease, root)
    if (state.context !== context) {
      throw new BlindStoreSessionError(
        'store session changed while its transaction lease was acquired',
        'BLIND_STORE_SESSION_CONTEXT_STALE'
      )
    }
    return lease
  } catch (error) {
    releaseTransactionLease(lease)
    throw error
  }
}

export class BlindStoreSession {
  constructor (options = {}) {
    this.root = canonicalRoot(options.root)
    this.controlDirectory = path.join(this.root, CONTROL_DIRECTORY)
    this.writerLockPath = path.join(this.controlDirectory, WRITER_LOCK_FILE)
    this.allowPristineBootstrap = options.allowPristineBootstrap === true
    if (options.faultInjector != null && typeof options.faultInjector !== 'function') {
      throw new TypeError('faultInjector must be a function')
    }
    this.faultInjector = options.faultInjector || null
    this.writerLockHandle = null
    this.lockHeld = false
    this.opened = false
    this.closing = false
    this.closed = false
    this.openPromise = null
    this.closePromise = null
    this.rootClassification = null
    this.bootstrapCreated = false
    STORE_SESSION_PRIVATE.set(this, {
      generation: 0,
      context: null,
      writerLockHandle: null,
      lockHeld: false,
      lockState: null,
      opened: false,
      closing: false,
      closed: false,
      activeTransactionLease: null
    })
  }

  async _fault (point, context = {}) {
    if (this.faultInjector) await this.faultInjector(point, Object.freeze({ root: this.root, ...context }))
  }

  open () {
    if (this.closed) return Promise.reject(new Error('store session is closed'))
    if (this.openPromise) return this.openPromise
    this.openPromise = this._open()
    return this.openPromise
  }

  async _open () {
    if (this.opened || this.writerLockHandle) throw new Error('store session is already open')
    if (ACTIVE_SESSION_ROOTS.has(this.root)) {
      throw new BlindStoreSessionError('store root already has a StoreSession in this process', 'BLIND_STORE_LOCKED')
    }
    if (!FS_CONSTANTS.O_NOFOLLOW) {
      throw new BlindStoreSessionError('O_NOFOLLOW is required for StoreSession', 'BLIND_STORE_LOCK_UNAVAILABLE')
    }
    ACTIVE_SESSION_ROOTS.add(this.root)
    try {
      const initial = await classifyBlindStoreRoot(this.root)
      await this._fault('store-session:after-classification', { classification: initial.kind })
      if (initial.kind === BLIND_STORE_ROOT_CLASSIFICATION.LEGACY_AMBIGUOUS) {
        throw new BlindStoreSessionError(
          `store layout is legacy or ambiguous: ${initial.reason}`,
          'BLIND_STORE_LAYOUT_AMBIGUOUS'
        )
      }
      if (initial.kind === BLIND_STORE_ROOT_CLASSIFICATION.PRISTINE) {
        await this._openPristine(initial)
      } else if (initial.kind === BLIND_STORE_ROOT_CLASSIFICATION.GENESIS_INCOMPLETE) {
        if (!this.allowPristineBootstrap) {
          throw new BlindStoreSessionError(
            'incomplete genesis resume was not explicitly authorized',
            'BLIND_STORE_BOOTSTRAP_NOT_AUTHORIZED'
          )
        }
        if (initial.controlNames.includes(WRITER_LOCK_FILE)) {
          await this._openExisting(initial, BLIND_STORE_ROOT_CLASSIFICATION.GENESIS_INCOMPLETE)
        } else {
          await this._openGenesisControlShell(initial)
        }
      } else {
        await this._openExisting(initial)
      }
      this.rootClassification = initial
      this.opened = true
      const state = sessionPrivate(this)
      state.generation++
      state.opened = true
      const context = Object.freeze({
        root: this.root,
        controlDirectory: this.controlDirectory,
        writerLockPath: this.writerLockPath,
        generation: state.generation,
        classification: this.rootClassification.kind,
        bootstrapCreated: this.bootstrapCreated,
        ownsWriterLock: true,
        transactionStoreLockOwnership: BLIND_STORE_SESSION_INTEGRATION_STATUS.transactionStoreLockOwnership,
        integrationBlocker: BLIND_STORE_SESSION_INTEGRATION_STATUS.blocker
      })
      state.context = context
      STORE_SESSION_CONTEXTS.set(context, Object.freeze({
        context,
        session: this,
        root: this.root,
        writerLockPath: this.writerLockPath,
        generation: state.generation,
        lockState: state.lockState
      }))
      return this
    } catch (error) {
      await this._release().catch(() => {})
      ACTIVE_SESSION_ROOTS.delete(this.root)
      throw error
    }
  }

  async _openExisting (initial, expectedClassification = BLIND_STORE_ROOT_CLASSIFICATION.CURRENT_MANIFESTED) {
    this.writerLockHandle = await fs.open(
      this.writerLockPath,
      FS_CONSTANTS.O_RDWR | FS_CONSTANTS.O_NOFOLLOW
    )
    const state = sessionPrivate(this)
    state.writerLockHandle = this.writerLockHandle
    state.lockState = await assertOpenedLock(this.writerLockHandle, this.writerLockPath)
    await this._fault('store-session:after-lock-open', { classification: initial.kind })
    if (!tryExclusiveFileLock(this.writerLockHandle)) {
      throw new BlindStoreSessionError('store root already has an active writer', 'BLIND_STORE_LOCKED')
    }
    this.lockHeld = true
    state.lockHeld = true
    await this._fault('store-session:after-lock-acquired', { classification: initial.kind })
    const rechecked = await classifyBlindStoreRoot(this.root)
    if (rechecked.kind !== expectedClassification ||
        classificationFingerprint(rechecked) !== classificationFingerprint(initial)) {
      throw new BlindStoreSessionError(
        'store layout changed between classification and writer-lock acquisition',
        'BLIND_STORE_LAYOUT_CHANGED'
      )
    }
  }

  async _openPristine (initial) {
    if (!this.allowPristineBootstrap) {
      throw new BlindStoreSessionError(
        'pristine store bootstrap was not explicitly authorized',
        'BLIND_STORE_BOOTSTRAP_NOT_AUTHORIZED'
      )
    }
    const rechecked = await classifyBlindStoreRoot(this.root)
    if (rechecked.kind !== BLIND_STORE_ROOT_CLASSIFICATION.PRISTINE ||
        classificationFingerprint(rechecked) !== classificationFingerprint(initial)) {
      throw new BlindStoreSessionError(
        'pristine store changed before bootstrap lock creation',
        'BLIND_STORE_LAYOUT_CHANGED'
      )
    }
    await this._fault('store-session:after-pristine-recheck', { classification: initial.kind })
    await fs.mkdir(this.controlDirectory, { mode: 0o700 })
    await this._fault('store-session:after-control-mkdir', { classification: initial.kind })
    this.writerLockHandle = await fs.open(
      this.writerLockPath,
      FS_CONSTANTS.O_RDWR | FS_CONSTANTS.O_CREAT | FS_CONSTANTS.O_EXCL | FS_CONSTANTS.O_NOFOLLOW,
      0o600
    )
    await this._fault('store-session:after-lock-create', { classification: initial.kind })
    const state = sessionPrivate(this)
    state.writerLockHandle = this.writerLockHandle
    const lockState = await assertOpenedLock(this.writerLockHandle, this.writerLockPath)
    state.lockState = lockState
    if (!tryExclusiveFileLock(this.writerLockHandle)) {
      throw new BlindStoreSessionError('new bootstrap writer lock could not be acquired', 'BLIND_STORE_LOCKED')
    }
    this.lockHeld = true
    state.lockHeld = true
    await this.writerLockHandle.sync()
    await this._fault('store-session:after-lock-file-sync', { classification: initial.kind })
    await syncDirectory(this.controlDirectory)
    await this._fault('store-session:after-control-directory-sync', { classification: initial.kind })
    await syncDirectory(this.root)
    await this._fault('store-session:after-root-directory-sync', { classification: initial.kind })
    const root = await inspectRootDirectory(this.root)
    const control = await inspectPrivateDirectory(this.controlDirectory, 'store control directory')
    const expectedRootNames = [...initial.rootNames, CONTROL_DIRECTORY].sort()
    if (!control.ok || !sameNames(root.names, expectedRootNames) ||
        !sameNames(control.names, [WRITER_LOCK_FILE])) {
      throw new BlindStoreSessionError('pristine bootstrap layout changed during lock creation', 'BLIND_STORE_LAYOUT_CHANGED')
    }
    const installed = await fs.lstat(this.writerLockPath)
    if (!sameState(lockState, stateFor(installed))) {
      throw new BlindStoreSessionError('bootstrap writer lock changed during creation', 'BLIND_STORE_LAYOUT_CHANGED')
    }
    this.bootstrapCreated = true
  }

  async _openGenesisControlShell (initial) {
    const rechecked = await classifyBlindStoreRoot(this.root)
    if (rechecked.kind !== BLIND_STORE_ROOT_CLASSIFICATION.GENESIS_INCOMPLETE ||
        rechecked.controlNames.length !== 0 ||
        classificationFingerprint(rechecked) !== classificationFingerprint(initial)) {
      throw new BlindStoreSessionError(
        'incomplete genesis control shell changed before writer-lock creation',
        'BLIND_STORE_LAYOUT_CHANGED'
      )
    }
    this.writerLockHandle = await fs.open(
      this.writerLockPath,
      FS_CONSTANTS.O_RDWR | FS_CONSTANTS.O_CREAT | FS_CONSTANTS.O_EXCL | FS_CONSTANTS.O_NOFOLLOW,
      0o600
    )
    await this._fault('store-session:after-lock-create', { classification: initial.kind })
    const state = sessionPrivate(this)
    state.writerLockHandle = this.writerLockHandle
    const lockState = await assertOpenedLock(this.writerLockHandle, this.writerLockPath)
    state.lockState = lockState
    if (!tryExclusiveFileLock(this.writerLockHandle)) {
      throw new BlindStoreSessionError('resumed bootstrap writer lock could not be acquired', 'BLIND_STORE_LOCKED')
    }
    this.lockHeld = true
    state.lockHeld = true
    await this.writerLockHandle.sync()
    await this._fault('store-session:after-lock-file-sync', { classification: initial.kind })
    await syncDirectory(this.controlDirectory)
    await this._fault('store-session:after-control-directory-sync', { classification: initial.kind })
    await syncDirectory(this.root)
    await this._fault('store-session:after-root-directory-sync', { classification: initial.kind })
    const installed = await fs.lstat(this.writerLockPath)
    if (!sameState(lockState, stateFor(installed))) {
      throw new BlindStoreSessionError('resumed bootstrap writer lock changed during creation', 'BLIND_STORE_LAYOUT_CHANGED')
    }
    this.bootstrapCreated = true
  }

  lockContext () {
    const state = sessionPrivate(this)
    if (!state.opened || state.closing || !state.lockHeld || !state.context) {
      throw new Error('store session does not hold its writer lock')
    }
    return state.context
  }

  async _release () {
    const state = sessionPrivate(this)
    const handle = this.writerLockHandle
    const held = this.lockHeld
    this.writerLockHandle = null
    this.lockHeld = false
    state.writerLockHandle = null
    state.lockHeld = false
    state.lockState = null
    if (!handle) return
    try {
      if (held) releaseExclusiveFileLock(handle)
    } finally {
      await handle.close()
    }
  }

  close () {
    const state = sessionPrivate(this)
    if (this.closePromise) return this.closePromise
    if (!this.opened && !this.writerLockHandle && !this.openPromise) {
      this.closed = true
      state.closed = true
      return Promise.resolve()
    }
    this.closing = true
    this.closed = true
    state.closing = true
    state.closed = true
    this.closePromise = (async () => {
      try {
        if (this.openPromise) await this.openPromise.catch(() => {})
        while (state.activeTransactionLease) {
          await state.activeTransactionLease.releasedPromise
        }
        await this._release()
      } finally {
        this.opened = false
        state.opened = false
        ACTIVE_SESSION_ROOTS.delete(this.root)
      }
    })()
    return this.closePromise
  }
}