go-io/docs/RFC.md
Virgil cc2b553c94
Some checks failed
CI / auto-merge (push) Failing after 0s
CI / auto-fix (push) Failing after 0s
CI / test (push) Failing after 2s
docs(ax): align RFC API reference with current surfaces
2026-03-31 06:26:16 +00:00

49 KiB

title description
API Reference Complete API reference for go-io.

API Reference

This document enumerates every exported type, function, method, and variable in go-io, with short usage examples.

Examples use the import paths from docs/index.md (forge.lthn.ai/core/go-io). Adjust paths if your module path differs.

Package io (forge.lthn.ai/core/go-io)

Defines the Medium interface, helper functions, and in-memory MemoryMedium implementation.

Medium (interface)

The common storage abstraction implemented by every backend.

Example:

var m io.Medium = io.NewMemoryMedium()
_ = m.Write("notes.txt", "hello")

Read(path string) (string, error) Reads a file as a string. Example:

m := io.NewMemoryMedium()
_ = m.Write("notes.txt", "hello")
value, _ := m.Read("notes.txt")

Write(path, content string) error Writes content to a file, creating it if needed. Example:

m := io.NewMemoryMedium()
_ = m.Write("notes.txt", "hello")

WriteMode(path, content string, mode fs.FileMode) error Writes content with explicit permissions. Example:

m := io.NewMemoryMedium()
_ = m.WriteMode("secret.txt", "secret", 0600)

EnsureDir(path string) error Ensures a directory exists. Example:

m := io.NewMemoryMedium()
_ = m.EnsureDir("config")

IsFile(path string) bool Reports whether a path is a regular file. Example:

m := io.NewMemoryMedium()
_ = m.Write("notes.txt", "hello")
ok := m.IsFile("notes.txt")

Read(path string) (string, error) Alias for Read. Example:

m := io.NewMemoryMedium()
_ = m.Write("notes.txt", "hello")
value, _ := m.Read("notes.txt")

Write(path, content string) error Alias for Write. Example:

m := io.NewMemoryMedium()
_ = m.Write("notes.txt", "hello")

Delete(path string) error Deletes a file or empty directory. Example:

m := io.NewMemoryMedium()
_ = m.Write("old.txt", "data")
_ = m.Delete("old.txt")

DeleteAll(path string) error Deletes a file or directory tree recursively. Example:

m := io.NewMemoryMedium()
_ = m.Write("logs/run.txt", "started")
_ = m.DeleteAll("logs")

Rename(oldPath, newPath string) error Moves or renames a file or directory. Example:

m := io.NewMemoryMedium()
_ = m.Write("old.txt", "data")
_ = m.Rename("old.txt", "new.txt")

List(path string) ([]fs.DirEntry, error) Lists immediate directory entries. Example:

m := io.NewMemoryMedium()
_ = m.Write("dir/file.txt", "data")
entries, _ := m.List("dir")

Stat(path string) (fs.FileInfo, error) Returns file metadata. Example:

m := io.NewMemoryMedium()
_ = m.Write("notes.txt", "hello")
info, _ := m.Stat("notes.txt")

Open(path string) (fs.File, error) Opens a file for reading. Example:

m := io.NewMemoryMedium()
_ = m.Write("notes.txt", "hello")
f, _ := m.Open("notes.txt")
defer f.Close()

Create(path string) (io.WriteCloser, error) Creates or truncates a file and returns a writer. Example:

m := io.NewMemoryMedium()
w, _ := m.Create("notes.txt")
_, _ = w.Write([]byte("hello"))
_ = w.Close()

Append(path string) (io.WriteCloser, error) Opens a file for appending, creating it if needed. Example:

m := io.NewMemoryMedium()
_ = m.Write("notes.txt", "hello")
w, _ := m.Append("notes.txt")
_, _ = w.Write([]byte(" world"))
_ = w.Close()

ReadStream(path string) (io.ReadCloser, error) Opens a streaming reader for a file. Example:

m := io.NewMemoryMedium()
_ = m.Write("notes.txt", "hello")
r, _ := m.ReadStream("notes.txt")
defer r.Close()

WriteStream(path string) (io.WriteCloser, error) Opens a streaming writer for a file. Example:

m := io.NewMemoryMedium()
w, _ := m.WriteStream("notes.txt")
_, _ = w.Write([]byte("hello"))
_ = w.Close()

Exists(path string) bool Reports whether a path exists. Example:

m := io.NewMemoryMedium()
_ = m.Write("notes.txt", "hello")
ok := m.Exists("notes.txt")

IsDir(path string) bool Reports whether a path is a directory. Example:

m := io.NewMemoryMedium()
_ = m.EnsureDir("config")
ok := m.IsDir("config")

FileInfo

Lightweight fs.FileInfo implementation used by MemoryMedium.

Name() string Example:

m := io.NewMemoryMedium()
_ = m.Write("file.txt", "data")
info, _ := m.Stat("file.txt")
_ = info.Name()

Size() int64 Example:

m := io.NewMemoryMedium()
_ = m.Write("file.txt", "data")
info, _ := m.Stat("file.txt")
_ = info.Size()

Mode() fs.FileMode Example:

m := io.NewMemoryMedium()
_ = m.Write("file.txt", "data")
info, _ := m.Stat("file.txt")
_ = info.Mode()

ModTime() time.Time Example:

m := io.NewMemoryMedium()
_ = m.Write("file.txt", "data")
info, _ := m.Stat("file.txt")
_ = info.ModTime()

IsDir() bool Example:

m := io.NewMemoryMedium()
_ = m.Write("file.txt", "data")
info, _ := m.Stat("file.txt")
_ = info.IsDir()

Sys() any Example:

m := io.NewMemoryMedium()
_ = m.Write("file.txt", "data")
info, _ := m.Stat("file.txt")
_ = info.Sys()

DirEntry

Lightweight fs.DirEntry implementation used by MemoryMedium listings.

Name() string Example:

m := io.NewMemoryMedium()
_ = m.Write("dir/file.txt", "data")
entries, _ := m.List("dir")
_ = entries[0].Name()

IsDir() bool Example:

m := io.NewMemoryMedium()
_ = m.EnsureDir("dir")
entries, _ := m.List("")
_ = entries[0].IsDir()

Type() fs.FileMode Example:

m := io.NewMemoryMedium()
_ = m.Write("dir/file.txt", "data")
entries, _ := m.List("dir")
_ = entries[0].Type()

Info() (fs.FileInfo, error) Example:

m := io.NewMemoryMedium()
_ = m.Write("dir/file.txt", "data")
entries, _ := m.List("dir")
info, _ := entries[0].Info()
_ = info.Name()

Local

Pre-initialised local filesystem medium rooted at /.

