Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[submodule "external/go"]
path = external/go
url = https://github.com/dappcore/go.git
branch = dev
1 change: 1 addition & 0 deletions external/go
Submodule go added at d661b7
10 changes: 10 additions & 0 deletions go.work
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
go 1.26.2

// Workspace mode for development: pulls local Core modules from external/.
//
// CI should run with GOWORK=off so go/go.mod tags drive reproducible builds.

use (
./go
./external/go
)
10 changes: 8 additions & 2 deletions actions.go → go/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,15 +209,21 @@ func copyAction(_ context.Context, opts core.Options) core.Result {

// localMediumFromOptions constructs a sandboxed local Medium using the
// "root" option.
func localMediumFromOptions(opts core.Options) (Medium, error) {
func localMediumFromOptions(opts core.Options) (
Medium,
error,
) {
root := opts.String("root")
if root == "" {
return nil, core.E("io.localMediumFromOptions", "root is required", fs.ErrInvalid)
}
return NewSandboxed(root)
}

func mediumFromOptions(opts core.Options, operation string) (Medium, error) {
func mediumFromOptions(opts core.Options, operation string) (
Medium,
error,
) {
medium, ok := opts.Get("medium").Value.(Medium)
if !ok {
return nil, core.E(operation, "medium is required", fs.ErrInvalid)
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
5 changes: 4 additions & 1 deletion cube/actions.go → go/cube/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,10 @@ func unpackAction(_ context.Context, opts core.Options) core.Result {
return core.Ok(nil)
}

func keyFromOptions(opts core.Options, operation string) ([]byte, error) {
func keyFromOptions(opts core.Options, operation string) (
[]byte,
error,
) {
key, ok := opts.Get("key").Value.([]byte)
if !ok {
return nil, core.E(operation, errKeyType, fs.ErrInvalid)
Expand Down
File renamed without changes.
File renamed without changes.
132 changes: 100 additions & 32 deletions cube/cube.go → go/cube/cube.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ type Options struct {
// Example: medium, _ := cube.New(cube.Options{Inner: io.NewMemoryMedium(), Key: key})
// Example: _ = medium.Write("secret.txt", "classified")
// Example: plaintext, _ := medium.Read("secret.txt")
func New(options Options) (*Medium, error) {
func New(options Options) (
*Medium,
error,
) {
if options.Inner == nil {
return nil, core.E(opCubeNew, "inner medium is required", fs.ErrInvalid)
}
Expand All @@ -68,7 +71,10 @@ func (medium *Medium) Inner() coreio.Medium {
}

// Example: content, _ := medium.Read("secret.txt")
func (medium *Medium) Read(path string) (string, error) {
func (medium *Medium) Read(path string) (
string,
error,
) {
ciphertext, err := medium.inner.Read(path)
if err != nil {
return "", err
Expand All @@ -81,12 +87,14 @@ func (medium *Medium) Read(path string) (string, error) {
}

// Example: _ = medium.Write("secret.txt", "classified")
func (medium *Medium) Write(path, content string) error {
func (medium *Medium) Write(path, content string) error { // legacy error contract

return medium.WriteMode(path, content, 0644)
}

// Example: _ = medium.WriteMode("keys/private.key", key, 0600)
func (medium *Medium) WriteMode(path, content string, mode fs.FileMode) error {
func (medium *Medium) WriteMode(path, content string, mode fs.FileMode) error { // legacy error contract

ciphertext, err := sigil.Transmute([]byte(content), []sigil.Sigil{medium.sigil})
if err != nil {
return core.E("cube.WriteMode", core.Concat("failed to encrypt: ", path), err)
Expand All @@ -95,7 +103,8 @@ func (medium *Medium) WriteMode(path, content string, mode fs.FileMode) error {
}

// Example: _ = medium.EnsureDir("data")
func (medium *Medium) EnsureDir(path string) error {
func (medium *Medium) EnsureDir(path string) error { // legacy error contract

return medium.inner.EnsureDir(path)
}

Expand All @@ -105,32 +114,44 @@ func (medium *Medium) IsFile(path string) bool {
}

// Example: _ = medium.Delete("secret.txt")
func (medium *Medium) Delete(path string) error {
func (medium *Medium) Delete(path string) error { // legacy error contract

return medium.inner.Delete(path)
}

// Example: _ = medium.DeleteAll("archive")
func (medium *Medium) DeleteAll(path string) error {
func (medium *Medium) DeleteAll(path string) error { // legacy error contract

return medium.inner.DeleteAll(path)
}

// Example: _ = medium.Rename("draft.txt", "final.txt")
func (medium *Medium) Rename(oldPath, newPath string) error {
func (medium *Medium) Rename(oldPath, newPath string) error { // legacy error contract

return medium.inner.Rename(oldPath, newPath)
}

// Example: entries, _ := medium.List("data")
func (medium *Medium) List(path string) ([]fs.DirEntry, error) {
func (medium *Medium) List(path string) (
[]fs.DirEntry,
error,
) {
return medium.inner.List(path)
}

// Example: info, _ := medium.Stat("secret.txt")
func (medium *Medium) Stat(path string) (fs.FileInfo, error) {
func (medium *Medium) Stat(path string) (
fs.FileInfo,
error,
) {
return medium.inner.Stat(path)
}

// Example: file, _ := medium.Open("secret.txt")
func (medium *Medium) Open(path string) (fs.File, error) {
func (medium *Medium) Open(path string) (
fs.File,
error,
) {
// Read via cube semantics (decrypt) then wrap in an in-memory fs.File.
ciphertext, err := medium.inner.Read(path)
if err != nil {
Expand All @@ -153,12 +174,18 @@ func (medium *Medium) Open(path string) (fs.File, error) {
}

// Example: writer, _ := medium.Create("secret.txt")
func (medium *Medium) Create(path string) (goio.WriteCloser, error) {
func (medium *Medium) Create(path string) (
goio.WriteCloser,
error,
) {
return &cubeWriteCloser{medium: medium, path: path, mode: 0644}, nil
}

// Example: writer, _ := medium.Append("log.txt")
func (medium *Medium) Append(path string) (goio.WriteCloser, error) {
func (medium *Medium) Append(path string) (
goio.WriteCloser,
error,
) {
var existing []byte
if medium.inner.Exists(path) {
plain, err := medium.Read(path)
Expand All @@ -171,7 +198,10 @@ func (medium *Medium) Append(path string) (goio.WriteCloser, error) {
}

// Example: reader, _ := medium.ReadStream("secret.txt")
func (medium *Medium) ReadStream(path string) (goio.ReadCloser, error) {
func (medium *Medium) ReadStream(path string) (
goio.ReadCloser,
error,
) {
file, err := medium.Open(path)
if err != nil {
return nil, err
Expand All @@ -180,7 +210,10 @@ func (medium *Medium) ReadStream(path string) (goio.ReadCloser, error) {
}

// Example: writer, _ := medium.WriteStream("secret.txt")
func (medium *Medium) WriteStream(path string) (goio.WriteCloser, error) {
func (medium *Medium) WriteStream(path string) (
goio.WriteCloser,
error,
) {
return medium.Create(path)
}

Expand All @@ -203,11 +236,17 @@ type cubeFile struct {
modTime time.Time
}

func (file *cubeFile) Stat() (fs.FileInfo, error) {
func (file *cubeFile) Stat() (
fs.FileInfo,
error,
) {
return coreio.NewFileInfo(file.name, int64(len(file.content)), file.mode, file.modTime, false), nil
}

func (file *cubeFile) Read(buffer []byte) (int, error) {
func (file *cubeFile) Read(buffer []byte) (
int,
error,
) {
if file.offset >= int64(len(file.content)) {
return 0, goio.EOF
}
Expand All @@ -216,7 +255,8 @@ func (file *cubeFile) Read(buffer []byte) (int, error) {
return readCount, nil
}

func (file *cubeFile) Close() error {
func (file *cubeFile) Close() error { // legacy error contract

return nil
}

Expand All @@ -225,7 +265,10 @@ type cubeArchiveBuffer struct {
data []byte
}

func (buffer *cubeArchiveBuffer) Write(data []byte) (int, error) {
func (buffer *cubeArchiveBuffer) Write(data []byte) (
int,
error,
) {
buffer.data = append(buffer.data, data...)
return len(data), nil
}
Expand All @@ -238,12 +281,16 @@ type cubeWriteCloser struct {
mode fs.FileMode
}

func (writer *cubeWriteCloser) Write(data []byte) (int, error) {
func (writer *cubeWriteCloser) Write(data []byte) (
int,
error,
) {
writer.data = append(writer.data, data...)
return len(data), nil
}

func (writer *cubeWriteCloser) Close() error {
func (writer *cubeWriteCloser) Close() error { // legacy error contract

mode := writer.mode
if mode == 0 {
mode = 0644
Expand All @@ -255,7 +302,8 @@ func (writer *cubeWriteCloser) Close() error {
//
// Pack walks the source Medium, packs every file into a tar archive, encrypts
// the archive, and writes the ciphertext to outputPath on the local filesystem.
func Pack(outputPath string, source coreio.Medium, key []byte) error {
func Pack(outputPath string, source coreio.Medium, key []byte) error { // legacy error contract

if source == nil {
return core.E(opCubePack, "source medium is required", fs.ErrInvalid)
}
Expand Down Expand Up @@ -286,7 +334,8 @@ func Pack(outputPath string, source coreio.Medium, key []byte) error {
//
// Unpack reads the encrypted archive from cubePath, decrypts it, unpacks the
// tar contents, and writes every entry to the destination Medium.
func Unpack(cubePath string, destination coreio.Medium, key []byte) error {
func Unpack(cubePath string, destination coreio.Medium, key []byte) error { // legacy error contract

if destination == nil {
return core.E(opCubeUnpack, "destination medium is required", fs.ErrInvalid)
}
Expand Down Expand Up @@ -320,7 +369,10 @@ func Unpack(cubePath string, destination coreio.Medium, key []byte) error {
// Open reads the encrypted archive at cubePath, decrypts it, and returns a
// Medium backed by an in-memory node.Node. Reads and writes do not flow back
// to the .cube file — use Pack again to persist updates.
func Open(cubePath string, key []byte) (coreio.Medium, error) {
func Open(cubePath string, key []byte) (
coreio.Medium,
error,
) {
if cubePath == "" {
return nil, core.E(opCubeOpen, "cube path is required", fs.ErrInvalid)
}
Expand Down Expand Up @@ -353,14 +405,19 @@ func Open(cubePath string, key []byte) (coreio.Medium, error) {
return medium, nil
}

func validateCubeKey(operation string, key []byte) error {
func validateCubeKey(operation string, key []byte) error { // legacy error contract

if _, err := sigil.NewChaChaPolySigil(key, nil); err != nil {
return core.E(operation, errCreateCipher, err)
}
return nil
}

func sandboxedLocalForPath(operation, filePath string) (coreio.Medium, string, error) {
func sandboxedLocalForPath(operation, filePath string) (
coreio.Medium,
string,
error,
) {
if filePath == "" {
return nil, "", core.E(operation, "path is required", fs.ErrInvalid)
}
Expand Down Expand Up @@ -398,15 +455,19 @@ func archiveChildPath(parent, name string) string {
return core.PathJoin(parent, name)
}

func archiveMediumToBorgDataNode(source coreio.Medium) (*borgdatanode.DataNode, error) {
func archiveMediumToBorgDataNode(source coreio.Medium) (
*borgdatanode.DataNode,
error,
) {
dataNode := borgdatanode.New()
if err := addMediumPathToBorgDataNode(source, "", dataNode); err != nil {
return nil, err
}
return dataNode, nil
}

func addMediumPathToBorgDataNode(source coreio.Medium, directoryPath string, dataNode *borgdatanode.DataNode) error {
func addMediumPathToBorgDataNode(source coreio.Medium, directoryPath string, dataNode *borgdatanode.DataNode) error { // legacy error contract

entries, err := source.List(directoryPath)
if err != nil {
return core.E(opCubeArchive, core.Concat("failed to list: ", directoryPath), err)
Expand All @@ -428,14 +489,16 @@ func addMediumPathToBorgDataNode(source coreio.Medium, directoryPath string, dat
return nil
}

func writeBorgDataNodeToMedium(dataNode *borgdatanode.DataNode, destination coreio.Medium) error {
func writeBorgDataNodeToMedium(dataNode *borgdatanode.DataNode, destination coreio.Medium) error { // legacy error contract

if dataNode == nil {
return core.E(opCubeExtract, "Borg DataNode is required", fs.ErrInvalid)
}
return writeBorgDataNodeDir(dataNode, "", destination)
}

func writeBorgDataNodeDir(dataNode *borgdatanode.DataNode, directoryPath string, destination coreio.Medium) error {
func writeBorgDataNodeDir(dataNode *borgdatanode.DataNode, directoryPath string, destination coreio.Medium) error { // legacy error contract

entries, err := dataNode.ReadDir(directoryPath)
if err != nil {
return core.E(opCubeExtract, core.Concat("failed to list Borg DataNode: ", directoryPath), err)
Expand All @@ -455,7 +518,8 @@ func writeBorgDataNodeDir(dataNode *borgdatanode.DataNode, directoryPath string,
return nil
}

func writeBorgDataNodeFile(dataNode *borgdatanode.DataNode, filePath string, destination coreio.Medium) error {
func writeBorgDataNodeFile(dataNode *borgdatanode.DataNode, filePath string, destination coreio.Medium) error { // legacy error contract

name, ok, err := validatedTarEntryName(filePath)
if err != nil || !ok {
return err
Expand All @@ -481,7 +545,11 @@ func closeBorgDataNodeFile(file fs.File, filePath string) {
}
}

func validatedTarEntryName(rawName string) (string, bool, error) {
func validatedTarEntryName(rawName string) (
string,
bool,
error,
) {
if rawName == "" {
return "", false, nil
}
Expand Down
File renamed without changes.
File renamed without changes.
Loading
Loading