This repository has been archived on 2026-08-19. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
tend/docs/ARCHITECTURE.md
T
gamertan 00d1dd4209 feat: publish Tend v0.2 preview source
Publish the reviewed allowlisted snapshot whose exact binary completed maintenance deployment, rollback, and reactivation exercises for Gamertan and Sandwich Hime.

Private-Source-Commit: 4d7094c8b7c61991bfb67b11fc1558724c874eb2

Private-Source-Tree: 54a2f74804f7acddf3755d7d4da5b97f5fc28381

AI-Assistance: OpenAI Codex assisted implementation, testing, security review, and release verification.
Signed-off-by: Cole Speelman <crspeelman@gmail.com>
2026-08-16 19:02:08 -04:00

2.8 KiB

Architecture

Tend has three deliberately separate boundaries.

Package boundary

tend package accepts only a clean checkout whose HEAD exactly matches the configured pushed branch. It rejects Go module replacements and unversioned dependencies, builds the configured main package twice with GOWORK=off, and requires byte-identical output. The resulting archive contains only:

  • the service binary;
  • RELEASE.json;
  • BUILDINFO.json;
  • SBOM.spdx.json; and
  • SHA256SUMS.

The external archive digest is the release identity used by deployment.

Transport boundary

tend push sends one bounded protocol frame to a dedicated account through a pinned OpenSSH host key. It uses an argument vector, disables config files, forwarding, PTYs, local commands, and proxy commands, and requests exactly tend-receive-v1. The account's forced command invokes only the root-owned receiver. The receiver's root-owned policy maps an allowlisted service name to one exact configuration path and size ceiling.

The target receives no source, repository credential, Go cache, dependency, or arbitrary command. The artifact digest must equal both the produced digest and the separately supplied approved digest before it is staged.

Target-host boundary

Schema-2 configurations live below /etc/tend/services/. Secrets live only in separate /etc/tend/environment/*.env files that are root-owned, non-symlink, and mode 0600. Configurations contain the path, never the values. Candidate and installed units read the same file; Tend overrides only the candidate's loopback listen address.

Dry-run validation extracts into a temporary directory and does not touch the release tree. Activation acquires the shared lock, installs a content-addressed release, verifies all embedded checksums and manifest fields, and starts the candidate without evaluating configuration as shell code.

Activation boundary

Blue/green mode points the inactive slot at the new release, restarts and probes it, atomically replaces one imported Caddy handler, validates the full Caddy configuration, reloads Caddy, and records the prior active slot.

Singleton mode starts the new release in a hardened transient systemd unit on a separate loopback address, probes it, stops the candidate, changes the current release pointer, and restarts the installed singleton unit.

After the local post-activation probes, Tend also checks configured HTTPS public origins. Any failure before state persistence restores the previously observed Caddy bytes and/or release pointers. Rollback is a separate explicit command over the recorded state. It rechecks local health/readiness and public reachability, but deliberately does not apply a future release's content marker to an older release whose routes may differ. Pruning preserves both active and previous releases.