Example:

content, _ := io.Local.Read("/etc/hostname")

NewSandboxed(root string) (Medium, error)

Creates a local filesystem medium sandboxed to root.

Example:

m, _ := io.NewSandboxed("/srv/app")
_ = m.Write("config/app.yaml", "port: 8080")

Read(m Medium, path string) (string, error)

Helper that calls Medium.Read on a supplied backend.

Example:

m := io.NewMemoryMedium()
_ = m.Write("notes.txt", "hello")
value, _ := io.Read(m, "notes.txt")

Write(m Medium, path, content string) error

Helper that calls Medium.Write on a supplied backend.

Example:

m := io.NewMemoryMedium()
_ = io.Write(m, "notes.txt", "hello")

ReadStream(m Medium, path string) (io.ReadCloser, error)

Helper that calls Medium.ReadStream on a supplied backend.

Example:

m := io.NewMemoryMedium()
_ = m.Write("notes.txt", "hello")
r, _ := io.ReadStream(m, "notes.txt")
defer r.Close()

WriteStream(m Medium, path string) (io.WriteCloser, error)

Helper that calls Medium.WriteStream on a supplied backend.

Example:

m := io.NewMemoryMedium()
w, _ := io.WriteStream(m, "notes.txt")
_, _ = w.Write([]byte("hello"))
_ = w.Close()

EnsureDir(m Medium, path string) error

Helper that calls Medium.EnsureDir on a supplied backend.

Example:

m := io.NewMemoryMedium()
_ = io.EnsureDir(m, "config")

IsFile(m Medium, path string) bool

Helper that calls Medium.IsFile on a supplied backend.

Example:

m := io.NewMemoryMedium()
_ = m.Write("notes.txt", "hello")
ok := io.IsFile(m, "notes.txt")

Copy(src Medium, srcPath string, dst Medium, dstPath string) error

Copies a file between two mediums.

Example:

src := io.NewMemoryMedium()
dst := io.NewMemoryMedium()
_ = src.Write("source.txt", "data")
_ = io.Copy(src, "source.txt", dst, "dest.txt")

MemoryMedium

In-memory Medium implementation for tests.

Example:

m := io.NewMemoryMedium()
_ = m.Write("seed.txt", "seeded")

Read(path string) (string, error) Example:

m := io.NewMemoryMedium()
_ = m.Write("notes.txt", "hello")
value, _ := m.Read("notes.txt")

Write(path, content string) error Example:

m := io.NewMemoryMedium()
_ = m.Write("notes.txt", "hello")

WriteMode(path, content string, mode fs.FileMode) error Example:

m := io.NewMemoryMedium()
_ = m.WriteMode("secret.txt", "secret", 0600)

EnsureDir(path string) error Example:

m := io.NewMemoryMedium()
_ = m.EnsureDir("config")

IsFile(path string) bool Example:

m := io.NewMemoryMedium()
_ = m.Write("notes.txt", "hello")
ok := m.IsFile("notes.txt")

Read(path string) (string, error) Example:

m := io.NewMemoryMedium()
_ = m.Write("notes.txt", "hello")
value, _ := m.Read("notes.txt")

Write(path, content string) error Example:

m := io.NewMemoryMedium()
_ = m.Write("notes.txt", "hello")

Delete(path string) error Example:

m := io.NewMemoryMedium()
_ = m.Write("old.txt", "data")
_ = m.Delete("old.txt")

DeleteAll(path string) error Example:

m := io.NewMemoryMedium()
_ = m.Write("logs/run.txt", "started")
_ = m.DeleteAll("logs")

Rename(oldPath, newPath string) error Example:

m := io.NewMemoryMedium()
_ = m.Write("old.txt", "data")
_ = m.Rename("old.txt", "new.txt")

List(path string) ([]fs.DirEntry, error) Example:

m := io.NewMemoryMedium()
_ = m.Write("dir/file.txt", "data")
entries, _ := m.List("dir")

Stat(path string) (fs.FileInfo, error) Example:

m := io.NewMemoryMedium()
_ = m.Write("notes.txt", "hello")
info, _ := m.Stat("notes.txt")

Open(path string) (fs.File, error) Example:

m := io.NewMemoryMedium()
_ = m.Write("notes.txt", "hello")
f, _ := m.Open("notes.txt")
defer f.Close()

Create(path string) (io.WriteCloser, error) Example:

m := io.NewMemoryMedium()
w, _ := m.Create("notes.txt")
_, _ = w.Write([]byte("hello"))
_ = w.Close()

Append(path string) (io.WriteCloser, error) Example:

m := io.NewMemoryMedium()
_ = m.Write("notes.txt", "hello")
w, _ := m.Append("notes.txt")
_, _ = w.Write([]byte(" world"))
_ = w.Close()

ReadStream(path string) (io.ReadCloser, error) Example:

m := io.NewMemoryMedium()
_ = m.Write("notes.txt", "hello")
r, _ := m.ReadStream("notes.txt")
defer r.Close()

WriteStream(path string) (io.WriteCloser, error) Example:

m := io.NewMemoryMedium()
w, _ := m.WriteStream("notes.txt")
_, _ = w.Write([]byte("hello"))
_ = w.Close()

Exists(path string) bool Example:

m := io.NewMemoryMedium()
_ = m.Write("notes.txt", "hello")
ok := m.Exists("notes.txt")

IsDir(path string) bool Example:

m := io.NewMemoryMedium()
_ = m.EnsureDir("config")
ok := m.IsDir("config")

NewMemoryMedium() *MemoryMedium

Creates a new empty in-memory medium.

Example:

m := io.NewMemoryMedium()
_ = m.Write("notes.txt", "hello")

MemoryFile

fs.File implementation returned by MemoryMedium.Open.

Stat() (fs.FileInfo, error) Example:

m := io.NewMemoryMedium()
_ = m.Write("notes.txt", "hello")
f, _ := m.Open("notes.txt")
info, _ := f.Stat()
_ = info.Name()

Read(b []byte) (int, error) Example:

m := io.NewMemoryMedium()
_ = m.Write("notes.txt", "hello")
f, _ := m.Open("notes.txt")
buf := make([]byte, 5)
_, _ = f.Read(buf)

Close() error Example:

m := io.NewMemoryMedium()
_ = m.Write("notes.txt", "hello")
f, _ := m.Open("notes.txt")
_ = f.Close()

MemoryWriteCloser

io.WriteCloser implementation returned by MemoryMedium.Create and MemoryMedium.Append.

Write(p []byte) (int, error) Example:

m := io.NewMemoryMedium()
w, _ := m.Create("notes.txt")
_, _ = w.Write([]byte("hello"))

Close() error Example:

