- Rust 98%
- Docker 1%
- Shell <1%
tangled-collaborator-sidecar #
BLANCMANGE-TAGLINE
How it fits together #
didbot server (pds.did.bot) owner PDS (Bluesky)
+----------------------------+ +------------------------------+
| subscribeRepos firehose | | org.tangled.repo.declaration |--> Jetstream
| bot.did.listAccounts | | getServiceAuth | |
| bot.did.listAccountLedgers | | OAuth, confidential client | |
+-------------+--------------+ +---------------+--------------+ |
| ^ |
key commits, | sessions, refreshes, | repo creates and |
tombstones | service-auth tokens | deletes |
v v |
+-----------------------------------------------------------------------+ |
| tangled-collaborator-sidecar |<---+
| Lightsail container, tangled-collaborator-sidecar.did.bot |
| |
| known agents x known repos x rules --> grants, audit on stdout |
| in memory: agents, repos, tombstones; files: sealed sessions |
+---------+-------------------------------------------------------------+
|
| createRecord / deleteRecord
| org.tangled.graph.collaborator
| aud = repo DID, iss = repo owner
v
+------------------------------+
| Tangled knot (knot1) |<-- the agent pushes branches and opens pulls
| the repo's collaborators |
+------------------------------+
- An agent on a claimed didbot server publishes an
org.tangled.key.sshKey. The commit that creates it arrives on the server's firehose. - The sidecar checks the agent's operator against the operator's own
bot.did.operatorrecords, and matches its zone and kind against the rules. - For each repo the rules name, the sidecar asks that repo's owner's PDS for
a service-auth token, and writes an
org.tangled.graph.collaboratorrecord on the repo's knot. The agent can then push and open pulls. - A new repo arrives through Jetstream. It is granted to every known agent its rules match.
- Only an explicit tombstone revokes, whoever added the collaborator: a
deletedaccount event, or adeprovisionedledger entry. A missing or unreachable server never does.
docs/design.md has the details.
Running it #
Build and check the configuration:
cargo build --release
./target/release/tangled-collaborator-sidecar --config deploy/config.toml check-config
deploy/config.toml is the configuration, and the image bakes it in. It holds
no secret: a change to it is a new image. It names the servers to follow, the
operators, the owners, the rules, and the sidecar's own hostname and data
directory. The committed data directory is /data, the container's volume, so
a local run needs a copy with a writable one.
The ACME contact email is optional, and the committed configuration leaves it
unset. Without tailnet_bind and tailnet_hostname, login, callback and
status are served on the public listener.
The data directory holds the session data key, the OAuth client signing key,
one sealed session file per owner under sessions/, and the ACME cache. Each
session file holds the owner's consent time. All are mode 0600. Back it up:
losing the signing key ends every owner session.
Commands:
tangled-collaborator-sidecar serve
tangled-collaborator-sidecar check-config
tangled-collaborator-sidecar true-up --dry-run
tangled-collaborator-sidecar status
Sign an owner in by opening https://<public_hostname>/login. /status is
public and shows owner DIDs and states, the known agent, repo and tombstone
counts, and whether each stream is connected. /health is public and always
answers 200; its worst field is the worst component state, including
expiring within 30 days of the two-year consent cap.
Deploying #
The image is published to ECR Public, and the host pulls it without a deploy
script. The default repository is
public.ecr.aws/i7w5y2e0/tangled-collaborator-sidecar; pass another, or a
tfvars file that holds it as image_repository, to override:
scripts/publish-image.sh
scripts/publish-image.sh --var-file /path/to/didbot/infra/sidecar/terraform.tfvars
It builds a static musl binary for linux/amd64 in a container, then pushes the
image tagged with the commit's short sha and latest. It refuses a dirty
tree, and it does not push until the build succeeds.
The host is didbot's infra/sidecar Lightsail stack. Its first apply installs
Docker, the data directory at /var/lib/tangled-collaborator-sidecar, and two
systemd units. The main unit runs the container as a non-root UID with 443
published, /data mounted from the data directory, CAP_NET_BIND_SERVICE and
a read-only filesystem. The timer pulls <image_repository>:latest every five
minutes and restarts the container only when the image ID changed. There is no
SSH deploy and no credential on the host.
Publishing never touches the data directory. The public certificate comes from Let's Encrypt on the instance and is cached there.