Files
justme 5b1bf09eb0
ci/woodpecker/push/web-build Pipeline was successful
ci/woodpecker/push/verify Pipeline was successful
ci/woodpecker/push/e2e Pipeline was successful
ci: drop the backend e2e step from the dev image pipeline
2026-10-21 15:45:29 +08:00

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 outside Fleet.Hosting.ConfigStore are 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 against docs/security/security.md.
  • backend/fleet/** must not reference MoShiro.* (ArchitectureTests). MoShiro.Measurement contains 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.Api must not reference Storage. Error-code to HTTP mapping happens once, in the Api layer.
  • Server-sent parameters pass ParamSpec validation 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 in docs/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 status before editing. Preserve existing uncommitted changes; do not reset, clean, stash, or commit unrelated files.
  • main is 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 main runs 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.PATCH runs the full cross-platform release pipeline. No version-bump commit is needed.
  • Versions are produced by ci/version.sh. The <Version> in backend/Directory.Build.props and the version in web package.json files are placeholders (0.0.0-dev) and must not be edited.
  • Linux Agent builds use ci/build-linux-agent.sh for 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 prune on these stores: it removes restore caches too.
  • Development images use the moshiro-dev/ repository path and release images use moshiro/. A development build must never overwrite a release tag such as latest.
  • Release manifests are registered at /api/release/offer, which requires no token because the panel verifies the signature.