m := io.NewMemoryMedium()
w, _ := m.Create("notes.txt")
_, _ = w.Write([]byte("hello"))
_ = w.Close()

Package local (forge.lthn.ai/core/go-io/local)

Local filesystem backend with sandboxed roots and symlink-escape protection.

New(root string) (*Medium, error)

Creates a new local filesystem medium rooted at root.

Example:

m, _ := local.New("/srv/app")
_ = m.Write("config/app.yaml", "port: 8080")

Medium

Local filesystem implementation of io.Medium.

Example:

m, _ := local.New("/srv/app")
_ = m.EnsureDir("config")

Read(path string) (string, error) Example:

m, _ := local.New("/srv/app")
_ = m.Write("notes.txt", "hello")
value, _ := m.Read("notes.txt")

Write(path, content string) error Example:

m, _ := local.New("/srv/app")
_ = m.Write("notes.txt", "hello")

WriteMode(path, content string, mode fs.FileMode) error Example:

m, _ := local.New("/srv/app")
_ = m.WriteMode("secret.txt", "secret", 0600)

EnsureDir(path string) error Example:

m, _ := local.New("/srv/app")
_ = m.EnsureDir("config")

IsDir(path string) bool Example:

m, _ := local.New("/srv/app")
_ = m.EnsureDir("config")
ok := m.IsDir("config")

IsFile(path string) bool Example:

m, _ := local.New("/srv/app")
_ = m.Write("notes.txt", "hello")
ok := m.IsFile("notes.txt")

Exists(path string) bool Example:

m, _ := local.New("/srv/app")
_ = m.Write("notes.txt", "hello")
ok := m.Exists("notes.txt")

List(path string) ([]fs.DirEntry, error) Example:

m, _ := local.New("/srv/app")
_ = m.Write("dir/file.txt", "data")
entries, _ := m.List("dir")

Stat(path string) (fs.FileInfo, error) Example:

m, _ := local.New("/srv/app")
_ = m.Write("notes.txt", "hello")
info, _ := m.Stat("notes.txt")

Open(path string) (fs.File, error) Example:

m, _ := local.New("/srv/app")
_ = m.Write("notes.txt", "hello")
f, _ := m.Open("notes.txt")
defer f.Close()

Create(path string) (io.WriteCloser, error) Example:

m, _ := local.New("/srv/app")
w, _ := m.Create("notes.txt")
_, _ = w.Write([]byte("hello"))
_ = w.Close()

Append(path string) (io.WriteCloser, error) Example:

m, _ := local.New("/srv/app")
_ = m.Write("notes.txt", "hello")
w, _ := m.Append("notes.txt")
_, _ = w.Write([]byte(" world"))
_ = w.Close()

ReadStream(path string) (io.ReadCloser, error) Example:

m, _ := local.New("/srv/app")
_ = m.Write("notes.txt", "hello")
r, _ := m.ReadStream("notes.txt")
defer r.Close()

WriteStream(path string) (io.WriteCloser, error) Example:

m, _ := local.New("/srv/app")
w, _ := m.WriteStream("notes.txt")
_, _ = w.Write([]byte("hello"))
_ = w.Close()

Delete(path string) error Example:

m, _ := local.New("/srv/app")
_ = m.Write("old.txt", "data")
_ = m.Delete("old.txt")

DeleteAll(path string) error Example:

m, _ := local.New("/srv/app")
_ = m.Write("logs/run.txt", "started")
_ = m.DeleteAll("logs")

Rename(oldPath, newPath string) error Example:

m, _ := local.New("/srv/app")
_ = m.Write("old.txt", "data")
_ = m.Rename("old.txt", "new.txt")

Read(path string) (string, error) Example:

m, _ := local.New("/srv/app")
_ = m.Write("notes.txt", "hello")
value, _ := m.Read("notes.txt")

Write(path, content string) error Example:

m, _ := local.New("/srv/app")
_ = m.Write("notes.txt", "hello")

Package node (forge.lthn.ai/core/go-io/node)

In-memory filesystem implementing io.Medium and fs.FS, with tar serialisation.

New() *Node

Creates a new empty in-memory filesystem.

Example:

n := node.New()

FromTar(data []byte) (*Node, error)

Creates a new Node by loading a tar archive.

Example:

tarball := []byte{}
n, _ := node.FromTar(tarball)

WalkOptions

Options for Node.Walk.

Example:

options := node.WalkOptions{MaxDepth: 1, SkipErrors: true}
_ = options.MaxDepth

Node

In-memory filesystem with implicit directories and tar support.

Example:

n := node.New()
n.AddData("config/app.yaml", []byte("port: 8080"))

AddData(name string, content []byte) Stages content in the in-memory filesystem. Example:

n := node.New()
n.AddData("config/app.yaml", []byte("port: 8080"))

ToTar() ([]byte, error) Serialises the tree to a tar archive. Example:

n := node.New()
_ = n.Write("a.txt", "alpha")
blob, _ := n.ToTar()

LoadTar(data []byte) error Replaces the tree with a tar archive. Example:

n := node.New()
_ = n.LoadTar([]byte{})

Walk(root string, fn fs.WalkDirFunc, options WalkOptions) error Walks the tree with optional depth or filter controls. Example:

n := node.New()
options := node.WalkOptions{MaxDepth: 1, SkipErrors: true}
_ = n.Walk(".", func(path string, d fs.DirEntry, err error) error {
	return nil
}, options)

ReadFile(name string) ([]byte, error) Reads file content as bytes. Example:

n := node.New()
_ = n.Write("file.txt", "data")
b, _ := n.ReadFile("file.txt")

CopyFile(sourcePath, destinationPath string, perm fs.FileMode) error Copies a file to the local filesystem. Example:

n := node.New()
_ = n.Write("file.txt", "data")
_ = n.CopyFile("file.txt", "/tmp/file.txt", 0644)

CopyTo(target io.Medium, sourcePath, destPath string) error Copies a file or directory tree to another medium. Example:

n := node.New()
_ = n.Write("config/app.yaml", "port: 8080")
copyTarget := io.NewMemoryMedium()
_ = n.CopyTo(copyTarget, "config", "backup/config")

Open(name string) (fs.File, error) Opens a file for reading. Example:

n := node.New()
_ = n.Write("file.txt", "data")
f, _ := n.Open("file.txt")
defer f.Close()

Stat(name string) (fs.FileInfo, error) Returns metadata for a file or directory. Example:

n := node.New()
_ = n.Write("file.txt", "data")
info, _ := n.Stat("file.txt")

ReadDir(name string) ([]fs.DirEntry, error) Lists directory entries. Example:

n := node.New()
_ = n.Write("dir/file.txt", "data")
entries, _ := n.ReadDir("dir")

