ARCHITECTURE.md:
- Note optional ?name=/&type= query filters on GET /v1/zones/{zone}/records
- Document ListRecordsRequest name/type fields as optional filters in gRPC service
- Add gRPC usage examples section with grpcurl commands
CLAUDE.md:
- Add mcdsl shared library section
- Add testing patterns (stdlib only, real SQLite, no mocks)
- Add key invariants: SOA serial YYYYMMDDNN format, CNAME exclusivity at DB layer
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
93 lines
3.3 KiB
Markdown
93 lines
3.3 KiB
Markdown
# CLAUDE.md
|
|
|
|
## Overview
|
|
|
|
MCNS (Metacircular Networking Service) is an authoritative DNS server for
|
|
the Metacircular platform. It serves DNS zones from SQLite, forwards
|
|
non-authoritative queries to upstream resolvers, and exposes a gRPC/REST
|
|
management API authenticated through MCIAS.
|
|
|
|
## Build Commands
|
|
|
|
```bash
|
|
make all # vet → lint → test → build
|
|
make build # go build ./...
|
|
make test # go test ./...
|
|
make vet # go vet ./...
|
|
make lint # golangci-lint run ./...
|
|
make proto # regenerate gRPC code from .proto files
|
|
make proto-lint # buf lint + buf breaking
|
|
make mcns # build mcns binary with version injection
|
|
make docker # build container image
|
|
make clean # remove binaries
|
|
make devserver # build and run against srv/ config
|
|
```
|
|
|
|
Run a single test: `go test ./internal/dns/ -run TestHandlerA`
|
|
|
|
## Architecture
|
|
|
|
Three listeners on one binary:
|
|
|
|
- **DNS server** (`:53`, UDP+TCP) — serves authoritative zones from SQLite,
|
|
forwards everything else to upstream resolvers. No authentication.
|
|
- **REST API** (`:8443`) — management API for zones and records. MCIAS auth.
|
|
- **gRPC API** (`:9443`) — same management operations. MCIAS auth.
|
|
|
|
Records stored in SQLite. Changes visible to DNS immediately on commit.
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
cmd/mcns/ CLI entry point (server, snapshot, status)
|
|
internal/
|
|
config/ TOML config with DNS-specific sections
|
|
db/ SQLite schema, migrations, zone/record queries
|
|
dns/ DNS server, handler, forwarder, cache
|
|
server/ REST API routes and handlers
|
|
grpcserver/ gRPC server, interceptors, service handlers
|
|
proto/mcns/v1/ Protobuf definitions
|
|
gen/mcns/v1/ Generated Go code (do not edit)
|
|
deploy/ Docker, systemd, install scripts, examples
|
|
```
|
|
|
|
## Ignored Directories
|
|
|
|
- `srv/` — local dev runtime data
|
|
- `gen/` — regenerated from proto, not hand-edited
|
|
|
|
## Shared Library
|
|
|
|
MCNS uses `mcdsl` (git.wntrmute.dev/kyle/mcdsl) for shared platform packages:
|
|
auth, db, config, httpserver, grpcserver. These provide MCIAS authentication,
|
|
SQLite database helpers, TOML config loading, and TLS-configured HTTP/gRPC
|
|
server scaffolding.
|
|
|
|
## Testing Patterns
|
|
|
|
- Use stdlib `testing` only. No third-party test frameworks.
|
|
- Tests use real SQLite databases in `t.TempDir()`. No mocks for databases.
|
|
|
|
## Key Invariants
|
|
|
|
- **SOA serial format**: YYYYMMDDNN, auto-incremented on every record mutation.
|
|
If the date prefix matches today, NN is incremented. Otherwise the serial
|
|
resets to today with NN=01.
|
|
- **CNAME exclusivity**: Enforced at the DB layer within transactions. A name
|
|
cannot have both CNAME and A/AAAA records. Attempts to violate this return
|
|
`ErrConflict`.
|
|
|
|
## Critical Rules
|
|
|
|
1. **REST/gRPC sync**: Every REST endpoint must have a corresponding gRPC
|
|
RPC, updated in the same change.
|
|
2. **gRPC interceptor maps**: New RPCs must be added to the correct
|
|
interceptor map (Public, AuthRequired, AdminRequired). Forgetting this
|
|
is a security defect.
|
|
3. **CNAME exclusivity**: A name cannot have both CNAME and A/AAAA records.
|
|
Enforced in the database layer within a transaction.
|
|
4. **SOA serial**: Auto-incremented on every record mutation. Never manually
|
|
set or decremented.
|
|
5. **DNS has no auth**: Port 53 serves records to any client. All mutations
|
|
go through the authenticated management API.
|