8.7 KiB
Agent Instructions
MoShiro is a self-hosted network path quality monitor. Agents on home broadband, NAT networks, or public VPS hosts run active measurements and record raw per-packet and per-event data. The Backend stores it, derives metrics, scores lines per service model, and serves a REST/SSE API to two web apps. Documentation is in Chinese under docs/; source comments are mostly Chinese too. README.md is the entry point.
Mental model
| Term | Meaning |
|---|---|
| Agent | Unified collector process (NativeAOT, BCL only), listening and dialing by default. Each Agent connects to the Backend over wss and reports outgoing link health and incoming sessions. |
| Line | One directed (dialer, listener) Agent pair, per IP family. Id <agent_id>~<dialer_id>, IPv6 adds ~ipv6; series key line:<dialer_id> |
| Kind | A declared measurement method (udp_echo, tcp_echo, connect, ...) composed from building blocks. Defined once in MoShiro.Protocol/Catalog/Kinds |
| RawChunk | Self-describing columnar block, cut every 10 s, appended to segment files. The Backend never trusts node-reported statistics |
| Metric, Model | MetricDef is a one-line declaration over accumulators; models score metrics at query time. Both are recomputable from raw data |
| Plan | A sequence of on-demand test phases (for example hy2_ladder). Exists only in the Backend (Application/Tests/Plans.cs) |
| Fleet | Product-agnostic node framework under backend/fleet/ (identity, enrollment, RPC, link, outbox, state sync) |
| Operator set | Passkey-signed trust root. Nodes pin its genesis fingerprint and owner at install time and verify the chain themselves |
Invariants (violations fail the build or review)
- Node processes are kept to measurement and reporting by build-time restrictions: process start, dynamic loading,
HttpClient, and file writes outsideFleet.Hosting.ConfigStoreare banned (backend/BannedSymbols.Node.txt). Capabilities such as updates or command execution are not part of the core; adding or changing one needs a design review againstdocs/security/security.md. backend/fleet/**must not referenceMoShiro.*(ArchitectureTests).MoShiro.Measurementcontains no service concepts such as REALITY or Hysteria2.- Every RPC method is declared in a method table (
FleetMethodTable,MoShiroMethodTable) with direction, type and roles. Add the declaration before the handler. Backend.Apimust not referenceStorage. Error-code to HTTP mapping happens once, in the Api layer.- Server-sent parameters pass
ParamSpecvalidation and then the node-local hard limits (BudgetGuard). Never bypass either. - Public API responses contain no IP, city or ASN.
- Code style is enforced at build time (
.editorconfig,BannedSymbols.txt, warnings as errors). Details indocs/dev/coding-style.md.
Where to change what
| Task | Location |
|---|---|
| New measurement method | Kind declaration in backend/shared/MoShiro.Protocol/Catalog/Kinds; new building block only if needed in MoShiro.Measurement/Blocks plus BlockCatalog |
| New metric | MetricDef in backend/src/MoShiro.Backend.Analysis/Metrics, add to MetricRegistry.All and a preset if shown |
| New service model | Analysis/Models |
| New RPC method | MoShiro.Protocol/Rpc (params, MoShiroMethodTable), then router.On(...) in AgentApp; Backend-side handlers register in Backend.Gateway (FleetGateway) |
| New REST endpoint | Backend.Api/Public or Admin (typed results, operationId, capability), contract DTO in Api/Contracts, then regenerate backend/openapi/v1.json and web types |
| New capability | Capability constants in Backend.Application/Auth/Capabilities.cs; every /api/admin endpoint must declare one |
| Schema change | Append a migration in Storage.Sqlite/Schema.cs and bump CurrentVersion |
| Agent-to-Agent connection states, retry cadence, health reporting | backend/agent/src/MoShiro.Agent/Dial (DialConnection control layer, TaskLink QUIC channel, LinkStatus), LinkHealth in MoShiro.Protocol/Rpc, docs/design/architecture.md §4.3 |
| Install or update behaviour | packaging/ (install scripts, Quadlet, compose, updater) and docs/ops/deployment.md |
| Web UI | web/display (anonymous read-only), web/admin, shared code in web/shared. Colors only in web/shared/theme/tokens.css |
Documentation
Index: README.md. Prefer the code and backend/openapi/v1.json when they disagree with a document, and fix the document. Update docs in the same change as behaviour: docs/design (architecture, protocol, measurement, analysis, storage, query), docs/security, docs/api, docs/ops, docs/dev, and docs/roadmap.md for unimplemented work. Do not record dates or change history in docs.
Writing style for docs, READMEs, comments and commit messages (the stop-slop skill lists the patterns in detail; it is written for English, the same rules apply to Chinese):
- State the fact directly. Drop "not X but Y" contrasts, negation lists, rhetorical setups, and aphorisms that read like pull-quotes.
- Name the actor. Prefer "the Agent rejects the task" over "the task is rejected".
- No filler openers ("it is worth noting"), no closing summaries, no adverbs doing emphasis. Avoid bold for emphasis.
- Do not claim absolutes ("never", "always", "cannot") unless the code or a build-time check enforces it. Describe current behaviour and mark planned work as planned.
- Give concrete names, paths, values and commands instead of general statements.
Workspace safety
- Inspect
git statusbefore editing. Preserve existing uncommitted changes; do not reset, clean, stash, or commit unrelated files. mainis the only working branch. Commit to it directly; use a pull request when review is required.- Never commit credentials, API keys, registry passwords, or generated runtime data. CI credentials are Woodpecker secrets (
zot_secret,gitea_token,release_signing_key). - The release signing private key must not enter the repository or the panel. Only the public key under
packaging/update/is versioned.
Build and test
Requirements: .NET SDK 10 (pinned by global.json) and Node.js with npm. NuGet versions are centralized in Directory.Packages.props.
| Task | Command |
|---|---|
| Build all .NET projects | dotnet build MoShiro.slnx -c Release |
| Backend tests | cd backend && dotnet test --solution MoShiro.slnx -c Release |
| Run Backend | cd backend && dotnet run --project src/MoShiro.Backend -- --urls http://localhost:5000 |
| Web dependencies and build | npm ci --prefix web && npm run build --prefix web |
| Web dev servers | npm run dev --prefix web (ports are set in the Vite configs) |
| Style check | npm run lint:css --prefix web |
| Regenerate API types | npm run gen:api --prefix web |
First run of the Backend prints a claim code in its log; the admin UI asks for it. Slow end-to-end tests carry [Trait("Category", "Slow")]. After changing API contracts, update backend/openapi/v1.json and regenerate the web types. Run only the validation the task requires; do not start a full tag or release build unless requested.
CI and releases
Triggers, tags and image paths are defined in .woodpecker/*.yml and docs/ops/deployment.md. Verify them there before changing or describing them. The rules below are the stable contract.
- Every push to
mainruns the fast Backend tests and the web build. Both must pass before images are published. - A commit message containing
[CI]builds and pushes development images.[CI SKIP]skips the pipeline;[SKIP TESTS]skips only the Backend tests. Slow end-to-end tests run only for pushes without[CI]and for pull requests. - A tag
vMAJOR.MINOR.PATCHruns the full cross-platform release pipeline. No version-bump commit is needed. - Versions are produced by
ci/version.sh. The<Version>inbackend/Directory.Build.propsand theversioninwebpackage.jsonfiles are placeholders (0.0.0-dev) and must not be edited. - Linux Agent builds use
ci/build-linux-agent.shfor glibc on amd64/arm64 and musl on arm64 in both dev and tag workflows. OCI and OpenWrt installers reuse these native outputs; Windows runners build only Windows/macOS. - Build stores keep NuGet cache mounts, retain image layers for 7 days, and clean temporary outputs under store locks (shared for native builds, exclusive for cleanup). Do not use
buildah pruneon these stores: it removes restore caches too. - Development images use the
moshiro-dev/repository path and release images usemoshiro/. A development build must never overwrite a release tag such aslatest. - Release manifests are registered at
/api/release/offer, which requires no token because the panel verifies the signature.