Read(p string) (string, error) Reads content as a string. Example:

n := node.New()
_ = n.Write("file.txt", "data")
value, _ := n.Read("file.txt")

Write(p, content string) error Writes content to a file. Example:

n := node.New()
_ = n.Write("file.txt", "data")

WriteMode(p, content string, mode fs.FileMode) error Writes content with explicit permissions (no-op in memory). Example:

n := node.New()
_ = n.WriteMode("file.txt", "data", 0600)

Read(p string) (string, error) Alias for Read. Example:

n := node.New()
_ = n.Write("file.txt", "data")
value, _ := n.Read("file.txt")

Write(p, content string) error Alias for Write. Example:

n := node.New()
_ = n.Write("file.txt", "data")

EnsureDir(path string) error No-op (directories are implicit). Example:

n := node.New()
_ = n.EnsureDir("dir")

Exists(p string) bool Reports whether a path exists. Example:

n := node.New()
_ = n.Write("file.txt", "data")
ok := n.Exists("file.txt")

IsFile(p string) bool Reports whether a path is a file. Example:

n := node.New()
_ = n.Write("file.txt", "data")
ok := n.IsFile("file.txt")

IsDir(p string) bool Reports whether a path is a directory. Example:

n := node.New()
_ = n.Write("dir/file.txt", "data")
ok := n.IsDir("dir")

Delete(p string) error Deletes a file. Example:

n := node.New()
_ = n.Write("old.txt", "data")
_ = n.Delete("old.txt")

DeleteAll(p string) error Deletes a file or directory tree. Example:

n := node.New()
_ = n.Write("logs/run.txt", "started")
_ = n.DeleteAll("logs")

Rename(oldPath, newPath string) error Moves a file within the node. Example:

n := node.New()
_ = n.Write("old.txt", "data")
_ = n.Rename("old.txt", "new.txt")

List(p string) ([]fs.DirEntry, error) Lists directory entries. Example:

n := node.New()
_ = n.Write("dir/file.txt", "data")
entries, _ := n.List("dir")

Create(p string) (io.WriteCloser, error) Creates or truncates a file and returns a writer. Example:

n := node.New()
w, _ := n.Create("file.txt")
_, _ = w.Write([]byte("data"))
_ = w.Close()

Append(p string) (io.WriteCloser, error) Appends to a file and returns a writer. Example:

n := node.New()
_ = n.Write("file.txt", "data")
w, _ := n.Append("file.txt")
_, _ = w.Write([]byte(" more"))
_ = w.Close()

ReadStream(p string) (io.ReadCloser, error) Opens a streaming reader. Example:

n := node.New()
_ = n.Write("file.txt", "data")
r, _ := n.ReadStream("file.txt")
defer r.Close()

WriteStream(p string) (io.WriteCloser, error) Opens a streaming writer. Example:

n := node.New()
w, _ := n.WriteStream("file.txt")
_, _ = w.Write([]byte("data"))
_ = w.Close()

Package store (forge.lthn.ai/core/go-io/store)

Group-namespaced key-value store backed by SQLite, plus a Medium adapter.

NotFoundError

Returned when a key does not exist.

Example:

s, _ := store.New(store.Options{Path: ":memory:"})
_, err := s.Get("config", "missing")
if core.Is(err, store.NotFoundError) {
	// handle missing key
}

Options

Configures the SQLite database path used by the store.

Example:

options := store.Options{Path: ":memory:"}
_ = options

New(options Options) (*Store, error)

Creates a new Store backed by the configured SQLite path.

Example:

s, _ := store.New(store.Options{Path: ":memory:"})
_ = s.Set("config", "theme", "midnight")

Store

Group-namespaced key-value store.

Example:

s, _ := store.New(store.Options{Path: ":memory:"})
_ = s.Set("config", "theme", "midnight")

Close() error Example:

s, _ := store.New(store.Options{Path: ":memory:"})
_ = s.Close()

Get(group, key string) (string, error) Example:

s, _ := store.New(store.Options{Path: ":memory:"})
_ = s.Set("config", "theme", "midnight")
value, _ := s.Get("config", "theme")

Set(group, key, value string) error Example:

s, _ := store.New(store.Options{Path: ":memory:"})
_ = s.Set("config", "theme", "midnight")

Delete(group, key string) error Example:

s, _ := store.New(store.Options{Path: ":memory:"})
_ = s.Set("config", "theme", "midnight")
_ = s.Delete("config", "theme")

Count(group string) (int, error) Example:

s, _ := store.New(store.Options{Path: ":memory:"})
_ = s.Set("config", "theme", "midnight")
count, _ := s.Count("config")

DeleteGroup(group string) error Example:

s, _ := store.New(store.Options{Path: ":memory:"})
_ = s.Set("config", "theme", "midnight")
_ = s.DeleteGroup("config")

GetAll(group string) (map[string]string, error) Example:

s, _ := store.New(store.Options{Path: ":memory:"})
_ = s.Set("config", "theme", "midnight")
all, _ := s.GetAll("config")

Render(tmplStr, group string) (string, error) Example:

s, _ := store.New(store.Options{Path: ":memory:"})
_ = s.Set("user", "name", "alice")
out, _ := s.Render("hello {{ .name }}", "user")

*AsMedium() Medium Example:

s, _ := store.New(store.Options{Path: ":memory:"})
m := s.AsMedium()
_ = m.Write("config/theme", "midnight")

NewMedium(options Options) (*Medium, error)

Creates an io.Medium backed by a SQLite key-value store.

Example:

m, _ := store.NewMedium(store.Options{Path: "config.db"})
_ = m.Write("config/theme", "midnight")

Medium

Adapter that maps group/key paths onto a Store.

Example:

m, _ := store.NewMedium(store.Options{Path: ":memory:"})
_ = m.Write("config/theme", "midnight")

*Store() Store Example:

m, _ := store.NewMedium(store.Options{Path: ":memory:"})
s := m.Store()
_ = s.Set("config", "theme", "midnight")

Close() error Example:

m, _ := store.NewMedium(store.Options{Path: ":memory:"})
_ = m.Close()

Read(p string) (string, error) Example:

m, _ := store.NewMedium(store.Options{Path: ":memory:"})
_ = m.Write("config/theme", "midnight")
value, _ := m.Read("config/theme")

Write(p, content string) error Example:

m, _ := store.NewMedium(store.Options{Path: ":memory:"})
_ = m.Write("config/theme", "midnight")

EnsureDir(path string) error No-op (groups are implicit). Example:

m, _ := store.NewMedium(store.Options{Path: ":memory:"})
_ = m.EnsureDir("config")

IsFile(p string) bool Example:

