docs: publish Tend Compose continuity evidence

Export the reviewed allowlisted snapshot from private source commit 07c1655921f21ee5e4fc4d85639d199e8867b17d. This records the Docker Compose activation, schema-compatible rollback, and stateful migration resource findings from Observatory Preview 19 dogfooding.

AI-Assisted: OpenAI Codex
Signed-off-by: Cole Speelman <crspeelman@gmail.com>
This commit is contained in:
2026-08-18 21:42:33 -04:00
commit bf56dbce0f
83 changed files with 8555 additions and 0 deletions
+123
View File
@@ -0,0 +1,123 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Package transport implements Tend's bounded, versioned deployment stream.
package transport
import (
"bufio"
"bytes"
"crypto/sha256"
"encoding/binary"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io"
"regexp"
"strings"
)
const (
Protocol = "tend-receive-v1"
MaxArtifactBytes = 512 << 20
maxHeaderBytes = 64 << 10
maxArtifactName = 128
)
var (
servicePattern = regexp.MustCompile(`^[a-z][a-z0-9-]{1,62}$`)
artifactPattern = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$`)
)
type Header struct {
Protocol string `json:"protocol"`
Service string `json:"service"`
ArtifactName string `json:"artifact_name"`
Size int64 `json:"size"`
SHA256 string `json:"sha256"`
ApprovedSHA256 string `json:"approved_sha256"`
Activate bool `json:"activate"`
}
func (h Header) Validate(maxBytes int64) error {
if h.Protocol != Protocol {
return errors.New("unsupported receive protocol")
}
if !servicePattern.MatchString(h.Service) {
return errors.New("invalid service name")
}
if len(h.ArtifactName) > maxArtifactName || !artifactPattern.MatchString(h.ArtifactName) {
return errors.New("invalid artifact name")
}
if h.Size <= 0 || h.Size > maxBytes {
return errors.New("artifact size exceeds policy")
}
if h.SHA256 != h.ApprovedSHA256 || len(h.SHA256) != 64 || strings.ToLower(h.SHA256) != h.SHA256 {
return errors.New("artifact digest was not explicitly approved")
}
if _, err := hex.DecodeString(h.SHA256); err != nil {
return errors.New("artifact digest is not hexadecimal")
}
return nil
}
func Prefix(header Header) ([]byte, error) {
if err := header.Validate(MaxArtifactBytes); err != nil {
return nil, err
}
body, err := json.Marshal(header)
if err != nil {
return nil, err
}
if len(body) > maxHeaderBytes {
return nil, errors.New("receive header exceeds limit")
}
prefix := make([]byte, 4+len(body))
binary.BigEndian.PutUint32(prefix[:4], uint32(len(body)))
copy(prefix[4:], body)
return prefix, nil
}
func ReadHeader(reader *bufio.Reader) (Header, error) {
var size [4]byte
if _, err := io.ReadFull(reader, size[:]); err != nil {
return Header{}, fmt.Errorf("read receive header length: %w", err)
}
length := binary.BigEndian.Uint32(size[:])
if length == 0 || length > maxHeaderBytes {
return Header{}, errors.New("receive header length is invalid")
}
body := make([]byte, length)
if _, err := io.ReadFull(reader, body); err != nil {
return Header{}, fmt.Errorf("read receive header: %w", err)
}
decoder := json.NewDecoder(bytes.NewReader(body))
decoder.DisallowUnknownFields()
var header Header
if err := decoder.Decode(&header); err != nil {
return Header{}, fmt.Errorf("decode receive header: %w", err)
}
var trailing any
if err := decoder.Decode(&trailing); !errors.Is(err, io.EOF) {
return Header{}, errors.New("receive header contains trailing data")
}
return header, nil
}
func CopyArtifact(destination io.Writer, reader *bufio.Reader, header Header, maxBytes int64) error {
if err := header.Validate(maxBytes); err != nil {
return err
}
hash := sha256.New()
written, err := io.CopyN(io.MultiWriter(destination, hash), reader, header.Size)
if err != nil || written != header.Size {
return errors.New("artifact stream ended before declared size")
}
if _, err = reader.ReadByte(); !errors.Is(err, io.EOF) {
return errors.New("artifact stream contains trailing bytes")
}
if hex.EncodeToString(hash.Sum(nil)) != header.SHA256 {
return errors.New("artifact stream digest does not match")
}
return nil
}
+81
View File
@@ -0,0 +1,81 @@
// SPDX-License-Identifier: AGPL-3.0-only
package transport
import (
"bufio"
"bytes"
"crypto/sha256"
"encoding/hex"
"strings"
"testing"
)
func validFrame(t *testing.T, artifact string) ([]byte, Header) {
t.Helper()
hash := sha256.Sum256([]byte(artifact))
digest := hex.EncodeToString(hash[:])
header := Header{Protocol: Protocol, Service: "example-site", ArtifactName: "example.tar.gz", Size: int64(len(artifact)), SHA256: digest, ApprovedSHA256: digest, Activate: true}
prefix, err := Prefix(header)
if err != nil {
t.Fatal(err)
}
return append(prefix, artifact...), header
}
func TestProtocolRoundTrip(t *testing.T) {
frame, expected := validFrame(t, "artifact")
reader := bufio.NewReader(bytes.NewReader(frame))
header, err := ReadHeader(reader)
if err != nil || header != expected {
t.Fatalf("header=%+v err=%v", header, err)
}
var artifact bytes.Buffer
if err = CopyArtifact(&artifact, reader, header, 1<<20); err != nil {
t.Fatal(err)
}
if artifact.String() != "artifact" {
t.Fatalf("artifact=%q", artifact.String())
}
}
func TestProtocolRejectsTrailingAndForgedInputs(t *testing.T) {
frame, header := validFrame(t, "artifact")
reader := bufio.NewReader(bytes.NewReader(append(frame, 'x')))
read, _ := ReadHeader(reader)
if err := CopyArtifact(&bytes.Buffer{}, reader, read, 1<<20); err == nil {
t.Fatal("accepted trailing bytes")
}
header.Service = "../../root"
if _, err := Prefix(header); err == nil {
t.Fatal("accepted forged service")
}
header.Service = "example-site"
header.ApprovedSHA256 = strings.Repeat("0", 64)
if _, err := Prefix(header); err == nil {
t.Fatal("accepted unapproved digest")
}
}
func FuzzProtocolFraming(f *testing.F) {
hash := sha256.Sum256([]byte("artifact"))
digest := hex.EncodeToString(hash[:])
prefix, err := Prefix(Header{Protocol: Protocol, Service: "example-site", ArtifactName: "example.tar.gz", Size: 8, SHA256: digest, ApprovedSHA256: digest})
if err != nil {
f.Fatal(err)
}
frame := append(prefix, []byte("artifact")...)
f.Add(frame)
f.Add([]byte{0, 0, 0, 0})
f.Fuzz(func(t *testing.T, input []byte) {
if len(input) > 2<<20 {
t.Skip()
}
reader := bufio.NewReader(bytes.NewReader(input))
header, err := ReadHeader(reader)
if err != nil {
return
}
_ = CopyArtifact(&bytes.Buffer{}, reader, header, 1<<20)
})
}
+153
View File
@@ -0,0 +1,153 @@
// SPDX-License-Identifier: AGPL-3.0-only
package transport
import (
"bytes"
"context"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"regexp"
"strconv"
"strings"
)
var targetPattern = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9_.-]*@[A-Za-z0-9][A-Za-z0-9.-]*$`)
type PushOptions struct {
Target string
Port int
KnownHosts string
Identity string
Service string
Artifact string
SHA256 string
ApprovedSHA256 string
Activate bool
}
type SSHRunner interface {
Run(context.Context, string, []string, io.Reader) ([]byte, error)
}
type ExecSSHRunner struct{}
func (ExecSSHRunner) Run(ctx context.Context, name string, args []string, stdin io.Reader) ([]byte, error) {
command := exec.CommandContext(ctx, name, args...)
command.Stdin = stdin
var output, diagnostic boundedBuffer
command.Stdout = &output
command.Stderr = &diagnostic
err := command.Run()
if err != nil {
return output.Bytes(), fmt.Errorf("ssh failed: %w: %s", err, strings.TrimSpace(diagnostic.String()))
}
return output.Bytes(), nil
}
type boundedBuffer struct{ bytes.Buffer }
func (b *boundedBuffer) Write(value []byte) (int, error) {
written := len(value)
remaining := (1 << 20) - b.Len()
if remaining > 0 {
if len(value) > remaining {
value = value[:remaining]
}
_, _ = b.Buffer.Write(value)
}
return written, nil
}
func Push(ctx context.Context, runner SSHRunner, options PushOptions) (json.RawMessage, error) {
if !targetPattern.MatchString(options.Target) || strings.HasPrefix(options.Target, "-") {
return nil, errors.New("target must be user@host without shell syntax")
}
if options.Port < 1 || options.Port > 65535 {
return nil, errors.New("SSH port is invalid")
}
if err := safeClientFile(options.KnownHosts, false); err != nil {
return nil, fmt.Errorf("known-hosts file: %w", err)
}
if options.Identity != "" {
if err := safeClientFile(options.Identity, true); err != nil {
return nil, fmt.Errorf("identity file: %w", err)
}
}
if !filepath.IsAbs(options.Artifact) || filepath.Clean(options.Artifact) != options.Artifact || strings.ContainsAny(options.Artifact, "\x00\r\n\t") {
return nil, errors.New("artifact path must be clean and absolute")
}
artifactInfo, err := os.Lstat(options.Artifact)
if err != nil || !artifactInfo.Mode().IsRegular() || artifactInfo.Mode()&os.ModeSymlink != 0 || artifactInfo.Size() <= 0 || artifactInfo.Size() > MaxArtifactBytes {
return nil, errors.New("artifact must be a bounded regular non-symlink file")
}
artifact, err := os.Open(options.Artifact)
if err != nil {
return nil, err
}
defer artifact.Close()
info, err := artifact.Stat()
if err != nil || !info.Mode().IsRegular() || !os.SameFile(artifactInfo, info) {
return nil, errors.New("artifact must be a bounded regular file")
}
hash := sha256.New()
if _, err = io.Copy(hash, artifact); err != nil {
return nil, err
}
actual := hex.EncodeToString(hash.Sum(nil))
if actual != options.SHA256 || options.SHA256 != options.ApprovedSHA256 {
return nil, errors.New("artifact digest was not explicitly approved")
}
if _, err = artifact.Seek(0, io.SeekStart); err != nil {
return nil, err
}
header := Header{Protocol: Protocol, Service: options.Service, ArtifactName: filepath.Base(options.Artifact), Size: info.Size(), SHA256: options.SHA256, ApprovedSHA256: options.ApprovedSHA256, Activate: options.Activate}
prefix, err := Prefix(header)
if err != nil {
return nil, err
}
args := []string{"-F", os.DevNull, "-T", "-p", strconv.Itoa(options.Port), "-o", "BatchMode=yes", "-o", "ClearAllForwardings=yes", "-o", "ExitOnForwardFailure=yes", "-o", "ForwardAgent=no", "-o", "IdentitiesOnly=yes", "-o", "LogLevel=ERROR", "-o", "PermitLocalCommand=no", "-o", "ProxyCommand=none", "-o", "RequestTTY=no", "-o", "StrictHostKeyChecking=yes", "-o", "UserKnownHostsFile=" + options.KnownHosts}
if options.Identity != "" {
args = append(args, "-i", options.Identity)
}
args = append(args, options.Target, Protocol)
output, err := runner.Run(ctx, "ssh", args, io.MultiReader(bytes.NewReader(prefix), artifact))
if err != nil {
return nil, err
}
if !json.Valid(output) {
return nil, errors.New("receiver returned invalid JSON")
}
return json.RawMessage(output), nil
}
func safeClientFile(path string, private bool) error {
if !filepath.IsAbs(path) || filepath.Clean(path) != path || strings.ContainsAny(path, "\x00\r\n\t") {
return errors.New("path must be clean and absolute")
}
parent, err := os.Lstat(filepath.Dir(path))
if err != nil || !parent.IsDir() || parent.Mode()&os.ModeSymlink != 0 || parent.Mode().Perm()&0o022 != 0 {
return errors.New("parent must be a real directory not writable by group or others")
}
info, err := os.Lstat(path)
if err != nil {
return err
}
if !info.Mode().IsRegular() || info.Mode()&os.ModeSymlink != 0 {
return errors.New("must be a regular non-symlink file")
}
if info.Mode().Perm()&0o022 != 0 {
return errors.New("must not be group- or world-writable")
}
if private && info.Mode().Perm()&0o077 != 0 {
return errors.New("must not be accessible by group or others")
}
return nil
}
+81
View File
@@ -0,0 +1,81 @@
// SPDX-License-Identifier: AGPL-3.0-only
package transport
import (
"bufio"
"bytes"
"context"
"crypto/sha256"
"encoding/hex"
"io"
"os"
"path/filepath"
"slices"
"testing"
)
type captureRunner struct {
name string
args []string
input []byte
calls int
}
func (runner *captureRunner) Run(_ context.Context, name string, args []string, input io.Reader) ([]byte, error) {
runner.calls++
runner.name = name
runner.args = append([]string(nil), args...)
runner.input, _ = io.ReadAll(input)
return []byte(`{"validated":true,"mutation":"activated"}`), nil
}
func TestPushUsesPinnedSSHAndExactFrame(t *testing.T) {
dir := t.TempDir()
knownHosts := filepath.Join(dir, "known_hosts")
identity := filepath.Join(dir, "identity")
artifact := filepath.Join(dir, "release.tar.gz")
if err := os.WriteFile(knownHosts, []byte("host key\n"), 0o644); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(identity, []byte("private\n"), 0o600); err != nil {
t.Fatal(err)
}
content := []byte("artifact")
if err := os.WriteFile(artifact, content, 0o600); err != nil {
t.Fatal(err)
}
hash := sha256.Sum256(content)
digest := hex.EncodeToString(hash[:])
runner := &captureRunner{}
result, err := Push(context.Background(), runner, PushOptions{Target: "tend-deploy@example.test", Port: 2222, KnownHosts: knownHosts, Identity: identity, Service: "example-site", Artifact: artifact, SHA256: digest, ApprovedSHA256: digest, Activate: true})
if err != nil {
t.Fatal(err)
}
if !bytes.Contains(result, []byte(`"activated"`)) || runner.calls != 1 || runner.name != "ssh" {
t.Fatalf("result=%s calls=%d name=%q", result, runner.calls, runner.name)
}
if !slices.Contains(runner.args, "ProxyCommand=none") || !slices.Contains(runner.args, "StrictHostKeyChecking=yes") || runner.args[len(runner.args)-1] != Protocol {
t.Fatalf("args=%#v", runner.args)
}
reader := bufio.NewReader(bytes.NewReader(runner.input))
header, err := ReadHeader(reader)
if err != nil {
t.Fatal(err)
}
var copied bytes.Buffer
if err = CopyArtifact(&copied, reader, header, 1<<20); err != nil {
t.Fatal(err)
}
if copied.String() != string(content) || header.Service != "example-site" || !header.Activate {
t.Fatalf("header=%+v body=%q", header, copied.String())
}
}
func TestPushRejectsShellTargetBeforeExecution(t *testing.T) {
runner := &captureRunner{}
_, err := Push(context.Background(), runner, PushOptions{Target: "root@example.test;touch", Port: 22})
if err == nil || runner.calls != 0 {
t.Fatalf("err=%v calls=%d", err, runner.calls)
}
}
+48
View File
@@ -0,0 +1,48 @@
// SPDX-License-Identifier: AGPL-3.0-only
package transport
import (
"bufio"
"context"
"fmt"
"io"
"os"
"gamertan.com/tend/internal/deploy"
"gamertan.com/tend/internal/serverpolicy"
)
func Receive(ctx context.Context, input io.Reader, policy serverpolicy.Policy, manager deploy.Manager) (deploy.Report, error) {
if err := policy.CheckDirectories(); err != nil {
return deploy.Report{}, err
}
reader := bufio.NewReaderSize(input, maxHeaderBytes+4)
header, err := ReadHeader(reader)
if err != nil {
return deploy.Report{}, err
}
service, err := policy.CheckService(header.Service)
if err != nil {
return deploy.Report{}, err
}
if err = header.Validate(service.Policy.MaxArtifactBytes); err != nil {
return deploy.Report{}, err
}
file, err := os.CreateTemp(policy.IncomingRoot, ".tend-receive-"+header.Service+"-")
if err != nil {
return deploy.Report{}, err
}
path := file.Name()
defer os.Remove(path)
if err = file.Chmod(0o600); err == nil {
err = CopyArtifact(file, reader, header, service.Policy.MaxArtifactBytes)
}
if closeErr := file.Close(); err == nil {
err = closeErr
}
if err != nil {
return deploy.Report{}, fmt.Errorf("receive artifact: %w", err)
}
return manager.Deploy(ctx, service.Config, deploy.Request{Artifact: path, SHA256: header.SHA256, ApprovedSHA256: header.ApprovedSHA256, Activate: header.Activate})
}