Files
Elydora-Go-SDK/cmd/elydora/plugins/transaction_atomic_windows.go
ZacharyZhang-NY eb41b991bf 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.
2026-07-21 19:02:57 -04:00

146 lines
3.7 KiB
Go

//go:build windows
package plugins
import (
"errors"
"fmt"
"os"
"path/filepath"
"time"
"golang.org/x/sys/windows"
)
func atomicRenameNoReplace(source, destination string) error {
from, err := windows.UTF16PtrFromString(source)
if err != nil {
return err
}
to, err := windows.UTF16PtrFromString(destination)
if err != nil {
return err
}
if err := windows.MoveFileEx(from, to, windows.MOVEFILE_WRITE_THROUGH); err != nil {
return err
}
return syncWindowsRenameDirectories(source, destination)
}
func isAtomicDestinationExists(err error) bool {
return errors.Is(err, windows.ERROR_ALREADY_EXISTS) ||
errors.Is(err, windows.ERROR_FILE_EXISTS)
}
func atomicReplaceWithBackup(target, replacement, backup string) error {
backupPointer, err := windows.UTF16PtrFromString(backup)
if err != nil {
return err
}
targetPointer, err := windows.UTF16PtrFromString(target)
if err != nil {
return err
}
if err := ensureWindowsAtomicBackup(
target,
backup,
targetPointer,
backupPointer,
); err != nil {
return err
}
replacementPointer, err := windows.UTF16PtrFromString(replacement)
if err != nil {
return err
}
deadline := time.Now().Add(2 * time.Second)
for {
err = windows.MoveFileEx(
replacementPointer,
targetPointer,
windows.MOVEFILE_REPLACE_EXISTING|windows.MOVEFILE_WRITE_THROUGH,
)
if err == nil {
return syncWindowsRenameDirectories(replacement, target)
}
if time.Now().After(deadline) ||
!errors.Is(err, windows.ERROR_ACCESS_DENIED) &&
!errors.Is(err, windows.ERROR_SHARING_VIOLATION) {
return err
}
time.Sleep(time.Millisecond)
}
}
func ensureWindowsAtomicBackup(
target, backup string,
targetPointer, backupPointer *uint16,
) error {
err := windows.CreateHardLink(backupPointer, targetPointer, 0)
if err != nil && !errors.Is(err, windows.ERROR_ALREADY_EXISTS) &&
!errors.Is(err, windows.ERROR_FILE_EXISTS) {
return err
}
if err != nil {
targetInfo, targetErr := os.Lstat(target)
backupInfo, backupErr := os.Lstat(backup)
if targetErr != nil || backupErr != nil ||
targetInfo.Mode()&os.ModeSymlink != 0 ||
backupInfo.Mode()&os.ModeSymlink != 0 ||
!targetInfo.Mode().IsRegular() || !backupInfo.Mode().IsRegular() ||
!os.SameFile(targetInfo, backupInfo) {
return errors.Join(
fmt.Errorf("atomic backup path is occupied by another object: %s", backup),
targetErr,
backupErr,
)
}
}
if err := syncTransactionDirectory(filepath.Dir(backup)); err != nil {
return fmt.Errorf("flush atomic backup directory: %w", err)
}
return nil
}
func atomicReplacementUsesSeparateBackup() bool {
return true
}
func transactionPlatformSupported() error {
return nil
}
func syncWindowsRenameDirectories(source, destination string) error {
destinationDirectory := filepath.Dir(destination)
destinationErr := syncTransactionDirectory(destinationDirectory)
if durablePathKey(filepath.Dir(source)) == durablePathKey(destinationDirectory) {
return destinationErr
}
return errors.Join(destinationErr, syncTransactionDirectory(filepath.Dir(source)))
}
func syncTransactionDirectory(path string) error {
pointer, err := windows.UTF16PtrFromString(path)
if err != nil {
return err
}
handle, err := windows.CreateFile(
pointer,
windows.GENERIC_WRITE,
windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE|windows.FILE_SHARE_DELETE,
nil,
windows.OPEN_EXISTING,
windows.FILE_FLAG_BACKUP_SEMANTICS|windows.FILE_FLAG_WRITE_THROUGH,
0,
)
if err != nil {
return fmt.Errorf("open directory for durable flush at %s: %w", path, err)
}
flushErr := windows.FlushFileBuffers(handle)
closeErr := windows.CloseHandle(handle)
if flushErr != nil {
flushErr = fmt.Errorf("flush directory metadata at %s: %w", path, flushErr)
}
return errors.Join(flushErr, closeErr)
}