m, _ := store.NewMedium(store.Options{Path: ":memory:"})
_ = m.Write("config/theme", "midnight")
ok := m.IsFile("config/theme")

Read(p string) (string, error) Example:

m, _ := store.NewMedium(store.Options{Path: ":memory:"})
_ = m.Write("config/theme", "midnight")
value, _ := m.Read("config/theme")

Write(p, content string) error Example:

m, _ := store.NewMedium(store.Options{Path: ":memory:"})
_ = m.Write("config/theme", "midnight")

Delete(p string) error Example:

m, _ := store.NewMedium(store.Options{Path: ":memory:"})
_ = m.Write("config/theme", "midnight")
_ = m.Delete("config/theme")

DeleteAll(p string) error Example:

m, _ := store.NewMedium(store.Options{Path: ":memory:"})
_ = m.Write("config/theme", "midnight")
_ = m.DeleteAll("config")

Rename(oldPath, newPath string) error Example:

m, _ := store.NewMedium(store.Options{Path: ":memory:"})
_ = m.Write("old/theme", "midnight")
_ = m.Rename("old/theme", "new/theme")

List(p string) ([]fs.DirEntry, error) Example:

m, _ := store.NewMedium(store.Options{Path: ":memory:"})
_ = m.Write("config/theme", "midnight")
entries, _ := m.List("")

Stat(p string) (fs.FileInfo, error) Example:

m, _ := store.NewMedium(store.Options{Path: ":memory:"})
_ = m.Write("config/theme", "midnight")
info, _ := m.Stat("config/theme")

Open(p string) (fs.File, error) Example:

m, _ := store.NewMedium(store.Options{Path: ":memory:"})
_ = m.Write("config/theme", "midnight")
f, _ := m.Open("config/theme")
defer f.Close()

Create(p string) (io.WriteCloser, error) Example:

m, _ := store.NewMedium(store.Options{Path: ":memory:"})
w, _ := m.Create("config/theme")
_, _ = w.Write([]byte("midnight"))
_ = w.Close()

Append(p string) (io.WriteCloser, error) Example:

m, _ := store.NewMedium(store.Options{Path: ":memory:"})
_ = m.Write("config/theme", "midnight")
w, _ := m.Append("config/theme")
_, _ = w.Write([]byte(" plus"))
_ = w.Close()

ReadStream(p string) (io.ReadCloser, error) Example:

m, _ := store.NewMedium(store.Options{Path: ":memory:"})
_ = m.Write("config/theme", "midnight")
r, _ := m.ReadStream("config/theme")
defer r.Close()

WriteStream(p string) (io.WriteCloser, error) Example:

m, _ := store.NewMedium(store.Options{Path: ":memory:"})
w, _ := m.WriteStream("config/theme")
_, _ = w.Write([]byte("midnight"))
_ = w.Close()

Exists(p string) bool Example:

m, _ := store.NewMedium(store.Options{Path: ":memory:"})
_ = m.Write("config/theme", "midnight")
ok := m.Exists("config")

IsDir(p string) bool Example:

m, _ := store.NewMedium(store.Options{Path: ":memory:"})
_ = m.Write("config/theme", "midnight")
ok := m.IsDir("config")

Package sqlite (forge.lthn.ai/core/go-io/sqlite)

SQLite-backed io.Medium implementation using the pure-Go driver.

Options

Configures the SQLite database path and optional table name.

Example:

options := sqlite.Options{Path: ":memory:", Table: "files"}
_ = options

New(options Options) (*Medium, error)

Creates a new SQLite-backed medium.

Example:

m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.Write("notes.txt", "hello")

Medium

SQLite-backed storage backend.

Example:

m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.Write("notes.txt", "hello")

Close() error Example:

m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.Close()

Read(p string) (string, error) Example:

m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.Write("notes.txt", "hello")
value, _ := m.Read("notes.txt")

Write(p, content string) error Example:

m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.Write("notes.txt", "hello")

EnsureDir(p string) error Example:

m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.EnsureDir("config")

IsFile(p string) bool Example:

m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.Write("notes.txt", "hello")
ok := m.IsFile("notes.txt")

Read(p string) (string, error) Example:

m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.Write("notes.txt", "hello")
value, _ := m.Read("notes.txt")

Write(p, content string) error Example:

m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.Write("notes.txt", "hello")

Delete(p string) error Example:

m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.Write("old.txt", "data")
_ = m.Delete("old.txt")

DeleteAll(p string) error Example:

m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.Write("logs/run.txt", "started")
_ = m.DeleteAll("logs")

Rename(oldPath, newPath string) error Example:

m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.Write("old.txt", "data")
_ = m.Rename("old.txt", "new.txt")

List(p string) ([]fs.DirEntry, error) Example:

m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.Write("dir/file.txt", "data")
entries, _ := m.List("dir")

Stat(p string) (fs.FileInfo, error) Example:

m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.Write("notes.txt", "hello")
info, _ := m.Stat("notes.txt")

Open(p string) (fs.File, error) Example:

m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.Write("notes.txt", "hello")
f, _ := m.Open("notes.txt")
defer f.Close()

Create(p string) (io.WriteCloser, error) Example:

m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
w, _ := m.Create("notes.txt")
_, _ = w.Write([]byte("hello"))
_ = w.Close()

Append(p string) (io.WriteCloser, error) Example:

m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.Write("notes.txt", "hello")
w, _ := m.Append("notes.txt")
_, _ = w.Write([]byte(" world"))
_ = w.Close()

ReadStream(p string) (io.ReadCloser, error) Example:

m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.Write("notes.txt", "hello")
r, _ := m.ReadStream("notes.txt")
defer r.Close()

WriteStream(p string) (io.WriteCloser, error) Example:

m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
w, _ := m.WriteStream("notes.txt")
_, _ = w.Write([]byte("hello"))
_ = w.Close()

Exists(p string) bool Example:

m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.Write("notes.txt", "hello")
ok := m.Exists("notes.txt")

IsDir(p string) bool Example:

m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.EnsureDir("config")
ok := m.IsDir("config")

Package s3 (forge.lthn.ai/core/go-io/s3)

Amazon S3-backed io.Medium implementation.

Options

Configures the bucket, client, and optional key prefix.

Example:

client := awss3.NewFromConfig(aws.Config{Region: "us-east-1"})
options := s3.Options{Bucket: "bucket", Client: client, Prefix: "daily/"}
_ = options

Client

Supplies an AWS SDK S3 client.

Example:

client := awss3.NewFromConfig(aws.Config{Region: "us-east-1"})
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})

New(options Options) (*Medium, error)

Creates a new S3-backed medium.

Example:

client := awss3.NewFromConfig(aws.Config{Region: "us-east-1"})
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})

Medium

S3-backed storage backend.

Example:

