Skip to content

Commit 977619a

Browse files
committed
Refresh CLAUDE.md's stale architecture/config description (P5)
CLAUDE.md described a flat pre-restructuring layout (internal/app as the run-core, top-level appletalk/router/port/service/pkg/config directories, koanf+go-toml config parsing, [LToUdp]/[TashTalk]/ [Volumes.*] TOML sections) that predates the current five-ring core/adapter/compose/client/cmd structure ARCHITECTURE.md already documents accurately and keeps current -- contributors reading CLAUDE.md first were getting conflicting guidance. Replaced the stale "Core Data Flow"/"Key Packages" section with a short accurate summary of each ring plus a strong pointer to ARCHITECTURE.md as the authoritative source, rather than hand- maintaining a second package table that would just go stale again. Also fixed: the go test example path (./service/afp/... -> ./core/service/afp/...), the CNID-tracking claim (defaults to in-memory, not SQLite -- sqlite is an opt-in build tag), the config-parsing claim (koanf isn't even in go.mod anymore; go-toml/v2 only) and its TOML section names (checked against the real server.toml.example: [[afpvolumes]], [[smbshares]], [MacIP], etc., not the stale [AFP]/[Volumes.*]/[LToUdp] spellings), and the hardcoded Go version (now points at go.mod instead of duplicating a number that will drift again). Also removed an accidental duplicated "### AFP Architecture" heading from the edit. Verified every cited path/file exists, and that the two example commands (go build .../cmd/classicstack, go test .../core/service/afp/...) actually work. Docs-only change; full repo build/vet/test swept clean (one core/service/browser flake under full-suite load on the first pass, gone on rerun -- confirmed pre-existing/unrelated, this commit touches only CLAUDE.md). This closes out P5's items worth doing now: the P0 csconnect stale-comment note turned out already resolved by P0 itself, and the runport.go/ntcreate.go TODOs are deliberately-deferred design decisions the plan says to leave alone. The diagnostic-tool shared- flags helper remains open (cosmetic-only, no bug) if wanted later.
1 parent 6868091 commit 977619a

1 file changed

Lines changed: 37 additions & 50 deletions

File tree

CLAUDE.md

Lines changed: 37 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ ClassicStack is a Go-based AppleTalk Phase 2 router and AFP file server. It also
88
It bridges legacy Apple networking protocols to modern environments, supporting EtherTalk (raw Ethernet), LToUDP (multicast UDP), TashTalk (serial), and virtual LocalTalk transports.
99

1010
**Module:** `github.com/ObsoleteMadness/ClassicStack`
11-
**Go version:** 1.23.0
11+
**Go version:** see `go.mod` (`go` directive) — kept current there, not duplicated here
1212

1313
## Remember!
1414
1. Always confirm implementation details with the specifications found in /spec/*.md
@@ -32,10 +32,10 @@ It bridges legacy Apple networking protocols to modern environments, supporting
3232
go build -tags all -o classicstack ./cmd/classicstack
3333

3434
# Run all tests
35-
go test ./...
35+
go test -tags all ./...
3636

3737
# Run tests for a specific package
38-
go test ./service/afp/...
38+
go test -tags all ./core/service/afp/...
3939

4040
# Run with TOML config
4141
./classicstack # auto-loads server.toml if present
@@ -46,63 +46,50 @@ go test ./service/afp/...
4646

4747
## Architecture
4848

49-
### Core Data Flow
50-
51-
```
52-
cmd/classicstack/main.go → internal/app (run-core) → Ports → Router → Services
53-
```
54-
55-
1. **Entry point** (`cmd/classicstack/`) is a thin `main()` that calls `internal/app`, which parses CLI flags and `server.toml`, constructs ports, wires them to the router, and starts services. Two sibling commands wrap the same run-core for background operation: `cmd/classicstack-svc` (Windows service) and `cmd/classicstackd` (Unix/macOS daemon).
56-
2. **Router** (`router/`) receives DDP datagrams from all ports, maintains the `RoutingTable` and `ZoneInformationTable`, and dispatches to services by socket number or forwards to other ports.
57-
3. **Ports** (`port/`) abstract network interfaces. All implement `port.Port` (Unicast/Broadcast/Multicast). Implementations: `ethertalk`, `localtalk/ltoudp`, `localtalk/tashtalk`, `localtalk/virtual`.
58-
4. **Services** (`service/`) plug into the router by registering socket numbers. Each implements `service.Service`.
59-
60-
### Key Packages
61-
62-
| Package | Role |
63-
|---|---|
64-
| `internal/app/` | The run-core (formerly `cmd/classicstack` package `main`): flag/TOML parsing, the `Supervisor`, every `wireXxx` hook, control-plane + web UI wiring. Exposes `Main(Version)` and `Run(ctx, args, Version)` so the interactive binary and the service/daemon wrappers all share one runtime. |
65-
| `cmd/classicstack/` | Thin interactive entry point (`main()``app.Main`); holds the link-time `Build*` vars (`-ldflags -X main.Build...`). |
66-
| `cmd/classicstack-svc/` | Windows service wrapper (SCM via `golang.org/x/sys/windows/svc`); `install`/`uninstall`/`start`/`stop`/`status`/`run`. Stub on non-Windows. |
67-
| `cmd/classicstackd/` | Unix/macOS background daemon (self-daemonize via fork+`Setsid`, PID file); `start`/`stop`/`status`/`run`, plus macOS LaunchAgent `install`/`uninstall`. Stub on Windows. |
68-
| `appletalk/` | DDP datagram struct, encode/decode, MacRoman codec |
69-
| `router/` | Core routing engine, routing table aging, zone info |
70-
| `port/ethertalk/` | EtherTalk over raw Ethernet using libpcap/Npcap, includes AARP |
71-
| `port/localtalk/` | LocalTalk base; subpackages: LToUDP (UDP multicast 239.192.76.84:1954), TashTalk (serial at 1 Mbit/s), Virtual |
72-
| `service/rtmp/` | Routing Table Maintenance Protocol — `RespondingService` + `SendingService` |
73-
| `service/zip/` | Zone Information Protocol — `RespondingService` + `SendingService` |
74-
| `service/afp/` | Apple Filing Protocol file server (largest subsystem, 35 files) |
75-
| `service/asp/` | AppleTalk Session Protocol — AFP transport over DDP |
76-
| `service/atp/` | AppleTalk Transaction Protocol — reliable messaging |
77-
| `service/dsi/` | Data Stream Interface — AFP transport over TCP |
78-
| `service/macip/` | IP-over-AppleTalk gateway with NAT and DHCP relay |
79-
| `core/service/ncp/` | Novell NetWare Core Protocol file server (NetWare 3.x bindery emulation) over IPX + SAP advertising (`-tags ncp`); reuses the AFP/SMB storage + auth seams. See `spec/17-ncp.md` |
80-
| `adapter/control/http/` | Management web UI (`-tags webui`): HTTPS adapter over `pkg/control` — JSON API, Finder over `/finder`, SSE stats stream, Vite SPA (`make spa`) |
81-
| `pkg/control/` | Transport-agnostic management API (status, config stage/apply/save, service start/stop/restart, diagnostics); the single contract every UI front-end shares |
82-
| `pkg/status/` | In-process service-status registry read by the dashboard |
83-
| `pkg/metrics/` | Streaming stats hub (expvar + SSE sinks) |
84-
| `pkg/logbuf/` | In-memory log ring buffer + `slog.Handler` + broadcaster feeding the web UI log viewer (installed via `logging.Options.Extra`) |
85-
| `pkg/serialport/` | Per-OS serial-port enumeration for the TashTalk dropdown |
86-
| `config/` | Config loader plus `Model` (in-memory, editable, serialisable view of `server.toml` with numbered-backup Save) |
87-
| `netlog/` | Structured logger with debug/info/warn levels |
88-
89-
The `cmd/classicstack` `Supervisor` owns the whole runtime: it builds ports, the
90-
router (and its DDP service set), and the standalone hooks from the config
91-
`Model`, and exposes per-service Start/Stop/Restart (dependency-aware) that the
92-
web UI drives through `pkg/control`. `main.go` only parses flags / loads TOML,
93-
builds the `Model`, and hands off to the supervisor.
49+
ClassicStack is a hexagonal (ports-and-adapters) architecture split into five
50+
rings — `core/`, `adapter/`, `compose/`, `client/`, `cmd/` — plus a `hardware/`
51+
tree for embedded targets. **[`ARCHITECTURE.md`](ARCHITECTURE.md) is the
52+
authoritative, maintained description of this layout** (the ring diagram, the
53+
per-ring import rules, the full package map, and how a request moves through
54+
the system); read it before orienting in the tree. Summary:
55+
56+
- **`core/`** — protocol-pure logic: wire codecs (`core/protocol/*`), the
57+
router (`core/router`), file/network services (`core/service/*`), the
58+
storage seam (`core/fs`, `core/share`, `core/metastore`). Imports stdlib
59+
only (enforced by `core/internal/archtest`), so it stays TinyGo-safe for the
60+
embedded targets under `hardware/`.
61+
- **`adapter/`** — the real world: `adapter/link` (pcap/ltoudp/tashtalk NICs),
62+
`adapter/control` (http/ubus/inproc management front-ends), `adapter/config`,
63+
`adapter/store`, `adapter/metastore`, `adapter/fork`. May import `core/`.
64+
- **`compose/`** — wiring only: `compose/registry` (name → factory),
65+
`compose/runtime` (build + cross-wire), `compose/supervisor` (lifecycle,
66+
dependency-ordered start/stop). Turns a `config.Model` into a running,
67+
supervised stack. May import `core/` and `adapter/`.
68+
- **`client/`** — the outbound mirror of the server: `client/afp`,
69+
`client/smb`, `client/ncp`, `client/etherdfs` dial a remote server and
70+
present it as an `fs.FileSystem` via `client/link`'s transport `Opener`.
71+
- **`cmd/`** — thin entry points only. `cmd/classicstack/main.go` hands off
72+
immediately to `cmd/internal/cli`, the shared run-core that parses flags/
73+
`server.toml`, builds the `compose/runtime` stack, optionally serves the
74+
web-admin control API (`-tags webui`), and runs until SIGINT/SIGTERM.
75+
`cmd/classicstack-svc` (Windows service) and `cmd/classicstackd` (Unix/macOS
76+
daemon) wrap the same run-core for background operation. `cmd/cs-tinygo` is
77+
the embedded compile-smoke target (blank-imports the TinyGo-safe `core/`
78+
subset); `cmd/csfs`/`cmd/csmount`/`cmd/csclient` are file-client CLIs over
79+
the `client/` SDK; the rest (`cmd/csecho`, `cmd/csnbp`, …) are AppleTalk/IPX
80+
diagnostic probes.
9481

9582
### AFP Architecture
9683

9784
AFP supports two transport stacks simultaneously:
9885
- **Classic:** DDP → ATP → ASP → AFP
9986
- **Modern:** TCP → DSI → AFP
10087

101-
AppleDouble metadata is stored either as `._filename` sidecars or in `.appledouble/` folders (Netatalk-compatible). CNID tracking uses SQLite (`modernc.org/sqlite`).
88+
AppleDouble metadata is stored either as `._filename` sidecars or in `.appledouble/` folders (Netatalk-compatible). CNID tracking (`core/metastore`) defaults to an in-memory store; the `sqlite` build tag swaps in a SQLite-backed one (`modernc.org/sqlite`) instead.
10289

10390
### Configuration
10491

105-
Copy `server.toml.example` to `server.toml`. Format is TOML (parsed via `knadh/koanf` + `pelletier/go-toml`). Sections: `[LToUdp]`, `[TashTalk]`, `[EtherTalk]`, `[MacIP]`, `[AFP]`, `[Volumes.*]`, `[Logging]`. File extension→type/creator mappings live in `extmap.conf` (Netatalk-compatible format).
92+
Copy `server.toml.example` to `server.toml`. Format is TOML (`pelletier/go-toml`), loaded into `core/config.Model` (see `core/config/config.go`). Section keys mirror the example file: singletons like `[identity]`, `[router]`, `[MacIP]`, `[http]`; repeated (named-instance) sections like `[[ethertalk]]`, `[[ltoudp]]`, `[[afpvolumes]]`, `[[smbshares]]`. File extension→type/creator mappings live in `extmap.conf` (Netatalk-compatible format). Full key-by-key reference: [`docs/config.md`](docs/config.md).
10693

10794
### Protocol Specifications
10895

0 commit comments

Comments
 (0)