summaryrefslogtreecommitdiff
path: root/AGENTS.md
blob: 8886c0be443d8da0a0908ff896751f91321f77af (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# wg-wrap Agent Guidelines

This document defines the architectural conventions, project layout, and system assumptions for the development of `wg-wrap`.

## Project Goals
`wg-wrap` is a transparent userspace VPN wrapper that allows native Linux processes to communicate over WireGuard without requiring host-level root privileges. It utilizes User and Network namespaces to isolate traffic and a userspace WireGuard implementation to handle encryption.

## Project Layout
The project follows a modern Go project structure to ensure scalability and a clear separation between public APIs and internal implementation details.

```text
.
├── Makefile              # Handles the C-to-Go embedding build chain
├── cmd/
│   └── wg-wrap/           # CLI Entry point. Handles flag parsing and subcommand routing.
├── internal/
│   ├── cli/               # Command line interface and bootstrap orchestration.
│   ├── config/            # Application-wide configuration types.
│   ├── namespace/         # Linux namespace management (unshare, setns, pinning).
│   │   └── launcher_src/   # C source for the rootless bootstrap helper.
│   └── wireguard/         # Userspace WireGuard controller and TUN device binding.
├── pkg/
│   └── wgconf/            # WireGuard .conf parsing logic. Reusable library.
├── tests/
│   └── e2e/               # End-to-End "Data Plane" tests using Virtual Peers.
├── go.mod                 # Module definition.
└── README.md              # Project overview and design specification.
```

## Development Conventions

### 1. Quality Assurance Pipeline
No piece of code is considered "done" until it has passed the full verification pipeline. Every implementation cycle must conclude with the following checks:

1. **Formatting**: `go fmt ./...`
2. **Static Analysis**: `go vet ./...`
3. **Linting**: `golangci-lint run`
4. **Verification**: `go test -timeout 30s ./...`

If any of these tools report an error or warning, the code must be corrected before the task is marked as complete.

### 2. Testing & Stubbing Conventions
To maintain a high-velocity development cycle without sacrificing correctness, we follow these rules for incomplete code:

- **Code Stubs**: Any unimplemented logic path must be explicitly marked with a `// TODO` comment and return a descriptive error (e.g., `fmt.Errorf("feature X not yet implemented")`).
- **Test Stubs**: Any test that is planned but not yet implementable must use `t.Skip("not implemented")` and include a comment describing the specific scenario the test is intended to verify.
- **Hermetic Configuration**: Tests involving profiles, settings, or filesystem state must not touch the actual user home directory. Use the `ConfigDir` injection pattern in the `App` struct combined with `t.TempDir()` to create isolated, temporary test environments.
- **Performance & Reliability**:
    - **Parallelism**: Use `t.Parallel()` in integration and E2E tests. Use `t.TempDir()` to ensure resource isolation.
    - **Granular Timeouts**: All system calls, network operations, and external command executions must be wrapped in a `context.WithTimeout` (typically 2-5 seconds) to prevent hanging tests.
    - **Interface Mocking**: Use interfaces for "heavy" system operations (e.g., routing, namespace creation) to allow fast unit testing of logic via mocks, reserving real syscalls for the integration tier.
    - **Shared Fixtures**: Use `sync.Once` or `TestMain` for expensive setup (e.g., Virtual Peer) to avoid redundant boot-ups across tests.

### 3. Platform Compatibility & Build Constraints
`wg-wrap` is fundamentally a Linux system tool. To ensure the module remains compilable on other platforms while restricting Linux-specific syscalls, we use the following patterns:

- **Build Tags**: All files interacting with `golang.org/x/sys/unix`, network namespaces, or TUN devices must start with `//go:build linux`.
- **The Stub Pattern**: For any platform-specific logic in `internal/`, we provide a matching stub file tagged with `//go:build !linux`. This allows the project to compile on non-Linux OSs, returning "not supported" errors at runtime rather than failing at build time.
- **Platform Agnosticism**: `pkg/` libraries (e.g., `pkg/wgconf`) must remain platform-agnostic and avoid any OS-specific imports to ensure they are reusable across all environments.

### 4. Testing Strategy
We employ a three-tier testing approach to balance speed and reliability:

| Tier | Location | Type | Scope | Requirement |
| :--- | :--- | :--- | :--- | :--- |
| **Unit** | Package dirs | `go test` | Pure logic (e.g., parsing, validation) | None |
| **Integration** | `internal/**/*_test.go` | `go test -tags=integration` | Syscalls, Namespace creation, Routing | Linux |
| **E2E** | `tests/e2e/` | `go test ./tests/e2e/...` | Full data path (Connect $\rightarrow$ Curl $\rightarrow$ Peer) | Linux + TUN access |

### 2. Platform Constraints
- **Target OS**: Linux only.
- **Build Tags**: Use `//go:build linux` or `//go:build linux,integration` for any code interacting with `golang.org/x/sys/unix` or network namespaces.
- **MTU**: Always default the TUN device MTU to `1420` to account for WireGuard overhead.

### 3. Namespace Lifecycle
- **Creation**: `CLONE_NEWUSER` $\rightarrow$ `CLONE_NEWNET`.
- **Persistence**: Namespaces are pinned by bind-mounting the namespace file to `/run/user/$UID/wg-wrap/profiles/<name>`.
- **Cleanup**: The tool must monitor the wrapped process and ensure the namespace is unpinned/torn down via `wg-wrap profile stop` or upon process termination.

## System Assumptions
The project assumes the target environment is a modern Linux system configured for rootless container operations (e.g., Podman is installed and functional):
- **User Namespaces**: `kernel.unprivileged_userns_clone=1` is assumed.
- **UID Mapping**: SubUIDs/SubGIDs are configured.
- **TUN Access**: The user has permission to access `/dev/net/tun`.
- **Tooling**: The `ip` command (iproute2) is available in the environment.

## Roadmap Priority
1. **Configuration**: Implement robust `.conf` parsing in `pkg/wgconf`.
2. **Bootstrapping**: Implement the `unshare` and user-mapping flow in `internal/namespace`.
3. **Data Path**: Integrate `wireguard-go` with the TUN device in `internal/wireguard`.
4. **Routing**: Automate the isolated routing table setup.
5. **Lifecycle**: Implement namespace pinning and cleanup.