client := awss3.NewFromConfig(aws.Config{Region: "us-east-1"})
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})

Read(p string) (string, error) Example:

client := awss3.NewFromConfig(aws.Config{Region: "us-east-1"})
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
value, _ := m.Read("notes.txt")

Write(p, content string) error Example:

client := awss3.NewFromConfig(aws.Config{Region: "us-east-1"})
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
_ = m.Write("notes.txt", "hello")

EnsureDir(path string) error No-op (S3 has no directories). Example:

client := awss3.NewFromConfig(aws.Config{Region: "us-east-1"})
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
_ = m.EnsureDir("config")

IsFile(p string) bool Example:

client := awss3.NewFromConfig(aws.Config{Region: "us-east-1"})
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
ok := m.IsFile("notes.txt")

Read(p string) (string, error) Example:

client := awss3.NewFromConfig(aws.Config{Region: "us-east-1"})
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
value, _ := m.Read("notes.txt")

Write(p, content string) error Example:

client := awss3.NewFromConfig(aws.Config{Region: "us-east-1"})
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
_ = m.Write("notes.txt", "hello")

Delete(p string) error Example:

client := awss3.NewFromConfig(aws.Config{Region: "us-east-1"})
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
_ = m.Delete("old.txt")

DeleteAll(p string) error Example:

client := awss3.NewFromConfig(aws.Config{Region: "us-east-1"})
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
_ = m.DeleteAll("logs")

Rename(oldPath, newPath string) error Example:

client := awss3.NewFromConfig(aws.Config{Region: "us-east-1"})
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
_ = m.Rename("old.txt", "new.txt")

List(p string) ([]fs.DirEntry, error) Example:

client := awss3.NewFromConfig(aws.Config{Region: "us-east-1"})
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
entries, _ := m.List("dir")

Stat(p string) (fs.FileInfo, error) Example:

client := awss3.NewFromConfig(aws.Config{Region: "us-east-1"})
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
info, _ := m.Stat("notes.txt")

Open(p string) (fs.File, error) Example:

client := awss3.NewFromConfig(aws.Config{Region: "us-east-1"})
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
f, _ := m.Open("notes.txt")
defer f.Close()

Create(p string) (io.WriteCloser, error) Example:

client := awss3.NewFromConfig(aws.Config{Region: "us-east-1"})
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
w, _ := m.Create("notes.txt")
_, _ = w.Write([]byte("hello"))
_ = w.Close()

Append(p string) (io.WriteCloser, error) Example:

client := awss3.NewFromConfig(aws.Config{Region: "us-east-1"})
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
w, _ := m.Append("notes.txt")
_, _ = w.Write([]byte(" world"))
_ = w.Close()

ReadStream(p string) (io.ReadCloser, error) Example:

client := awss3.NewFromConfig(aws.Config{Region: "us-east-1"})
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
r, _ := m.ReadStream("notes.txt")
defer r.Close()

WriteStream(p string) (io.WriteCloser, error) Example:

client := awss3.NewFromConfig(aws.Config{Region: "us-east-1"})
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
w, _ := m.WriteStream("notes.txt")
_, _ = w.Write([]byte("hello"))
_ = w.Close()

Exists(p string) bool Example:

client := awss3.NewFromConfig(aws.Config{Region: "us-east-1"})
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
ok := m.Exists("notes.txt")

IsDir(p string) bool Example:

client := awss3.NewFromConfig(aws.Config{Region: "us-east-1"})
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
ok := m.IsDir("logs")

Package datanode (forge.lthn.ai/core/go-io/datanode)

In-memory io.Medium backed by Borg's DataNode, with tar snapshot/restore support.

New() *Medium

Creates a new empty DataNode-backed medium.

Example:

m := datanode.New()
_ = m.Write("jobs/run.log", "started")

FromTar(data []byte) (*Medium, error)

Restores a medium from a tar archive.

Example:

m, _ := datanode.FromTar([]byte{})

Medium

Thread-safe in-memory medium using Borg DataNode.

Example:

m := datanode.New()
_ = m.Write("jobs/run.log", "started")

Snapshot() ([]byte, error) Serialises the filesystem to a tarball. Example:

m := datanode.New()
_ = m.Write("jobs/run.log", "started")
snap, _ := m.Snapshot()

Restore(data []byte) error Replaces the filesystem from a tarball. Example:

m := datanode.New()
_ = m.Restore([]byte{})

*DataNode() datanode.DataNode Returns the underlying Borg DataNode. Example:

m := datanode.New()
dn := m.DataNode()
_ = dn

Read(p string) (string, error) Example:

m := datanode.New()
_ = m.Write("notes.txt", "hello")
value, _ := m.Read("notes.txt")

Write(p, content string) error Example:

m := datanode.New()
_ = m.Write("notes.txt", "hello")

WriteMode(p, content string, mode fs.FileMode) error Example:

m := datanode.New()
_ = m.WriteMode("notes.txt", "hello", 0600)

EnsureDir(p string) error Example:

m := datanode.New()
_ = m.EnsureDir("config")

IsFile(p string) bool Example:

m := datanode.New()
_ = m.Write("notes.txt", "hello")
ok := m.IsFile("notes.txt")

Read(p string) (string, error) Example:

m := datanode.New()
_ = m.Write("notes.txt", "hello")
value, _ := m.Read("notes.txt")

Write(p, content string) error Example:

m := datanode.New()
_ = m.Write("notes.txt", "hello")

Delete(p string) error Example:

m := datanode.New()
_ = m.Write("old.txt", "data")
_ = m.Delete("old.txt")

DeleteAll(p string) error Example:

m := datanode.New()
_ = m.Write("logs/run.txt", "started")
_ = m.DeleteAll("logs")

Rename(oldPath, newPath string) error Example:

m := datanode.New()
_ = m.Write("old.txt", "data")
_ = m.Rename("old.txt", "new.txt")

List(p string) ([]fs.DirEntry, error) Example:

m := datanode.New()
_ = m.Write("dir/file.txt", "data")
entries, _ := m.List("dir")

Stat(p string) (fs.FileInfo, error) Example:

m := datanode.New()
_ = m.Write("notes.txt", "hello")
info, _ := m.Stat("notes.txt")

Open(p string) (fs.File, error) Example:

m := datanode.New()
_ = m.Write("notes.txt", "hello")
f, _ := m.Open("notes.txt")
defer f.Close()

Create(p string) (io.WriteCloser, error) Example:

m := datanode.New()
w, _ := m.Create("notes.txt")
_, _ = w.Write([]byte("hello"))
_ = w.Close()

Append(p string) (io.WriteCloser, error) Example:

m := datanode.New()
_ = m.Write("notes.txt", "hello")
w, _ := m.Append("notes.txt")
_, _ = w.Write([]byte(" world"))
_ = w.Close()

