myc

Self-custodial remote signer for Radroots apps
git clone https://radroots.dev/git/myc.git
Log | Files | Refs | README | LICENSE

commit 9a19a2a1fd1a4dc9d7e2c8e174821ff32cf39890
parent bc366777047fc19643cfbb7d1eb43bfbaa7b5cb1
Author: triesap <tyson@radroots.org>
Date:   Sun,  9 Aug 2026 01:01:01 +0000

docs: add myc refactor agent rules

- define clean-slate provider config persistence and process boundaries
- preserve standalone source-lock and local workflow authority
- require durable admission publication admin and observability invariants
- codify complete release acceptance and irreversible action gates

Diffstat:
MAGENTS.md | 200+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 181 insertions(+), 19 deletions(-)

diff --git a/AGENTS.md b/AGENTS.md @@ -1,19 +1,181 @@ -# myc - code directives - -- this repo defines `myc`, the Radroots signer service -- treat signing, key material handling, approval flows, session control, and signer-facing transport as security-critical repo-owned behavior -- do not make this repo responsible for relay storage, relay fanout, relay tenancy, SDK contract generation, wallet product flows, platform-wide artifacts, publication, promotion, or deployment transport unless explicitly assigned here -- prefer the smallest coherent change that fully addresses the request; do not mix unrelated cleanup, speculative refactors, compatibility scaffolding, or roadmap work into the same change -- inspect the relevant implementation, tests, manifests, and docs before changing behavior -- do not invent requirements, APIs, dependencies, release processes, or external integration behavior -- do not depend on private repositories, unpublished artifacts, local machine layouts, absolute paths, or internal monorepo context -- keep key material handling narrow, explicit, auditable, and separated from presentation or transport glue -- prefer typed request, response, approval, session, and error models over stringly or implicit state -- keep public docs, manifests, tests, generated artifacts, and contract surfaces aligned with behavior changes -- avoid hidden production panics; use typed errors for expected failure modes -- avoid `unsafe` unless it is strictly necessary, locally justified, and documented with nearby invariants -- tests and examples must not include real secrets, realistic private keys, reusable credentials, or sensitive event content -- preserve least-privilege boundaries and explicit trust boundaries; stop and report concerns before weakening security, privacy, or key custody boundaries -- use checked-in, repo-owned validation first; run the smallest documented validation that credibly covers the change -- if validation cannot run, report exactly what was skipped and why; never claim validation passed unless it actually ran -- keep commits focused and reviewable, using `<scope>: <imperative summary>` unless a repo convention overrides it +# myc — repository agent contract + +## 1. Scope and operating model + +- This file applies to the complete repository unless a nearer `AGENTS.md` is + stricter. +- This repository owns `myc`, the standalone Radroots NIP-46 signer service. + Treat identity custody, signing, approval, session, persistence, and + signer-facing transport as security-critical behavior. +- Keep the repository independently buildable, testable, packageable, and + operable. Do not depend on private repositories, unreachable or unlocked + artifacts, internal monorepo paths, absolute workstation paths, or private + harnesses. An unpublished public dependency is allowed only when its exact + commit is reachable from the governed public Git source and pinned by the + checked-in source lock. +- `.github/**` and capsule-local CI workflows are forbidden; keep validation + forge-agnostic, and place any required monorepo orchestration exclusively + under the parent monorepo's root `.act/**` authority. +- Myc does not own relay storage or tenancy, general relay fanout, SDK contract + generation, wallet UX, hosted accounts, telemetry, artifact promotion, or + deployment transport. + +## 2. Authority and preflight + +- Before editing, read this file, `README`, `Cargo.toml`, + `radroots.lib.source-lock.v1.toml`, the relevant implementation and tests, + and `flake.nix` or migrations when they are in scope. +- Treat checked-in source, tests, and prototype behavior as implementation + evidence, not permission to preserve behavior that the active requirement + removes. +- Do not invent protocol behavior, APIs, dependencies, release processes, + identity authority, migration behavior, or external integration semantics. +- Inspect `git status --short`, the exact repository root, and nearby tests + before changing behavior. Preserve unrelated work and stop on an unresolved + security or custody conflict. +- Keep changes narrowly scoped and independently reviewable. Do not mix + unrelated cleanup, speculative abstractions, roadmap work, or compatibility + scaffolding into a checkpoint. + +## 3. Clean-slate service rule + +- Do not add or preserve prototype configuration readers, `.env` or + `--env-file` runtime configuration, `MYC_*` runtime selectors, JSON/JSONL + mutable state, prototype config/state importers or migrations, worker paths, + old-path probes, aliases, fallbacks, dual readers/writers, deprecated + modules/APIs/re-exports, or old/new feature switches. Offline production + schema migration must never accept an unreleased prototype format. +- Remove superseded behavior and update every affected Radroots-owned consumer + directly. Do not hide a breaking change behind a compatibility adapter unless + an accepted public requirement explicitly requires one. +- Preserve canonical NIP-04, NIP-44, and NIP-46 interoperability. Clean-slate + product behavior never authorizes protocol drift or relaxed wire validation. +- A breaking config, CLI, state, provider, admin, error, or wire change must + update its public machine contracts, examples, tests, generated surfaces, and + release qualification in the same coherent sequence. + +## 4. Identity, provider, and secret boundaries + +- Keep transport, user, and optional discovery identities explicit. Never + generate, replace, infer, or collapse an identity during ordinary `run`. +- Support only the governed `encrypted_file` and permissioned Unix-socket + `local_signer` providers. Do not add plaintext keys, arbitrary child + commands, shells, desktop/server keyrings, managed accounts, TCP signers, or + sibling wrapping-key fallback. +- Treat every provider result as untrusted. Verify contract version, operation + and correlation IDs, expected identity and role, bounds, exact unsigned event + fields, author, event ID, signature, and applicable NIP semantics before use. +- Keep plaintext keys, decrypted key material, wrapping credentials, provider + secrets, and equivalent protected material out of config, logs, status, + metrics, audit output, fixtures, backups, process arguments, environment + contracts, error strings, and ordinary `Debug` output. A governed backup may + contain the encrypted ciphertext envelope, but never the material needed to + unwrap it. Minimize and zeroize protected values where practical. +- Use typed request, response, approval, permission, session, provider, and + error models. Raw provider, relay, SQL, or source-chain errors never cross a + public or operator boundary. + +## 5. Configuration, state, and process boundaries + +- Load exactly one immutable, strictly versioned TOML document. Reject unknown + fields, implicit relays, unsafe defaults, environment overlays, includes, + interpolation, fragments, hot reload, and arbitrary leaf flags. +- Each service instance owns one explicitly initialized SQLite catalog and one + live writer lock. Normal `run` opens existing state only and never creates, + imports, guesses, or silently migrates prototype state. +- Keep raw SQLite pools and write authority private to the store. The daemon is + the only live writer; live mutations and online backup use the typed, + permissioned Unix-socket admin boundary and never fall back to direct writes. + Offline state operations must prove that no daemon writer lock is held. +- Never hold a database transaction while waiting for a provider, relay, DNS, + clock, entropy, or other external effect. +- Parse the process CLI and initialize the tracing subscriber only in the + binary composition boundary. Library modules may emit tracing events but + must not install signal handlers, create nested Tokio runtimes, call + `process::exit`, or detach authoritative tasks. +- Inject wall time, monotonic time, entropy, providers, transport, and + failpoints. Supervise and join every authoritative task; panic, error, or + unexpected successful return from a critical task must coordinate shutdown + and produce a nonzero process result. + +## 6. Admission, commit, and publication invariants + +- Bound and validate signed event bytes, tags, authored time, recipient, + signature, event ID, decrypted plaintext, request identity, method, replay, + conflicting reuse, connection admission, authorization challenges, and rate + retention before accepting work. +- Keep authorization-challenge URLs and display-only client metadata under + operator policy; untrusted clients never choose redirect or display + authority. Use separate bounded rate budgets for connection admission and + authorization challenges so exhaustion of one cannot bypass or disable the + other. +- Commit the request decision, session effects, audit, exact serialized signed + response bytes, immutable target set, and initial outbox state atomically + before any relay submission. +- Treat stored signed bytes as the sole publication authority. Retry, crash + recovery, and reopen must submit the identical bytes and digest without + deserializing, rebuilding, re-signing, or changing targets. +- Distinguish submitted, delivered, failed, and unknown outcomes. Lost + acknowledgement never becomes proof of failure or delivery. +- Bound every queue, pool, request, response, event, tag set, retry schedule, + deadline, rate window, retention set, audit query, and in-memory collection. + Saturation must reject or defer safely without dropping committed work. + +## 7. Admin and observability boundaries + +- Detailed status and every live mutation use bounded, versioned HTTP/JSON over + the permissioned Unix socket. Do not add TCP admin, browser auth, CORS, or a + direct writable CLI fallback. +- Optional TCP operations expose only cached `/livez`, `/readyz`, and + `/metrics`. They must not perform SQLite, provider, relay, credential, DNS, + or other active probes. +- Keep logs as safe structured stderr output. Keep result data on stdout and + diagnostics on stderr. Use stable bounded public codes and messages, bounded + metric labels, and explicit redaction. +- Backup and restore must preserve lock, manifest, integrity, schema, service, + instance, identity, permission, fsync, atomic-rename, and protected-material + exclusion invariants. + +## 8. Rust and test discipline + +- Prefer pure transformations, explicit state machines, validated newtypes, + tagged enums, narrow side-effect boundaries, and private visibility. +- Avoid hidden production panics. Use typed errors for expected failures and + reserve `unwrap` or `expect` for tests or locally proven invariants. +- Keep `#![forbid(unsafe_code)]` at the crate roots; unsafe code is forbidden. +- Add deterministic positive, negative, boundary, crash/retry, cancellation, + saturation, redaction, and interoperability tests for every behavior change. + Tests and examples must not contain real secrets, realistic private keys, + reusable credentials, or sensitive event content. +- Treat generated files as generated. Update them through the owning command + and run the corresponding freshness check. + +## 9. Canonical verification + +Use the repository-owned Nix lanes as the standalone command authority: + +```text +nix run .#fmt +nix run .#check +nix run .#test +nix run .#release-acceptance +``` + +The release-acceptance contract requires formatting, locked metadata, locked +all-target checking and testing, warnings-denied all-target Clippy, rustdoc with +warnings denied, and diff hygiene. Run any gate not yet covered by the current +release script explicitly; do not describe the script as sufficient until it +enforces the complete contract. Run additional SQLx freshness, source-lock, +Nix, OCI, systemd, package, SBOM, checksum, notice, and fresh-install gates when +their surfaces change. Use narrower checked-in commands only for iteration, +and never claim a command passed unless it ran successfully. + +## 10. Commits and irreversible actions + +- Format commits as `<scope>: <imperative summary>`, with a blank line and + `- ` bullets when a body is useful. Split unrelated changes. +- Report the exact files changed, behavior changed, commands run, results, + unresolved risks, and whether the next checkpoint is safe. +- Do not publish, push, tag, sign, deploy, rotate credentials, change ownership, + or mutate trusted-publisher or external runtime state without explicit + authorization for that exact action.