rumpk/libs/membrane/config_ledger.nim

76 lines
2.4 KiB
Nim

# SPDX-License-Identifier: LUL-1.0
# Copyright (c) 2026 Markus Maiwald
# Stewardship: Self Sovereign Society Foundation
#
# This file is part of the Nexus Sovereign Core.
# See legal/LICENSE_SOVEREIGN.md for license terms.
## Nexus Membrane: Configuration Ledger (SPEC-803)
## Implements Event Sourcing for System State.
import strutils, times, options
import kdl # Local NPK/NipBox KDL
type
OpType* = enum
OpAdd, OpSet, OpDel, OpMerge, OpRollback
ConfigTx* = object
id*: uint64
timestamp*: uint64
author*: string
op*: OpType
path*: string
value*: Node # KDL Node for complex values
ConfigLedger* = object
head_tx*: uint64
ledger_path*: string
# --- Internal: Serialization ---
proc serialize_tx*(tx: ConfigTx): string =
## Converts a transaction to a KDL block for the log file.
result = "tx id=" & $tx.id & " ts=" & $tx.timestamp & " author=\"" & tx.author & "\" {\n"
result.add " op \"" & ($tx.op).replace("Op", "").toUpperAscii() & "\"\n"
result.add " path \"" & tx.path & "\"\n"
if tx.value != nil:
result.add tx.value.render(indent = 2)
result.add "}\n"
# --- Primary API ---
proc ledger_append*(ledger: var ConfigLedger, op: OpType, path: string, value: Node, author: string = "root") =
## Appends a new transaction to the ledger.
ledger.head_tx += 1
let tx = ConfigTx(
id: ledger.head_tx,
timestamp: uint64(epochTime()),
author: author,
op: op,
path: path,
value: value
)
# TODO: SFS-backed atomic write to /Data/ledger.sfs
let entry = serialize_tx(tx)
echo "[LEDGER] TX Commit: ", tx.id, " (", tx.path, ")"
# writeToFile(ledger.ledger_path, entry, append=true)
proc ledger_replay*(ledger: ConfigLedger): Node =
## Replays the entire log to project the current state tree.
## Returns the root KDL Node of the current world state.
result = newNode("root")
echo "[LEDGER] Replaying from 1 to ", ledger.head_tx
# 1. Read ledger.sfs
# 2. Parse into seq[ConfigTx]
# 3. Apply operations sequentially to result tree
# TODO: Implement state projection logic
proc ledger_rollback*(ledger: var ConfigLedger, target_tx: uint64) =
## Rolls back the system state.
## Note: This appends a ROLLBACK tx rather than truncating (SPEC-803 Doctrine).
let rb_node = newNode("rollback_target")
rb_node.addArg(newVal(int(target_tx)))
ledger.ledger_append(OpRollback, "system.rollback", rb_node)