ReadStream(p string) (io.ReadCloser, error) Example:

m := datanode.New()
_ = m.Write("notes.txt", "hello")
r, _ := m.ReadStream("notes.txt")
defer r.Close()

WriteStream(p string) (io.WriteCloser, error) Example:

m := datanode.New()
w, _ := m.WriteStream("notes.txt")
_, _ = w.Write([]byte("hello"))
_ = w.Close()

Exists(p string) bool Example:

m := datanode.New()
_ = m.Write("notes.txt", "hello")
ok := m.Exists("notes.txt")

IsDir(p string) bool Example:

m := datanode.New()
_ = m.EnsureDir("config")
ok := m.IsDir("config")

Package workspace (forge.lthn.ai/core/go-io/workspace)

Encrypted user workspace management.

Workspace (interface)

Creates and operates on encrypted workspaces through a service.

Example:

service, _ := workspace.New(workspace.Options{KeyPairProvider: stubKeyPairProvider{}})
_ = service

KeyPairProvider

Creates key pairs for workspace provisioning.

Example:

keyPairProvider := stubKeyPairProvider{}
keyPair, _ := keyPairProvider.CreateKeyPair("alice", "pass123")
_ = keyPair

WorkspaceCreateAction

Action value used to create a workspace.

Example:

command := workspace.WorkspaceCommand{Action: workspace.WorkspaceCreateAction, Identifier: "alice", Password: "pass123"}
_ = command

WorkspaceSwitchAction

Action value used to switch to an existing workspace.

Example:

command := workspace.WorkspaceCommand{Action: workspace.WorkspaceSwitchAction, WorkspaceID: "f3f0d7"}
_ = command

WorkspaceCommand

Command envelope consumed by the service.

Example:

command := workspace.WorkspaceCommand{Action: workspace.WorkspaceCreateAction, Identifier: "alice", Password: "pass123"}
_ = command

Options

Configures the workspace service.

Example:

service, _ := workspace.New(workspace.Options{KeyPairProvider: stubKeyPairProvider{}})
_ = service

New(options Options) (*Service, error)

Creates a new workspace service.

Example:

type stubKeyPairProvider struct{}

func (stubKeyPairProvider) CreateKeyPair(name, passphrase string) (string, error) {
	return "key", nil
}

service, _ := workspace.New(workspace.Options{KeyPairProvider: stubKeyPairProvider{}})
_ = service

Service

Implements Workspace and handles Core messages.

Example:

service, _ := workspace.New(workspace.Options{KeyPairProvider: stubKeyPairProvider{}})
_ = service

CreateWorkspace(identifier, password string) (string, error) Example:

service, _ := workspace.New(workspace.Options{KeyPairProvider: stubKeyPairProvider{}})
workspaceID, _ := service.CreateWorkspace("alice", "pass123")
_ = workspaceID

SwitchWorkspace(workspaceID string) error Example:

service, _ := workspace.New(workspace.Options{KeyPairProvider: stubKeyPairProvider{}})
_ = service.SwitchWorkspace("f3f0d7")

ReadWorkspaceFile(workspaceFilePath string) (string, error) Example:

service, _ := workspace.New(workspace.Options{KeyPairProvider: stubKeyPairProvider{}})
content, _ := service.ReadWorkspaceFile("notes/todo.txt")
_ = content

WriteWorkspaceFile(workspaceFilePath, content string) error Example:

service, _ := workspace.New(workspace.Options{KeyPairProvider: stubKeyPairProvider{}})
_ = service.WriteWorkspaceFile("notes/todo.txt", "ship it")

HandleWorkspaceCommand(command WorkspaceCommand) core.Result Example:

service, _ := workspace.New(workspace.Options{KeyPairProvider: stubKeyPairProvider{}})
result := service.HandleWorkspaceCommand(workspace.WorkspaceCommand{Action: workspace.WorkspaceCreateAction, Identifier: "alice", Password: "pass123"})
_ = result.OK

*HandleWorkspaceMessage(_ core.Core, message core.Message) core.Result Example:

service, _ := workspace.New(workspace.Options{KeyPairProvider: stubKeyPairProvider{}})
result := service.HandleWorkspaceMessage(core.New(), workspace.WorkspaceCommand{Action: workspace.WorkspaceSwitchAction, WorkspaceID: "f3f0d7"})
_ = result.OK

Package sigil (forge.lthn.ai/core/go-io/sigil)

Composable data-transformation sigils for encoding, compression, hashing, and encryption.

Sigil (interface)

Defines the transformation contract.

Example:

var s sigil.Sigil = &sigil.HexSigil{}
out, _ := s.In([]byte("hello"))
_ = out

In(data []byte) ([]byte, error) Applies the forward transformation. Example:

s := &sigil.HexSigil{}
encoded, _ := s.In([]byte("hello"))

Out(data []byte) ([]byte, error) Applies the reverse transformation. Example:

s := &sigil.HexSigil{}
encoded, _ := s.In([]byte("hello"))
decoded, _ := s.Out(encoded)

Transmute(data []byte, sigils []Sigil) ([]byte, error)

Applies In across a chain of sigils.

Example:

hexSigil, _ := sigil.NewSigil("hex")
base64Sigil, _ := sigil.NewSigil("base64")
encoded, _ := sigil.Transmute([]byte("hello"), []sigil.Sigil{hexSigil, base64Sigil})

Untransmute(data []byte, sigils []Sigil) ([]byte, error)

Reverses a transmutation by applying Out in reverse order.

Example:

hexSigil, _ := sigil.NewSigil("hex")
base64Sigil, _ := sigil.NewSigil("base64")
encoded, _ := sigil.Transmute([]byte("hello"), []sigil.Sigil{hexSigil, base64Sigil})
plain, _ := sigil.Untransmute(encoded, []sigil.Sigil{hexSigil, base64Sigil})

ReverseSigil

Reverses byte order (symmetric).

Example:

s := &sigil.ReverseSigil{}

In(data []byte) ([]byte, error) Example:

s := &sigil.ReverseSigil{}
reversed, _ := s.In([]byte("hello"))

Out(data []byte) ([]byte, error) Example:

s := &sigil.ReverseSigil{}
reversed, _ := s.In([]byte("hello"))
restored, _ := s.Out(reversed)

HexSigil

Encodes/decodes hexadecimal.

Example:

s := &sigil.HexSigil{}

In(data []byte) ([]byte, error) Example:

s := &sigil.HexSigil{}
encoded, _ := s.In([]byte("hello"))

Out(data []byte) ([]byte, error) Example:

s := &sigil.HexSigil{}
encoded, _ := s.In([]byte("hello"))
decoded, _ := s.Out(encoded)

