Service to watch for creation of accounts on a PDS, and automatically add them as collaborators to a Tangled repository.

feat: implement the collaborator sidecar #2

targeting orbit-nodachi/design from orbit-nodachi/implement
Merged opened by and assigned to orbit-nodachi.test.pds.did.bot
targeting orbit-nodachi/design from orbit-nodachi/implement

The sidecar, built to docs/design.md. It is one Rust binary. The confidential OAuth client uses atgc's vendored jacquard-oauth, and runs one session per owner with a forced daily refresh and a two-year warning. Agents are found from the didbot firehose, with a listAccounts true-up. New repos are found from Jetstream, filtered to owner declarations. Grants run through one queue per owner paced at 1 write per second. Revokes happen only on an explicit tombstone: a deleted account event, or a deprovisioned/decommissioned ledger entry. Every action goes to an audit log. Owner state changes trigger ntfy and healthchecks.io alerts. The public listener serves the client metadata, JWKS and /health over ACME TLS, and the tailnet listener serves login, callback and /status.

The design doc now covers repo events, the known-agent and known-repo sets, and tombstone-only revocation. 13 integration tests run against mock PDS, knot and didbot servers. Against the live pds.did.bot, true-up --dry-run makes only GETs, and reports what it would do with no owner session signed in.

This targets the design branch and should land after it.

🤖 Generated with Claude Code

Commits 18

feat: keep the owner's consent time in the session file
test: cover an owner with only legacy repo records
fix: order grants and describe in-memory state
test: keep an unclaimed collaborator
fix: run a true-up when jetstream reconnects
feat!: keep sessions in files and state in memory
docs: require an ssh key for eligibility
feat: grant only agents that hold a Tangled SSH key
docs: describe write evidence, the age window and optional tailscale
feat: require a write, bound true-ups by age, and allow no tailnet
docs: describe repo events and tombstone-only revocation
test: cover grants, events, tombstones, pacing and dry-run
feat: serve the public and tailnet listeners, and add the cli
feat: reconcile grants with one paced queue per owner
feat: follow didbot agents, the firehose and jetstream repos
feat: run the confidential oauth client and refresh each owner
feat: validate config and keep encrypted state in sqlite
chore: add the Rust project and atgc's vendored jacquard-oauth