feat: establish NekoNest Cloud control and relay

This commit is contained in:
2026-08-12 23:25:43 +08:00
commit f27606b709
222 changed files with 71456 additions and 0 deletions
+128
View File
@@ -0,0 +1,128 @@
package tenantpurge
import (
"context"
"crypto/sha256"
"encoding/hex"
"errors"
"fmt"
"os"
"path/filepath"
"strconv"
"strings"
"github.com/klarkxy/nekonest-cloud/relay/internal/tenantfs"
)
type Result struct {
DataDeleted bool
BackupsDeleted bool
EvidenceSHA256 string
}
func exactChild(parent, child string) (string, string, error) {
parentAbsolute, err := filepath.Abs(strings.TrimSpace(parent))
if err != nil || strings.TrimSpace(parent) == "" {
return "", "", errors.New("invalid purge parent")
}
childAbsolute, err := filepath.Abs(strings.TrimSpace(child))
if err != nil || filepath.Dir(childAbsolute) != parentAbsolute {
return "", "", errors.New("purge target escaped its parent")
}
return parentAbsolute, childAbsolute, nil
}
func validateTree(ctx context.Context, root string) error {
return filepath.WalkDir(root, func(path string, entry os.DirEntry, walkErr error) error {
if walkErr != nil {
return walkErr
}
if err := ctx.Err(); err != nil {
return err
}
if entry.Type()&os.ModeSymlink != 0 {
return fmt.Errorf("purge target contains a symbolic link: %s", path)
}
info, err := entry.Info()
if err != nil {
return err
}
if !info.IsDir() && !info.Mode().IsRegular() {
return fmt.Errorf("purge target contains a non-regular artifact: %s", path)
}
return nil
})
}
func removeTree(ctx context.Context, parent, target string) (bool, error) {
parent, target, err := exactChild(parent, target)
if err != nil {
return false, err
}
parentInfo, err := os.Lstat(parent)
if os.IsNotExist(err) {
return false, nil
}
if err != nil || parentInfo.Mode()&os.ModeSymlink != 0 || !parentInfo.IsDir() {
return false, errors.New("purge parent is not a real directory")
}
info, err := os.Lstat(target)
if os.IsNotExist(err) {
return false, nil
}
if err != nil || info.Mode()&os.ModeSymlink != 0 || !info.IsDir() {
return false, errors.New("purge target is not a real directory")
}
if err := validateTree(ctx, target); err != nil {
return false, err
}
if err := os.RemoveAll(target); err != nil {
return false, err
}
if _, err := os.Lstat(target); !os.IsNotExist(err) {
if err == nil {
return false, errors.New("purge target still exists")
}
return false, err
}
return true, nil
}
func evidence(tenantID string, generation int64) string {
digest := sha256.Sum256([]byte(
"nekonest-cloud/tenant-logical-purge/v1\x00" + tenantID + "\x00" + strconv.FormatInt(generation, 10),
))
return hex.EncodeToString(digest[:])
}
// Purge performs an idempotent application-layer deletion of one tenant's
// live Relay directory and every backup directory. It refuses links and
// special files rather than following them. Storage-provider block erasure is
// outside this primitive and must be covered by the infrastructure policy.
func Purge(ctx context.Context, dataRoot, backupRoot, tenantID string, generation int64) (Result, error) {
if generation < 1 {
return Result{}, errors.New("invalid purge generation")
}
paths, err := tenantfs.Derive(dataRoot, tenantID)
if err != nil {
return Result{}, err
}
dataParent := filepath.Dir(paths.Root)
backupRootAbsolute, err := filepath.Abs(strings.TrimSpace(backupRoot))
if err != nil || strings.TrimSpace(backupRoot) == "" {
return Result{}, errors.New("invalid backup root")
}
backupTenantRoot := filepath.Join(backupRootAbsolute, filepath.Base(paths.Root))
dataDeleted, err := removeTree(ctx, dataParent, paths.Root)
if err != nil {
return Result{}, fmt.Errorf("delete tenant Relay data: %w", err)
}
backupsDeleted, err := removeTree(ctx, backupRootAbsolute, backupTenantRoot)
if err != nil {
return Result{}, fmt.Errorf("delete tenant Relay backups: %w", err)
}
return Result{
DataDeleted: dataDeleted, BackupsDeleted: backupsDeleted,
EvidenceSHA256: evidence(tenantID, generation),
}, nil
}