Base64Sigil

Encodes/decodes base64.

Example:

s := &sigil.Base64Sigil{}

In(data []byte) ([]byte, error) Example:

s := &sigil.Base64Sigil{}
encoded, _ := s.In([]byte("hello"))

Out(data []byte) ([]byte, error) Example:

s := &sigil.Base64Sigil{}
encoded, _ := s.In([]byte("hello"))
decoded, _ := s.Out(encoded)

GzipSigil

Compresses/decompresses gzip payloads.

Example:

s := &sigil.GzipSigil{}

In(data []byte) ([]byte, error) Example:

s := &sigil.GzipSigil{}
compressed, _ := s.In([]byte("hello"))

Out(data []byte) ([]byte, error) Example:

s := &sigil.GzipSigil{}
compressed, _ := s.In([]byte("hello"))
plain, _ := s.Out(compressed)

JSONSigil

Compacts or indents JSON (depending on Indent).

Example:

s := &sigil.JSONSigil{Indent: true}

In(data []byte) ([]byte, error) Example:

s := &sigil.JSONSigil{Indent: false}
compacted, _ := s.In([]byte(`{"key":"value"}`))

Out(data []byte) ([]byte, error) No-op for JSONSigil. Example:

s := &sigil.JSONSigil{Indent: false}
pass, _ := s.Out([]byte(`{"key":"value"}`))

HashSigil

Hashes input using the configured crypto.Hash.

Example:

s := sigil.NewHashSigil(crypto.SHA256)

In(data []byte) ([]byte, error) Example:

s := sigil.NewHashSigil(crypto.SHA256)
digest, _ := s.In([]byte("hello"))

Out(data []byte) ([]byte, error) No-op for hash sigils. Example:

s := sigil.NewHashSigil(crypto.SHA256)
digest, _ := s.In([]byte("hello"))
pass, _ := s.Out(digest)

NewHashSigil(h crypto.Hash) *HashSigil

Creates a new HashSigil.

Example:

s := sigil.NewHashSigil(crypto.SHA256)

NewSigil(name string) (Sigil, error)

Factory for built-in sigils.

Example:

s, _ := sigil.NewSigil("hex")

ErrInvalidKey

Returned when an encryption key is not 32 bytes.

Example:

_, err := sigil.NewChaChaPolySigil([]byte("short"))
if errors.Is(err, sigil.ErrInvalidKey) {
	// handle invalid key
}

ErrCiphertextTooShort

Returned when ciphertext is too short to decrypt.

Example:

_, err := sigil.GetNonceFromCiphertext([]byte("short"))
if errors.Is(err, sigil.ErrCiphertextTooShort) {
	// handle truncated payload
}

ErrDecryptionFailed

Returned when decryption or authentication fails.

Example:

key := make([]byte, 32)
s, _ := sigil.NewChaChaPolySigil(key)
_, err := s.Out([]byte("tampered"))
if errors.Is(err, sigil.ErrDecryptionFailed) {
	// handle failed decrypt
}

ErrNoKeyConfigured

Returned when a ChaChaPolySigil has no key.

Example:

s := &sigil.ChaChaPolySigil{}
_, err := s.In([]byte("data"))
if errors.Is(err, sigil.ErrNoKeyConfigured) {
	// handle missing key
}

PreObfuscator (interface)

Defines pre-obfuscation hooks for encryption sigils.

Example:

var ob sigil.PreObfuscator = &sigil.XORObfuscator{}
_ = ob

Obfuscate(data []byte, entropy []byte) []byte Example:

ob := &sigil.XORObfuscator{}
masked := ob.Obfuscate([]byte("hello"), []byte("nonce"))

Deobfuscate(data []byte, entropy []byte) []byte Example:

ob := &sigil.XORObfuscator{}
masked := ob.Obfuscate([]byte("hello"), []byte("nonce"))
plain := ob.Deobfuscate(masked, []byte("nonce"))

XORObfuscator

XOR-based pre-obfuscator.

Example:

ob := &sigil.XORObfuscator{}

Obfuscate(data []byte, entropy []byte) []byte Example:

ob := &sigil.XORObfuscator{}
masked := ob.Obfuscate([]byte("hello"), []byte("nonce"))

Deobfuscate(data []byte, entropy []byte) []byte Example:

ob := &sigil.XORObfuscator{}
masked := ob.Obfuscate([]byte("hello"), []byte("nonce"))
plain := ob.Deobfuscate(masked, []byte("nonce"))

ShuffleMaskObfuscator

Shuffle + mask pre-obfuscator.

Example:

ob := &sigil.ShuffleMaskObfuscator{}

Obfuscate(data []byte, entropy []byte) []byte Example:

ob := &sigil.ShuffleMaskObfuscator{}
masked := ob.Obfuscate([]byte("hello"), []byte("nonce"))

Deobfuscate(data []byte, entropy []byte) []byte Example:

ob := &sigil.ShuffleMaskObfuscator{}
masked := ob.Obfuscate([]byte("hello"), []byte("nonce"))
plain := ob.Deobfuscate(masked, []byte("nonce"))

ChaChaPolySigil

XChaCha20-Poly1305 encryption sigil with optional pre-obfuscation.

Example:

key := make([]byte, 32)
s, _ := sigil.NewChaChaPolySigil(key)

In(data []byte) ([]byte, error) Example:

key := make([]byte, 32)
s, _ := sigil.NewChaChaPolySigil(key)
ciphertext, _ := s.In([]byte("hello"))

Out(data []byte) ([]byte, error) Example:

key := make([]byte, 32)
s, _ := sigil.NewChaChaPolySigil(key)
ciphertext, _ := s.In([]byte("hello"))
plain, _ := s.Out(ciphertext)

NewChaChaPolySigil(key []byte) (*ChaChaPolySigil, error)

Creates an encryption sigil with the default XOR obfuscator.

Example:

key := make([]byte, 32)
s, _ := sigil.NewChaChaPolySigil(key)

NewChaChaPolySigilWithObfuscator(key []byte, obfuscator PreObfuscator) (*ChaChaPolySigil, error)

Creates an encryption sigil with a custom obfuscator.

Example:

key := make([]byte, 32)
ob := &sigil.ShuffleMaskObfuscator{}
s, _ := sigil.NewChaChaPolySigilWithObfuscator(key, ob)

GetNonceFromCiphertext(ciphertext []byte) ([]byte, error)

Extracts the XChaCha20 nonce from encrypted output.

Example:

key := make([]byte, 32)
s, _ := sigil.NewChaChaPolySigil(key)
ciphertext, _ := s.In([]byte("hello"))
nonce, _ := sigil.GetNonceFromCiphertext(ciphertext)