feat(go): durable transaction engine and Kiro IDE 1.0 adapter

Split the monolithic transaction into focused modules: append-only
crash-recoverable journal under ~/.elydora/transactions with owner
tokens and per-transaction namespaces, staged atomic publication
(stage .pending, fsync, rename, fsync), platform-specific atomic
replacement (MoveFileEx, renameat2, renamex_np), private-directory
hardening per OS, lock-guarded recovery, and workspace cleanup that
removes only transaction-created empty directories.

Add the Kiro IDE 1.0 plugin: strict v1 hook schema with one enabled
PreToolUse guard and PostToolUse audit pair bound to the active
workspace, agent-to-workspace identity binding in runtime config, and
exact migration of the legacy elydora-audit.kiro.hook contract.

Gates: go test ./... and -race pass, go vet clean, govulncheck reports
zero reachable vulnerabilities, git diff --check clean.
This commit is contained in:
ZacharyZhang-NY committed 2026-07-21 19:02:57 -04:00
1 parent dd72793cdb
commit eb41b991bf
70 files changed
+8182 -358

No files matched your search

@@ -0,0 +1,261 @@
package plugins
import (
"errors"
"fmt"
"os"
"path/filepath"
"runtime"
"sort"
"strings"
)
func initializeDurableLayout(journal *durableJournal, changes []fileChange) error {
directories := make(map[string]int)
for index, change := range changes {
directory := filepath.Dir(change.filePath)
if err := ensureManagedDirectory(directory, "directory for "+change.label); err != nil {
return err
}
key := durablePathKey(directory)
workspaceIndex, exists := directories[key]
if !exists {
workspacePath := filepath.Join(directory, ".elydora-txn-"+journal.ID)
workspaceIndex = len(journal.Workspaces)
directories[key] = workspaceIndex
journal.Workspaces = append(journal.Workspaces, durableWorkspace{
Path: workspacePath, MarkerPath: filepath.Join(workspacePath, "owner"),
OwnerToken: journal.OwnerToken,
})
}
workspace := journal.Workspaces[workspaceIndex].Path
entry := durableEntry{
Path: change.filePath, Label: change.label, Workspace: workspace,
DiscardPath: filepath.Join(workspace, fmt.Sprintf("%04d.discard", index)),
Original: artifactFromChangeOriginal(change),
}
switch {
case change.remove:
entry.Kind = durableDelete
entry.OriginalPath = filepath.Join(workspace, fmt.Sprintf("%04d.original", index))
default:
entry.NextPath = filepath.Join(workspace, fmt.Sprintf("%04d.next", index))
entry.Next = durableArtifact{
Exists: true, SHA256: artifactDigest(change.next), Mode: uint32(change.mode.Perm()),
}
if change.existed {
entry.Kind = durableUpdate
if atomicReplacementUsesSeparateBackup() {
entry.OriginalPath = filepath.Join(
workspace,
fmt.Sprintf("%04d.original", index),
)
} else {
entry.OriginalPath = entry.NextPath
}
} else {
entry.Kind = durableCreate
}
}
journal.Entries = append(journal.Entries, entry)
}
sort.Slice(journal.Workspaces, func(left, right int) bool {
return durablePathKey(journal.Workspaces[left].Path) <
durablePathKey(journal.Workspaces[right].Path)
})
return nil
}
func durablePathKey(path string) string {
key := filepath.Clean(path)
if runtime.GOOS == "windows" {
return strings.ToLower(filepath.ToSlash(key))
}
return key
}
func createDurableWorkspaces(journal *durableJournal) error {
for index := range journal.Workspaces {
workspace := &journal.Workspaces[index]
if err := createPrivateTransactionDirectory(workspace.Path); err != nil {
return fmt.Errorf(
"create transaction workspace %s: %w; recovery namespace %s",
workspace.Path,
err,
journal.JournalDir,
)
}
marker := []byte(journal.ID + ":" + workspace.OwnerToken + "\n")
if err := writeOwnedFile(workspace.MarkerPath, marker, 0600); err != nil {
return fmt.Errorf("write transaction workspace owner at %s: %w", workspace.Path, err)
}
if err := syncTransactionDirectory(workspace.Path); err != nil {
return fmt.Errorf("persist transaction workspace owner at %s: %w", workspace.Path, err)
}
if err := syncTransactionDirectory(filepath.Dir(workspace.Path)); err != nil {
return fmt.Errorf("persist transaction workspace at %s: %w", workspace.Path, err)
}
identity, err := transactionDirectoryIdentity(workspace.Path)
if err != nil {
return err
}
workspace.DirectoryID = identity
if err := appendDurableJournal(journal, durablePhaseInitializing); err != nil {
return fmt.Errorf("persist transaction workspace identity at %s: %w", workspace.Path, err)
}
if err := probeAtomicTransactionCapabilities(workspace.Path); err != nil {
return fmt.Errorf(
"filesystem at %s lacks required durable transaction primitives: %w",
workspace.Path,
err,
)
}
}
return nil
}
func transactionDirectoryIdentity(path string) (string, error) {
directory, err := os.Open(path)
if err != nil {
return "", err
}
info, statErr := directory.Stat()
if statErr != nil || !info.IsDir() {
return "", errors.Join(
fmt.Errorf("transaction workspace is not a directory: %s", path),
statErr,
directory.Close(),
)
}
identity, identityErr := transactionFileIdentity(directory, info)
return identity, errors.Join(identityErr, directory.Close())
}
func stageDurableEntries(journal *durableJournal, changes []fileChange) error {
for index := range journal.Entries {
entry := &journal.Entries[index]
change := changes[index]
if entry.Kind == durableDelete {
continue
}
if err := writeOwnedFile(entry.NextPath, change.next, change.mode); err != nil {
return fmt.Errorf("stage %s at %s: %w", change.label, entry.NextPath, err)
}
snapshot, err := readDurableArtifact(entry.NextPath, "staged "+change.label)
if err != nil {
return err
}
entry.Next = artifactFromSnapshot(snapshot)
if entry.Next.SHA256 != artifactDigest(change.next) ||
!sameManagedFileMode(snapshot.mode, change.mode) {
return fmt.Errorf("staged %s changed before commit: %s", change.label, entry.NextPath)
}
if err := appendDurableJournal(journal, durablePhaseInitializing); err != nil {
return fmt.Errorf("persist staged %s identity: %w", change.label, err)
}
}
return nil
}
func probeAtomicTransactionCapabilities(workspace string) (result error) {
target := filepath.Join(workspace, "probe-target")
replacement := filepath.Join(workspace, "probe-replacement")
backup := replacement
if atomicReplacementUsesSeparateBackup() {
backup = filepath.Join(workspace, "probe-backup")
}
discard := filepath.Join(workspace, "probe-discard")
left := filepath.Join(workspace, "probe-left")
right := filepath.Join(workspace, "probe-right")
defer func() {
result = errors.Join(
result,
cleanupInterruptedCapabilityProbe(workspace),
)
}()
for path, content := range map[string]string{target: "old", replacement: "new"} {
if err := writeOwnedFile(path, []byte(content), 0600); err != nil {
return err
}
}
if err := atomicReplaceWithBackup(target, replacement, backup); err != nil {
return err
}
installed, err := readDurableArtifact(target, "atomic replacement probe")
if err != nil || installed == nil || string(installed.contents) != "new" {
return errors.Join(fmt.Errorf("atomic replacement probe failed"), err)
}
old, err := readDurableArtifact(backup, "atomic backup probe")
if err != nil || old == nil || string(old.contents) != "old" {
return errors.Join(fmt.Errorf("atomic replacement backup probe failed"), err)
}
if err := atomicReplaceWithBackup(target, backup, discardPathForProbe(backup, discard)); err != nil {
return fmt.Errorf("atomic rollback probe failed: %w", err)
}
if err := writeOwnedFile(left, []byte("left"), 0600); err != nil {
return err
}
if err := writeOwnedFile(right, []byte("right"), 0600); err != nil {
return err
}
leftBefore, err := readDurableArtifact(left, "atomic no-replace source probe")
if err != nil || leftBefore == nil {
return errors.Join(fmt.Errorf("read atomic no-replace source probe"), err)
}
rightBefore, err := readDurableArtifact(right, "atomic no-replace destination probe")
if err != nil || rightBefore == nil {
return errors.Join(fmt.Errorf("read atomic no-replace destination probe"), err)
}
renameErr := atomicRenameNoReplace(left, right)
if renameErr == nil {
return fmt.Errorf("atomic no-replace probe replaced an existing file")
}
if !isAtomicDestinationExists(renameErr) {
return fmt.Errorf("atomic no-replace probe returned an unsupported error: %w", renameErr)
}
if _, err := requireDurableArtifact(
left,
"atomic no-replace source probe",
artifactFromSnapshot(leftBefore),
); err != nil {
return err
}
if _, err := requireDurableArtifact(
right,
"atomic no-replace destination probe",
artifactFromSnapshot(rightBefore),
); err != nil {
return err
}
return nil
}
func discardPathForProbe(backup, discard string) string {
if atomicReplacementUsesSeparateBackup() {
return discard
}
return backup
}
func cleanupInterruptedCapabilityProbe(workspace string) error {
var failures []error
for _, name := range []string{
"probe-target",
"probe-replacement",
"probe-backup",
"probe-discard",
"probe-left",
"probe-right",
} {
path := filepath.Join(workspace, name)
snapshot, err := readManagedFile(path, "transaction capability probe", 64)
if err != nil {
failures = append(failures, err)
continue
}
if snapshot != nil {
failures = append(failures, removePhysicalOwnedFile(path, snapshot.identity))
}
}
return errors.Join(errors.Join(failures...), syncTransactionDirectory(workspace))
}