go-io/docs/RFC.md

2521 lines
48 KiB
Markdown

---
title: API Reference
description: 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 mock implementations.
### Medium (interface)
The common storage abstraction implemented by every backend.
Example:
```go
var m io.Medium = io.NewMockMedium()
_ = m.Write("notes.txt", "hello")
```
**Read(path string) (string, error)**
Reads a file as a string.
Example:
```go
m := io.NewMockMedium()
_ = 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:
```go
m := io.NewMockMedium()
_ = m.Write("notes.txt", "hello")
```
**WriteMode(path, content string, mode fs.FileMode) error**
Writes content with explicit permissions.
Example:
```go
m := io.NewMockMedium()
_ = m.WriteMode("secret.txt", "secret", 0600)
```
**EnsureDir(path string) error**
Ensures a directory exists.
Example:
```go
m := io.NewMockMedium()
_ = m.EnsureDir("config")
```
**IsFile(path string) bool**
Reports whether a path is a regular file.
Example:
```go
m := io.NewMockMedium()
_ = m.Write("notes.txt", "hello")
ok := m.IsFile("notes.txt")
```
**FileGet(path string) (string, error)**
Alias for `Read`.
Example:
```go
m := io.NewMockMedium()
_ = m.FileSet("notes.txt", "hello")
value, _ := m.FileGet("notes.txt")
```
**FileSet(path, content string) error**
Alias for `Write`.
Example:
```go
m := io.NewMockMedium()
_ = m.FileSet("notes.txt", "hello")
```
**Delete(path string) error**
Deletes a file or empty directory.
Example:
```go
m := io.NewMockMedium()
_ = m.Write("old.txt", "data")
_ = m.Delete("old.txt")
```
**DeleteAll(path string) error**
Deletes a file or directory tree recursively.
Example:
```go
m := io.NewMockMedium()
_ = m.Write("logs/run.txt", "started")
_ = m.DeleteAll("logs")
```
**Rename(oldPath, newPath string) error**
Moves or renames a file or directory.
Example:
```go
m := io.NewMockMedium()
_ = m.Write("old.txt", "data")
_ = m.Rename("old.txt", "new.txt")
```
**List(path string) ([]fs.DirEntry, error)**
Lists immediate directory entries.
Example:
```go
m := io.NewMockMedium()
_ = m.Write("dir/file.txt", "data")
entries, _ := m.List("dir")
```
**Stat(path string) (fs.FileInfo, error)**
Returns file metadata.
Example:
```go
m := io.NewMockMedium()
_ = m.Write("notes.txt", "hello")
info, _ := m.Stat("notes.txt")
```
**Open(path string) (fs.File, error)**
Opens a file for reading.
Example:
```go
m := io.NewMockMedium()
_ = 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:
```go
m := io.NewMockMedium()
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:
```go
m := io.NewMockMedium()
_ = 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:
```go
m := io.NewMockMedium()
_ = 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:
```go
m := io.NewMockMedium()
w, _ := m.WriteStream("notes.txt")
_, _ = w.Write([]byte("hello"))
_ = w.Close()
```
**Exists(path string) bool**
Reports whether a path exists.
Example:
```go
m := io.NewMockMedium()
_ = m.Write("notes.txt", "hello")
ok := m.Exists("notes.txt")
```
**IsDir(path string) bool**
Reports whether a path is a directory.
Example:
```go
m := io.NewMockMedium()
_ = m.EnsureDir("config")
ok := m.IsDir("config")
```
### FileInfo
Lightweight `fs.FileInfo` implementation used by `MockMedium`.
**Name() string**
Example:
```go
m := io.NewMockMedium()
_ = m.Write("file.txt", "data")
info, _ := m.Stat("file.txt")
_ = info.Name()
```
**Size() int64**
Example:
```go
m := io.NewMockMedium()
_ = m.Write("file.txt", "data")
info, _ := m.Stat("file.txt")
_ = info.Size()
```
**Mode() fs.FileMode**
Example:
```go
m := io.NewMockMedium()
_ = m.Write("file.txt", "data")
info, _ := m.Stat("file.txt")
_ = info.Mode()
```
**ModTime() time.Time**
Example:
```go
m := io.NewMockMedium()
_ = m.Write("file.txt", "data")
info, _ := m.Stat("file.txt")
_ = info.ModTime()
```
**IsDir() bool**
Example:
```go
m := io.NewMockMedium()
_ = m.Write("file.txt", "data")
info, _ := m.Stat("file.txt")
_ = info.IsDir()
```
**Sys() any**
Example:
```go
m := io.NewMockMedium()
_ = m.Write("file.txt", "data")
info, _ := m.Stat("file.txt")
_ = info.Sys()
```
### DirEntry
Lightweight `fs.DirEntry` implementation used by `MockMedium` listings.
**Name() string**
Example:
```go
m := io.NewMockMedium()
_ = m.Write("dir/file.txt", "data")
entries, _ := m.List("dir")
_ = entries[0].Name()
```
**IsDir() bool**
Example:
```go
m := io.NewMockMedium()
_ = m.EnsureDir("dir")
entries, _ := m.List("")
_ = entries[0].IsDir()
```
**Type() fs.FileMode**
Example:
```go
m := io.NewMockMedium()
_ = m.Write("dir/file.txt", "data")
entries, _ := m.List("dir")
_ = entries[0].Type()
```
**Info() (fs.FileInfo, error)**
Example:
```go
m := io.NewMockMedium()
_ = 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:
```go
content, _ := io.Local.Read("/etc/hostname")
```
### NewSandboxed(root string) (Medium, error)
Creates a local filesystem medium sandboxed to `root`.
Example:
```go
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:
```go
m := io.NewMockMedium()
_ = 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:
```go
m := io.NewMockMedium()
_ = io.Write(m, "notes.txt", "hello")
```
### ReadStream(m Medium, path string) (io.ReadCloser, error)
Helper that calls `Medium.ReadStream` on a supplied backend.
Example:
```go
m := io.NewMockMedium()
_ = 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:
```go
m := io.NewMockMedium()
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:
```go
m := io.NewMockMedium()
_ = io.EnsureDir(m, "config")
```
### IsFile(m Medium, path string) bool
Helper that calls `Medium.IsFile` on a supplied backend.
Example:
```go
m := io.NewMockMedium()
_ = 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:
```go
src := io.NewMockMedium()
dst := io.NewMockMedium()
_ = src.Write("source.txt", "data")
_ = io.Copy(src, "source.txt", dst, "dest.txt")
```
### MockMedium
In-memory `Medium` implementation for tests. Exposes `Files`, `Dirs`, and `ModTimes` maps for seeding state.
Example:
```go
m := io.NewMockMedium()
m.Files["seed.txt"] = "seeded"
```
**Read(path string) (string, error)**
Example:
```go
m := io.NewMockMedium()
m.Files["notes.txt"] = "hello"
value, _ := m.Read("notes.txt")
```
**Write(path, content string) error**
Example:
```go
m := io.NewMockMedium()
_ = m.Write("notes.txt", "hello")
```
**WriteMode(path, content string, mode fs.FileMode) error**
Example:
```go
m := io.NewMockMedium()
_ = m.WriteMode("secret.txt", "secret", 0600)
```
**EnsureDir(path string) error**
Example:
```go
m := io.NewMockMedium()
_ = m.EnsureDir("config")
```
**IsFile(path string) bool**
Example:
```go
m := io.NewMockMedium()
_ = m.Write("notes.txt", "hello")
ok := m.IsFile("notes.txt")
```
**FileGet(path string) (string, error)**
Example:
```go
m := io.NewMockMedium()
_ = m.FileSet("notes.txt", "hello")
value, _ := m.FileGet("notes.txt")
```
**FileSet(path, content string) error**
Example:
```go
m := io.NewMockMedium()
_ = m.FileSet("notes.txt", "hello")
```
**Delete(path string) error**
Example:
```go
m := io.NewMockMedium()
_ = m.Write("old.txt", "data")
_ = m.Delete("old.txt")
```
**DeleteAll(path string) error**
Example:
```go
m := io.NewMockMedium()
_ = m.Write("logs/run.txt", "started")
_ = m.DeleteAll("logs")
```
**Rename(oldPath, newPath string) error**
Example:
```go
m := io.NewMockMedium()
_ = m.Write("old.txt", "data")
_ = m.Rename("old.txt", "new.txt")
```
**List(path string) ([]fs.DirEntry, error)**
Example:
```go
m := io.NewMockMedium()
_ = m.Write("dir/file.txt", "data")
entries, _ := m.List("dir")
```
**Stat(path string) (fs.FileInfo, error)**
Example:
```go
m := io.NewMockMedium()
_ = m.Write("notes.txt", "hello")
info, _ := m.Stat("notes.txt")
```
**Open(path string) (fs.File, error)**
Example:
```go
m := io.NewMockMedium()
_ = m.Write("notes.txt", "hello")
f, _ := m.Open("notes.txt")
defer f.Close()
```
**Create(path string) (io.WriteCloser, error)**
Example:
```go
m := io.NewMockMedium()
w, _ := m.Create("notes.txt")
_, _ = w.Write([]byte("hello"))
_ = w.Close()
```
**Append(path string) (io.WriteCloser, error)**
Example:
```go
m := io.NewMockMedium()
_ = m.Write("notes.txt", "hello")
w, _ := m.Append("notes.txt")
_, _ = w.Write([]byte(" world"))
_ = w.Close()
```
**ReadStream(path string) (io.ReadCloser, error)**
Example:
```go
m := io.NewMockMedium()
_ = m.Write("notes.txt", "hello")
r, _ := m.ReadStream("notes.txt")
defer r.Close()
```
**WriteStream(path string) (io.WriteCloser, error)**
Example:
```go
m := io.NewMockMedium()
w, _ := m.WriteStream("notes.txt")
_, _ = w.Write([]byte("hello"))
_ = w.Close()
```
**Exists(path string) bool**
Example:
```go
m := io.NewMockMedium()
_ = m.Write("notes.txt", "hello")
ok := m.Exists("notes.txt")
```
**IsDir(path string) bool**
Example:
```go
m := io.NewMockMedium()
_ = m.EnsureDir("config")
ok := m.IsDir("config")
```
### NewMockMedium() *MockMedium
Creates a new empty in-memory medium.
Example:
```go
m := io.NewMockMedium()
_ = m.Write("notes.txt", "hello")
```
### MockFile
`fs.File` implementation returned by `MockMedium.Open`.
**Stat() (fs.FileInfo, error)**
Example:
```go
m := io.NewMockMedium()
_ = m.Write("notes.txt", "hello")
f, _ := m.Open("notes.txt")
info, _ := f.Stat()
_ = info.Name()
```
**Read(b []byte) (int, error)**
Example:
```go
m := io.NewMockMedium()
_ = m.Write("notes.txt", "hello")
f, _ := m.Open("notes.txt")
buf := make([]byte, 5)
_, _ = f.Read(buf)
```
**Close() error**
Example:
```go
m := io.NewMockMedium()
_ = m.Write("notes.txt", "hello")
f, _ := m.Open("notes.txt")
_ = f.Close()
```
### MockWriteCloser
`io.WriteCloser` implementation returned by `MockMedium.Create` and `MockMedium.Append`.
**Write(p []byte) (int, error)**
Example:
```go
m := io.NewMockMedium()
w, _ := m.Create("notes.txt")
_, _ = w.Write([]byte("hello"))
```
**Close() error**
Example:
```go
m := io.NewMockMedium()
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:
```go
m, _ := local.New("/srv/app")
_ = m.Write("config/app.yaml", "port: 8080")
```
### Medium
Local filesystem implementation of `io.Medium`.
Example:
```go
m, _ := local.New("/srv/app")
_ = m.EnsureDir("config")
```
**Read(path string) (string, error)**
Example:
```go
m, _ := local.New("/srv/app")
_ = m.Write("notes.txt", "hello")
value, _ := m.Read("notes.txt")
```
**Write(path, content string) error**
Example:
```go
m, _ := local.New("/srv/app")
_ = m.Write("notes.txt", "hello")
```
**WriteMode(path, content string, mode fs.FileMode) error**
Example:
```go
m, _ := local.New("/srv/app")
_ = m.WriteMode("secret.txt", "secret", 0600)
```
**EnsureDir(path string) error**
Example:
```go
m, _ := local.New("/srv/app")
_ = m.EnsureDir("config")
```
**IsDir(path string) bool**
Example:
```go
m, _ := local.New("/srv/app")
_ = m.EnsureDir("config")
ok := m.IsDir("config")
```
**IsFile(path string) bool**
Example:
```go
m, _ := local.New("/srv/app")
_ = m.Write("notes.txt", "hello")
ok := m.IsFile("notes.txt")
```
**Exists(path string) bool**
Example:
```go
m, _ := local.New("/srv/app")
_ = m.Write("notes.txt", "hello")
ok := m.Exists("notes.txt")
```
**List(path string) ([]fs.DirEntry, error)**
Example:
```go
m, _ := local.New("/srv/app")
_ = m.Write("dir/file.txt", "data")
entries, _ := m.List("dir")
```
**Stat(path string) (fs.FileInfo, error)**
Example:
```go
m, _ := local.New("/srv/app")
_ = m.Write("notes.txt", "hello")
info, _ := m.Stat("notes.txt")
```
**Open(path string) (fs.File, error)**
Example:
```go
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:
```go
m, _ := local.New("/srv/app")
w, _ := m.Create("notes.txt")
_, _ = w.Write([]byte("hello"))
_ = w.Close()
```
**Append(path string) (io.WriteCloser, error)**
Example:
```go
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:
```go
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:
```go
m, _ := local.New("/srv/app")
w, _ := m.WriteStream("notes.txt")
_, _ = w.Write([]byte("hello"))
_ = w.Close()
```
**Delete(path string) error**
Example:
```go
m, _ := local.New("/srv/app")
_ = m.Write("old.txt", "data")
_ = m.Delete("old.txt")
```
**DeleteAll(path string) error**
Example:
```go
m, _ := local.New("/srv/app")
_ = m.Write("logs/run.txt", "started")
_ = m.DeleteAll("logs")
```
**Rename(oldPath, newPath string) error**
Example:
```go
m, _ := local.New("/srv/app")
_ = m.Write("old.txt", "data")
_ = m.Rename("old.txt", "new.txt")
```
**FileGet(path string) (string, error)**
Example:
```go
m, _ := local.New("/srv/app")
_ = m.FileSet("notes.txt", "hello")
value, _ := m.FileGet("notes.txt")
```
**FileSet(path, content string) error**
Example:
```go
m, _ := local.New("/srv/app")
_ = m.FileSet("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:
```go
n := node.New()
```
### FromTar(data []byte) (*Node, error)
Creates a new `Node` by loading a tar archive.
Example:
```go
tarball := []byte{}
n, _ := node.FromTar(tarball)
```
### WalkOptions
Options for `Node.Walk`.
Example:
```go
opts := node.WalkOptions{MaxDepth: 1, SkipErrors: true}
_ = opts.MaxDepth
```
### Node
In-memory filesystem with implicit directories and tar support.
Example:
```go
n := node.New()
n.AddData("config/app.yaml", []byte("port: 8080"))
```
**AddData(name string, content []byte)**
Stages content in the in-memory filesystem.
Example:
```go
n := node.New()
n.AddData("config/app.yaml", []byte("port: 8080"))
```
**ToTar() ([]byte, error)**
Serialises the tree to a tar archive.
Example:
```go
n := node.New()
_ = n.Write("a.txt", "alpha")
blob, _ := n.ToTar()
```
**LoadTar(data []byte) error**
Replaces the tree with a tar archive.
Example:
```go
n := node.New()
_ = n.LoadTar([]byte{})
```
**WalkNode(root string, fn fs.WalkDirFunc) error**
Walks the tree using `fs.WalkDir`.
Example:
```go
n := node.New()
_ = n.WalkNode(".", func(path string, d fs.DirEntry, err error) error {
return nil
})
```
**Walk(root string, fn fs.WalkDirFunc, opts ...WalkOptions) error**
Walks the tree with optional depth or filter controls.
Example:
```go
n := node.New()
_ = n.Walk(".", func(path string, d fs.DirEntry, err error) error {
return nil
}, node.WalkOptions{MaxDepth: 1})
```
**ReadFile(name string) ([]byte, error)**
Reads file content as bytes.
Example:
```go
n := node.New()
_ = n.Write("file.txt", "data")
b, _ := n.ReadFile("file.txt")
```
**CopyFile(src, dst string, perm fs.FileMode) error**
Copies a file to the local filesystem.
Example:
```go
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:
```go
n := node.New()
_ = n.Write("config/app.yaml", "port: 8080")
copyTarget := io.NewMockMedium()
_ = n.CopyTo(copyTarget, "config", "backup/config")
```
**Open(name string) (fs.File, error)**
Opens a file for reading.
Example:
```go
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:
```go
n := node.New()
_ = n.Write("file.txt", "data")
info, _ := n.Stat("file.txt")
```
**ReadDir(name string) ([]fs.DirEntry, error)**
Lists directory entries.
Example:
```go
n := node.New()
_ = n.Write("dir/file.txt", "data")
entries, _ := n.ReadDir("dir")
```
**Read(p string) (string, error)**
Reads content as a string.
Example:
```go
n := node.New()
_ = n.Write("file.txt", "data")
value, _ := n.Read("file.txt")
```
**Write(p, content string) error**
Writes content to a file.
Example:
```go
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:
```go
n := node.New()
_ = n.WriteMode("file.txt", "data", 0600)
```
**FileGet(p string) (string, error)**
Alias for `Read`.
Example:
```go
n := node.New()
_ = n.FileSet("file.txt", "data")
value, _ := n.FileGet("file.txt")
```
**FileSet(p, content string) error**
Alias for `Write`.
Example:
```go
n := node.New()
_ = n.FileSet("file.txt", "data")
```
**EnsureDir(path string) error**
No-op (directories are implicit).
Example:
```go
n := node.New()
_ = n.EnsureDir("dir")
```
**Exists(p string) bool**
Reports whether a path exists.
Example:
```go
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:
```go
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:
```go
n := node.New()
_ = n.Write("dir/file.txt", "data")
ok := n.IsDir("dir")
```
**Delete(p string) error**
Deletes a file.
Example:
```go
n := node.New()
_ = n.Write("old.txt", "data")
_ = n.Delete("old.txt")
```
**DeleteAll(p string) error**
Deletes a file or directory tree.
Example:
```go
n := node.New()
_ = n.Write("logs/run.txt", "started")
_ = n.DeleteAll("logs")
```
**Rename(oldPath, newPath string) error**
Moves a file within the node.
Example:
```go
n := node.New()
_ = n.Write("old.txt", "data")
_ = n.Rename("old.txt", "new.txt")
```
**List(p string) ([]fs.DirEntry, error)**
Lists directory entries.
Example:
```go
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:
```go
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:
```go
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:
```go
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:
```go
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.
### ErrNotFound
Returned when a key does not exist.
Example:
```go
s, _ := store.New(":memory:")
_, err := s.Get("config", "missing")
if core.Is(err, store.ErrNotFound) {
// handle missing key
}
```
### New(dbPath string) (*Store, error)
Creates a new `Store` at the SQLite path.
Example:
```go
s, _ := store.New(":memory:")
_ = s.Set("config", "theme", "midnight")
```
### Store
Group-namespaced key-value store.
Example:
```go
s, _ := store.New(":memory:")
_ = s.Set("config", "theme", "midnight")
```
**Close() error**
Example:
```go
s, _ := store.New(":memory:")
_ = s.Close()
```
**Get(group, key string) (string, error)**
Example:
```go
s, _ := store.New(":memory:")
_ = s.Set("config", "theme", "midnight")
value, _ := s.Get("config", "theme")
```
**Set(group, key, value string) error**
Example:
```go
s, _ := store.New(":memory:")
_ = s.Set("config", "theme", "midnight")
```
**Delete(group, key string) error**
Example:
```go
s, _ := store.New(":memory:")
_ = s.Set("config", "theme", "midnight")
_ = s.Delete("config", "theme")
```
**Count(group string) (int, error)**
Example:
```go
s, _ := store.New(":memory:")
_ = s.Set("config", "theme", "midnight")
count, _ := s.Count("config")
```
**DeleteGroup(group string) error**
Example:
```go
s, _ := store.New(":memory:")
_ = s.Set("config", "theme", "midnight")
_ = s.DeleteGroup("config")
```
**GetAll(group string) (map[string]string, error)**
Example:
```go
s, _ := store.New(":memory:")
_ = s.Set("config", "theme", "midnight")
all, _ := s.GetAll("config")
```
**Render(tmplStr, group string) (string, error)**
Example:
```go
s, _ := store.New(":memory:")
_ = s.Set("user", "name", "alice")
out, _ := s.Render("hello {{ .name }}", "user")
```
**AsMedium() *Medium**
Example:
```go
s, _ := store.New(":memory:")
m := s.AsMedium()
_ = m.Write("config/theme", "midnight")
```
### NewMedium(dbPath string) (*Medium, error)
Creates an `io.Medium` backed by a SQLite key-value store.
Example:
```go
m, _ := store.NewMedium("config.db")
_ = m.Write("config/theme", "midnight")
```
### Medium
Adapter that maps `group/key` paths onto a `Store`.
Example:
```go
m, _ := store.NewMedium(":memory:")
_ = m.Write("config/theme", "midnight")
```
**Store() *Store**
Example:
```go
m, _ := store.NewMedium(":memory:")
s := m.Store()
_ = s.Set("config", "theme", "midnight")
```
**Close() error**
Example:
```go
m, _ := store.NewMedium(":memory:")
_ = m.Close()
```
**Read(p string) (string, error)**
Example:
```go
m, _ := store.NewMedium(":memory:")
_ = m.Write("config/theme", "midnight")
value, _ := m.Read("config/theme")
```
**Write(p, content string) error**
Example:
```go
m, _ := store.NewMedium(":memory:")
_ = m.Write("config/theme", "midnight")
```
**EnsureDir(path string) error**
No-op (groups are implicit).
Example:
```go
m, _ := store.NewMedium(":memory:")
_ = m.EnsureDir("config")
```
**IsFile(p string) bool**
Example:
```go
m, _ := store.NewMedium(":memory:")
_ = m.Write("config/theme", "midnight")
ok := m.IsFile("config/theme")
```
**FileGet(p string) (string, error)**
Example:
```go
m, _ := store.NewMedium(":memory:")
_ = m.FileSet("config/theme", "midnight")
value, _ := m.FileGet("config/theme")
```
**FileSet(p, content string) error**
Example:
```go
m, _ := store.NewMedium(":memory:")
_ = m.FileSet("config/theme", "midnight")
```
**Delete(p string) error**
Example:
```go
m, _ := store.NewMedium(":memory:")
_ = m.Write("config/theme", "midnight")
_ = m.Delete("config/theme")
```
**DeleteAll(p string) error**
Example:
```go
m, _ := store.NewMedium(":memory:")
_ = m.Write("config/theme", "midnight")
_ = m.DeleteAll("config")
```
**Rename(oldPath, newPath string) error**
Example:
```go
m, _ := store.NewMedium(":memory:")
_ = m.Write("old/theme", "midnight")
_ = m.Rename("old/theme", "new/theme")
```
**List(p string) ([]fs.DirEntry, error)**
Example:
```go
m, _ := store.NewMedium(":memory:")
_ = m.Write("config/theme", "midnight")
entries, _ := m.List("")
```
**Stat(p string) (fs.FileInfo, error)**
Example:
```go
m, _ := store.NewMedium(":memory:")
_ = m.Write("config/theme", "midnight")
info, _ := m.Stat("config/theme")
```
**Open(p string) (fs.File, error)**
Example:
```go
m, _ := store.NewMedium(":memory:")
_ = m.Write("config/theme", "midnight")
f, _ := m.Open("config/theme")
defer f.Close()
```
**Create(p string) (io.WriteCloser, error)**
Example:
```go
m, _ := store.NewMedium(":memory:")
w, _ := m.Create("config/theme")
_, _ = w.Write([]byte("midnight"))
_ = w.Close()
```
**Append(p string) (io.WriteCloser, error)**
Example:
```go
m, _ := store.NewMedium(":memory:")
_ = m.Write("config/theme", "midnight")
w, _ := m.Append("config/theme")
_, _ = w.Write([]byte(" plus"))
_ = w.Close()
```
**ReadStream(p string) (io.ReadCloser, error)**
Example:
```go
m, _ := store.NewMedium(":memory:")
_ = m.Write("config/theme", "midnight")
r, _ := m.ReadStream("config/theme")
defer r.Close()
```
**WriteStream(p string) (io.WriteCloser, error)**
Example:
```go
m, _ := store.NewMedium(":memory:")
w, _ := m.WriteStream("config/theme")
_, _ = w.Write([]byte("midnight"))
_ = w.Close()
```
**Exists(p string) bool**
Example:
```go
m, _ := store.NewMedium(":memory:")
_ = m.Write("config/theme", "midnight")
ok := m.Exists("config")
```
**IsDir(p string) bool**
Example:
```go
m, _ := store.NewMedium(":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.
### Option
Functional option for configuring `Medium`.
Example:
```go
opt := sqlite.Options{Path: ":memory:", Table: "files"}
_ = opt
```
### Options
Sets the table name used for storage (default: `files`).
Example:
```go
m, _ := sqlite.New(sqlite.Options{Path: ":memory:", Table: "files"})
```
### New(dbPath string, opts ...Option) (*Medium, error)
Creates a new SQLite-backed medium.
Example:
```go
m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.Write("notes.txt", "hello")
```
### Medium
SQLite-backed storage backend.
Example:
```go
m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.Write("notes.txt", "hello")
```
**Close() error**
Example:
```go
m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.Close()
```
**Read(p string) (string, error)**
Example:
```go
m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.Write("notes.txt", "hello")
value, _ := m.Read("notes.txt")
```
**Write(p, content string) error**
Example:
```go
m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.Write("notes.txt", "hello")
```
**EnsureDir(p string) error**
Example:
```go
m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.EnsureDir("config")
```
**IsFile(p string) bool**
Example:
```go
m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.Write("notes.txt", "hello")
ok := m.IsFile("notes.txt")
```
**FileGet(p string) (string, error)**
Example:
```go
m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.FileSet("notes.txt", "hello")
value, _ := m.FileGet("notes.txt")
```
**FileSet(p, content string) error**
Example:
```go
m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.FileSet("notes.txt", "hello")
```
**Delete(p string) error**
Example:
```go
m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.Write("old.txt", "data")
_ = m.Delete("old.txt")
```
**DeleteAll(p string) error**
Example:
```go
m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.Write("logs/run.txt", "started")
_ = m.DeleteAll("logs")
```
**Rename(oldPath, newPath string) error**
Example:
```go
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:
```go
m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.Write("dir/file.txt", "data")
entries, _ := m.List("dir")
```
**Stat(p string) (fs.FileInfo, error)**
Example:
```go
m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.Write("notes.txt", "hello")
info, _ := m.Stat("notes.txt")
```
**Open(p string) (fs.File, error)**
Example:
```go
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:
```go
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:
```go
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:
```go
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:
```go
m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
w, _ := m.WriteStream("notes.txt")
_, _ = w.Write([]byte("hello"))
_ = w.Close()
```
**Exists(p string) bool**
Example:
```go
m, _ := sqlite.New(sqlite.Options{Path: ":memory:"})
_ = m.Write("notes.txt", "hello")
ok := m.Exists("notes.txt")
```
**IsDir(p string) bool**
Example:
```go
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.
### Option
Functional option for configuring `Medium`.
Example:
```go
opt := s3.Options{Prefix: "daily/"}
_ = opt
```
### Options
Sets a key prefix for all operations.
Example:
```go
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: awsClient, Prefix: "daily/"})
```
### Client
Supplies an AWS SDK S3 client.
Example:
```go
client := awss3.NewFromConfig(cfg)
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
```
### New(bucket string, opts ...Option) (*Medium, error)
Creates a new S3-backed medium.
Example:
```go
client := awss3.NewFromConfig(cfg)
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
```
### Medium
S3-backed storage backend.
Example:
```go
client := awss3.NewFromConfig(cfg)
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
```
**Read(p string) (string, error)**
Example:
```go
client := awss3.NewFromConfig(cfg)
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
value, _ := m.Read("notes.txt")
```
**Write(p, content string) error**
Example:
```go
client := awss3.NewFromConfig(cfg)
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:
```go
client := awss3.NewFromConfig(cfg)
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
_ = m.EnsureDir("config")
```
**IsFile(p string) bool**
Example:
```go
client := awss3.NewFromConfig(cfg)
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
ok := m.IsFile("notes.txt")
```
**FileGet(p string) (string, error)**
Example:
```go
client := awss3.NewFromConfig(cfg)
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
value, _ := m.FileGet("notes.txt")
```
**FileSet(p, content string) error**
Example:
```go
client := awss3.NewFromConfig(cfg)
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
_ = m.FileSet("notes.txt", "hello")
```
**Delete(p string) error**
Example:
```go
client := awss3.NewFromConfig(cfg)
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
_ = m.Delete("old.txt")
```
**DeleteAll(p string) error**
Example:
```go
client := awss3.NewFromConfig(cfg)
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
_ = m.DeleteAll("logs")
```
**Rename(oldPath, newPath string) error**
Example:
```go
client := awss3.NewFromConfig(cfg)
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
_ = m.Rename("old.txt", "new.txt")
```
**List(p string) ([]fs.DirEntry, error)**
Example:
```go
client := awss3.NewFromConfig(cfg)
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
entries, _ := m.List("dir")
```
**Stat(p string) (fs.FileInfo, error)**
Example:
```go
client := awss3.NewFromConfig(cfg)
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
info, _ := m.Stat("notes.txt")
```
**Open(p string) (fs.File, error)**
Example:
```go
client := awss3.NewFromConfig(cfg)
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
f, _ := m.Open("notes.txt")
defer f.Close()
```
**Create(p string) (io.WriteCloser, error)**
Example:
```go
client := awss3.NewFromConfig(cfg)
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:
```go
client := awss3.NewFromConfig(cfg)
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:
```go
client := awss3.NewFromConfig(cfg)
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
r, _ := m.ReadStream("notes.txt")
defer r.Close()
```
**WriteStream(p string) (io.WriteCloser, error)**
Example:
```go
client := awss3.NewFromConfig(cfg)
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:
```go
client := awss3.NewFromConfig(cfg)
m, _ := s3.New(s3.Options{Bucket: "bucket", Client: client})
ok := m.Exists("notes.txt")
```
**IsDir(p string) bool**
Example:
```go
client := awss3.NewFromConfig(cfg)
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:
```go
m := datanode.New()
_ = m.Write("jobs/run.log", "started")
```
### FromTar(data []byte) (*Medium, error)
Restores a medium from a tar archive.
Example:
```go
m, _ := datanode.FromTar([]byte{})
```
### Medium
Thread-safe in-memory medium using Borg DataNode.
Example:
```go
m := datanode.New()
_ = m.Write("jobs/run.log", "started")
```
**Snapshot() ([]byte, error)**
Serialises the filesystem to a tarball.
Example:
```go
m := datanode.New()
_ = m.Write("jobs/run.log", "started")
snap, _ := m.Snapshot()
```
**Restore(data []byte) error**
Replaces the filesystem from a tarball.
Example:
```go
m := datanode.New()
_ = m.Restore([]byte{})
```
**DataNode() *datanode.DataNode**
Returns the underlying Borg DataNode.
Example:
```go
m := datanode.New()
dn := m.DataNode()
_ = dn
```
**Read(p string) (string, error)**
Example:
```go
m := datanode.New()
_ = m.Write("notes.txt", "hello")
value, _ := m.Read("notes.txt")
```
**Write(p, content string) error**
Example:
```go
m := datanode.New()
_ = m.Write("notes.txt", "hello")
```
**WriteMode(p, content string, mode fs.FileMode) error**
Example:
```go
m := datanode.New()
_ = m.WriteMode("notes.txt", "hello", 0600)
```
**EnsureDir(p string) error**
Example:
```go
m := datanode.New()
_ = m.EnsureDir("config")
```
**IsFile(p string) bool**
Example:
```go
m := datanode.New()
_ = m.Write("notes.txt", "hello")
ok := m.IsFile("notes.txt")
```
**FileGet(p string) (string, error)**
Example:
```go
m := datanode.New()
_ = m.FileSet("notes.txt", "hello")
value, _ := m.FileGet("notes.txt")
```
**FileSet(p, content string) error**
Example:
```go
m := datanode.New()
_ = m.FileSet("notes.txt", "hello")
```
**Delete(p string) error**
Example:
```go
m := datanode.New()
_ = m.Write("old.txt", "data")
_ = m.Delete("old.txt")
```
**DeleteAll(p string) error**
Example:
```go
m := datanode.New()
_ = m.Write("logs/run.txt", "started")
_ = m.DeleteAll("logs")
```
**Rename(oldPath, newPath string) error**
Example:
```go
m := datanode.New()
_ = m.Write("old.txt", "data")
_ = m.Rename("old.txt", "new.txt")
```
**List(p string) ([]fs.DirEntry, error)**
Example:
```go
m := datanode.New()
_ = m.Write("dir/file.txt", "data")
entries, _ := m.List("dir")
```
**Stat(p string) (fs.FileInfo, error)**
Example:
```go
m := datanode.New()
_ = m.Write("notes.txt", "hello")
info, _ := m.Stat("notes.txt")
```
**Open(p string) (fs.File, error)**
Example:
```go
m := datanode.New()
_ = m.Write("notes.txt", "hello")
f, _ := m.Open("notes.txt")
defer f.Close()
```
**Create(p string) (io.WriteCloser, error)**
Example:
```go
m := datanode.New()
w, _ := m.Create("notes.txt")
_, _ = w.Write([]byte("hello"))
_ = w.Close()
```
**Append(p string) (io.WriteCloser, error)**
Example:
```go
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:
```go
m := datanode.New()
_ = m.Write("notes.txt", "hello")
r, _ := m.ReadStream("notes.txt")
defer r.Close()
```
**WriteStream(p string) (io.WriteCloser, error)**
Example:
```go
m := datanode.New()
w, _ := m.WriteStream("notes.txt")
_, _ = w.Write([]byte("hello"))
_ = w.Close()
```
**Exists(p string) bool**
Example:
```go
m := datanode.New()
_ = m.Write("notes.txt", "hello")
ok := m.Exists("notes.txt")
```
**IsDir(p string) bool**
Example:
```go
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)
Defines the workspace operations exposed by the service.
Example:
```go
var ws workspace.Workspace = &workspace.Service{}
_ = ws
```
**CreateWorkspace(identifier, password string) (string, error)**
Example:
```go
svcAny, _ := workspace.New(workspace.Options{Core: core.New(), Crypt: stubCrypt{}})
svc := svcAny.(*workspace.Service)
wsID, _ := svc.CreateWorkspace("user", "pass")
```
**SwitchWorkspace(name string) error**
Example:
```go
svcAny, _ := workspace.New(workspace.Options{Core: core.New(), Crypt: stubCrypt{}})
svc := svcAny.(*workspace.Service)
_ = svc.SwitchWorkspace("workspace-id")
```
**WorkspaceFileGet(filename string) (string, error)**
Example:
```go
svcAny, _ := workspace.New(workspace.Options{Core: core.New(), Crypt: stubCrypt{}})
svc := svcAny.(*workspace.Service)
value, _ := svc.WorkspaceFileGet("notes.txt")
```
**WorkspaceFileSet(filename, content string) error**
Example:
```go
svcAny, _ := workspace.New(workspace.Options{Core: core.New(), Crypt: stubCrypt{}})
svc := svcAny.(*workspace.Service)
_ = svc.WorkspaceFileSet("notes.txt", "hello")
```
### New(options Options) (any, error)
Creates a new workspace service. Returns `*Service` as `any`.
Example:
```go
type stubCrypt struct{}
func (stubCrypt) CreateKeyPair(name, passphrase string) (string, error) { return "key", nil }
svcAny, _ := workspace.New(workspace.Options{Core: core.New(), Crypt: stubCrypt{}})
svc := svcAny.(*workspace.Service)
_ = svc
```
### Service
Implements `Workspace` and handles IPC messages.
Example:
```go
svcAny, _ := workspace.New(workspace.Options{Core: core.New(), Crypt: stubCrypt{}})
svc := svcAny.(*workspace.Service)
_ = svc
```
**CreateWorkspace(identifier, password string) (string, error)**
Example:
```go
svcAny, _ := workspace.New(workspace.Options{Core: core.New(), Crypt: stubCrypt{}})
svc := svcAny.(*workspace.Service)
wsID, _ := svc.CreateWorkspace("user", "pass")
```
**SwitchWorkspace(name string) error**
Example:
```go
svcAny, _ := workspace.New(workspace.Options{Core: core.New(), Crypt: stubCrypt{}})
svc := svcAny.(*workspace.Service)
_ = svc.SwitchWorkspace("workspace-id")
```
**WorkspaceFileGet(filename string) (string, error)**
Example:
```go
svcAny, _ := workspace.New(workspace.Options{Core: core.New(), Crypt: stubCrypt{}})
svc := svcAny.(*workspace.Service)
value, _ := svc.WorkspaceFileGet("notes.txt")
```
**WorkspaceFileSet(filename, content string) error**
Example:
```go
svcAny, _ := workspace.New(workspace.Options{Core: core.New(), Crypt: stubCrypt{}})
svc := svcAny.(*workspace.Service)
_ = svc.WorkspaceFileSet("notes.txt", "hello")
```
**HandleIPCEvents(c *core.Core, msg core.Message) core.Result**
Example:
```go
svcAny, _ := workspace.New(workspace.Options{Core: core.New(), Crypt: stubCrypt{}})
svc := svcAny.(*workspace.Service)
result := svc.HandleIPCEvents(core.New(), map[string]any{
"action": "workspace.create",
"identifier": "user",
"password": "pass",
})
_ = 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:
```go
var s sigil.Sigil = &sigil.HexSigil{}
out, _ := s.In([]byte("hello"))
_ = out
```
**In(data []byte) ([]byte, error)**
Applies the forward transformation.
Example:
```go
s := &sigil.HexSigil{}
encoded, _ := s.In([]byte("hello"))
```
**Out(data []byte) ([]byte, error)**
Applies the reverse transformation.
Example:
```go
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:
```go
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:
```go
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:
```go
s := &sigil.ReverseSigil{}
```
**In(data []byte) ([]byte, error)**
Example:
```go
s := &sigil.ReverseSigil{}
reversed, _ := s.In([]byte("hello"))
```
**Out(data []byte) ([]byte, error)**
Example:
```go
s := &sigil.ReverseSigil{}
reversed, _ := s.In([]byte("hello"))
restored, _ := s.Out(reversed)
```
### HexSigil
Encodes/decodes hexadecimal.
Example:
```go
s := &sigil.HexSigil{}
```
**In(data []byte) ([]byte, error)**
Example:
```go
s := &sigil.HexSigil{}
encoded, _ := s.In([]byte("hello"))
```
**Out(data []byte) ([]byte, error)**
Example:
```go
s := &sigil.HexSigil{}
encoded, _ := s.In([]byte("hello"))
decoded, _ := s.Out(encoded)
```
### Base64Sigil
Encodes/decodes base64.
Example:
```go
s := &sigil.Base64Sigil{}
```
**In(data []byte) ([]byte, error)**
Example:
```go
s := &sigil.Base64Sigil{}
encoded, _ := s.In([]byte("hello"))
```
**Out(data []byte) ([]byte, error)**
Example:
```go
s := &sigil.Base64Sigil{}
encoded, _ := s.In([]byte("hello"))
decoded, _ := s.Out(encoded)
```
### GzipSigil
Compresses/decompresses gzip payloads.
Example:
```go
s := &sigil.GzipSigil{}
```
**In(data []byte) ([]byte, error)**
Example:
```go
s := &sigil.GzipSigil{}
compressed, _ := s.In([]byte("hello"))
```
**Out(data []byte) ([]byte, error)**
Example:
```go
s := &sigil.GzipSigil{}
compressed, _ := s.In([]byte("hello"))
plain, _ := s.Out(compressed)
```
### JSONSigil
Compacts or indents JSON (depending on `Indent`).
Example:
```go
s := &sigil.JSONSigil{Indent: true}
```
**In(data []byte) ([]byte, error)**
Example:
```go
s := &sigil.JSONSigil{Indent: false}
compacted, _ := s.In([]byte(`{"key":"value"}`))
```
**Out(data []byte) ([]byte, error)**
No-op for `JSONSigil`.
Example:
```go
s := &sigil.JSONSigil{Indent: false}
pass, _ := s.Out([]byte(`{"key":"value"}`))
```
### HashSigil
Hashes input using the configured `crypto.Hash`.
Example:
```go
s := sigil.NewHashSigil(crypto.SHA256)
```
**In(data []byte) ([]byte, error)**
Example:
```go
s := sigil.NewHashSigil(crypto.SHA256)
digest, _ := s.In([]byte("hello"))
```
**Out(data []byte) ([]byte, error)**
No-op for hash sigils.
Example:
```go
s := sigil.NewHashSigil(crypto.SHA256)
digest, _ := s.In([]byte("hello"))
pass, _ := s.Out(digest)
```
### NewHashSigil(h crypto.Hash) *HashSigil
Creates a new `HashSigil`.
Example:
```go
s := sigil.NewHashSigil(crypto.SHA256)
```
### NewSigil(name string) (Sigil, error)
Factory for built-in sigils.
Example:
```go
s, _ := sigil.NewSigil("hex")
```
### ErrInvalidKey
Returned when an encryption key is not 32 bytes.
Example:
```go
_, err := sigil.NewChaChaPolySigil([]byte("short"))
if errors.Is(err, sigil.ErrInvalidKey) {
// handle invalid key
}
```
### ErrCiphertextTooShort
Returned when ciphertext is too short to decrypt.
Example:
```go
_, err := sigil.GetNonceFromCiphertext([]byte("short"))
if errors.Is(err, sigil.ErrCiphertextTooShort) {
// handle truncated payload
}
```
### ErrDecryptionFailed
Returned when decryption or authentication fails.
Example:
```go
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:
```go
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:
```go
var ob sigil.PreObfuscator = &sigil.XORObfuscator{}
_ = ob
```
**Obfuscate(data []byte, entropy []byte) []byte**
Example:
```go
ob := &sigil.XORObfuscator{}
masked := ob.Obfuscate([]byte("hello"), []byte("nonce"))
```
**Deobfuscate(data []byte, entropy []byte) []byte**
Example:
```go
ob := &sigil.XORObfuscator{}
masked := ob.Obfuscate([]byte("hello"), []byte("nonce"))
plain := ob.Deobfuscate(masked, []byte("nonce"))
```
### XORObfuscator
XOR-based pre-obfuscator.
Example:
```go
ob := &sigil.XORObfuscator{}
```
**Obfuscate(data []byte, entropy []byte) []byte**
Example:
```go
ob := &sigil.XORObfuscator{}
masked := ob.Obfuscate([]byte("hello"), []byte("nonce"))
```
**Deobfuscate(data []byte, entropy []byte) []byte**
Example:
```go
ob := &sigil.XORObfuscator{}
masked := ob.Obfuscate([]byte("hello"), []byte("nonce"))
plain := ob.Deobfuscate(masked, []byte("nonce"))
```
### ShuffleMaskObfuscator
Shuffle + mask pre-obfuscator.
Example:
```go
ob := &sigil.ShuffleMaskObfuscator{}
```
**Obfuscate(data []byte, entropy []byte) []byte**
Example:
```go
ob := &sigil.ShuffleMaskObfuscator{}
masked := ob.Obfuscate([]byte("hello"), []byte("nonce"))
```
**Deobfuscate(data []byte, entropy []byte) []byte**
Example:
```go
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:
```go
key := make([]byte, 32)
s, _ := sigil.NewChaChaPolySigil(key)
```
**In(data []byte) ([]byte, error)**
Example:
```go
key := make([]byte, 32)
s, _ := sigil.NewChaChaPolySigil(key)
ciphertext, _ := s.In([]byte("hello"))
```
**Out(data []byte) ([]byte, error)**
Example:
```go
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:
```go
key := make([]byte, 32)
s, _ := sigil.NewChaChaPolySigil(key)
```
### NewChaChaPolySigilWithObfuscator(key []byte, obfuscator PreObfuscator) (*ChaChaPolySigil, error)
Creates an encryption sigil with a custom obfuscator.
Example:
```go
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:
```go
key := make([]byte, 32)
s, _ := sigil.NewChaChaPolySigil(key)
ciphertext, _ := s.In([]byte("hello"))
nonce, _ := sigil.GetNonceFromCiphertext(ciphertext)
```