Add Codex specific files
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
# Codex Implementation Flow
|
||||
|
||||
## Project configuration
|
||||
|
||||
The project configuration is `.codex/config.toml`. It selects GPT-6-Sol with
|
||||
medium reasoning for the primary coordinator and GPT-6-Luna with high reasoning
|
||||
as the default for spawned agents. Custom project agents are discovered from
|
||||
`.codex/agents/`:
|
||||
|
||||
| Agent | File | Responsibility |
|
||||
| ------------- | -------------------------------- | --------------------------------------------------- |
|
||||
| `implementer` | `.codex/agents/implementer.toml` | Implement a bounded task and focused tests |
|
||||
| `reviewer` | `.codex/agents/reviewer.toml` | Independently review actual changes without editing |
|
||||
| `repairer` | `.codex/agents/repairer.toml` | Resolve findings and provide regression evidence |
|
||||
| `explorer` | `.codex/agents/explorer.toml` | Optional read-only prerequisite research |
|
||||
|
||||
All four custom agents explicitly select GPT-6-Luna/high. There is no separate
|
||||
coordinator subagent: the primary session is the coordinator. At most three
|
||||
spawned threads run concurrently, but file ownership defaults to one writer.
|
||||
|
||||
## Starting work
|
||||
|
||||
Open a fresh Codex session in this project, using a client that supports the
|
||||
documented project configuration and custom agents. Project trust, managed
|
||||
requirements, and explicit client/session overrides can affect which settings
|
||||
are applied. Verify the coordinator and spawned-agent model/effort settings in
|
||||
the client before implementation; report unavailable models rather than silently
|
||||
substituting alternatives. Existing sessions are not reconfigured by these files.
|
||||
|
||||
An example execution request is:
|
||||
|
||||
> Execute the next pending milestone in PLANS.md. Use implementer for bounded
|
||||
> implementation, a fresh reviewer for independent review, and repairer for
|
||||
> findings. Repeat review and repair until the acceptance gates pass, update
|
||||
> PLANS.md with evidence, and stop after accepting this milestone or recording
|
||||
> a concrete blocker. Use explorer only when prerequisite research is needed.
|
||||
|
||||
For an explicitly authorized full-plan run, continue to the next milestone only
|
||||
after the current one is accepted. Do not confuse this project's Commit action
|
||||
with permission to create Git commits.
|
||||
|
||||
## Flow and limitations
|
||||
|
||||
The root instructions define prepare, implement, review, repair, re-review, and
|
||||
acceptance. PLANS.md is the durable record of milestone/task IDs, ownership,
|
||||
progress, findings, validation, and blockers. The TOML files configure model
|
||||
selection and agent instructions; they do not implement a deterministic workflow
|
||||
engine or automatically start execution.
|
||||
|
||||
Reviewer/explorer read-only behavior is an instruction boundary, not a distinct
|
||||
OS sandbox. Custom agents inherit the parent's permission controls. This setup
|
||||
does not change sandbox, approvals, provider, MCP access, or user-level trust.
|
||||
|
||||
Container tests require a disposable Alpine Testcontainers environment, and real
|
||||
systemd validation requires a separate disposable VM; see [TESTING.md](TESTING.md).
|
||||
No role is authorized to experiment on production.
|
||||
|
||||
## Verification status
|
||||
|
||||
The files were parsed as TOML and checked for consistent role names and requested
|
||||
model/effort values. A live model session and subagent dispatch were not started.
|
||||
The installed CLI reports version 0.161.0. Its `features` command does not support
|
||||
`--strict-config`, so that command cannot establish complete schema validation.
|
||||
|
||||
Official references:
|
||||
|
||||
- [Subagents and custom agent files](https://learn.chatgpt.com/docs/agent-configuration/subagents)
|
||||
- [Configuration reference](https://learn.chatgpt.com/docs/config-file/config-reference)
|
||||
@@ -0,0 +1,40 @@
|
||||
# Dependency Policy and Approved Choices
|
||||
|
||||
Read this document before changing dependencies, features, or build/runtime requirements. The approved choices may be introduced without renewed approval; unapproved direct dependencies require prior user agreement.
|
||||
|
||||
## Approved dependencies
|
||||
|
||||
The user has approved the following choices. They may be introduced when their implementation stage needs them without requesting approval again. Approval does not mean they are already installed. Select compatible maintained versions and minimal features, and record exact resolved versions in `Cargo.lock`.
|
||||
|
||||
| Purpose | Approved crates | Intended use |
|
||||
| --------------------------- | ---------------------- | -------------------------------------------------------------------- |
|
||||
| Terminal UI | `ratatui`, `crossterm` | Widgets, layout, keyboard events, terminal lifecycle |
|
||||
| Serialization and settings | `serde`, `toml` | Typed application settings and metadata; TOML backup manifests |
|
||||
| Typed errors | `thiserror` | Recoverable domain and adapter errors |
|
||||
| Address ranges | `ipnet` | IPv4/IPv6 subnet validation and allocation support |
|
||||
| Dates | `time` | UTC metadata, backup timestamps, handshake display |
|
||||
| QR encoding | `qrcode` | Additional terminal delivery of client configurations |
|
||||
| Backup archives | `tar` | Archives with manifests; initially without compression |
|
||||
| Temporary files | `tempfile` | Staged file replacement and isolated test directories |
|
||||
| Linux operations | `rustix` | User checks and controlled low-level filesystem operations |
|
||||
| Encrypted vault | `age` | Recipient encryption and password protection of the vault secret key |
|
||||
| WireGuard key pairs | `x25519-dalek` | Key generation and public/private key matching |
|
||||
| Secure randomness | `getrandom` | Operating-system randomness for key generation |
|
||||
| WireGuard key encoding | `base64` | Reading and writing WireGuard key representations |
|
||||
| Secret handling | `secrecy`, `zeroize` | Explicit secret exposure and supported memory cleanup |
|
||||
| WireGuard runtime | `wireguard-uapi` | Direct Linux interface, peer, handshake, and traffic queries |
|
||||
| Service management | `zbus` | Direct systemd D-Bus requests and job completion tracking |
|
||||
| Container integration tests | `testcontainers` | Alpine server/client lifecycle; development dependency only |
|
||||
|
||||
- Use a separate vault key pair from all WireGuard client/server key pairs. Encrypt each client secret to the vault public key; protect the vault secret key with password-based encryption using the established `age` format. Do not replace this with password-only encryption of every new client record, which would require a password on creation.
|
||||
- Validate `wireguard-uapi` against the isolated integration environment before relying on it. A systemd D-Bus request being accepted is not proof of job completion or successful VPN application.
|
||||
- Avoid incompatible duplicate versions of secret-handling types where library APIs exchange them. Use supported re-exports where appropriate rather than adding redundant direct dependencies.
|
||||
- Additional direct dependencies still require the comparison and prior agreement required by [AGENTS.md](../AGENTS.md), including any test/build helpers. Transitive dependencies of approved crates are resolved through Cargo; review their compatibility and runtime requirements. Do not add a direct `tokio` dependency merely because an approved library uses an async runtime internally.
|
||||
- `clap`, `chrono`, SQLite, a generic INI writer, a mocking framework, and archive compression libraries are not part of the approved initial set. Use the standard library for the small startup argument surface and background threads/channels where sufficient.
|
||||
|
||||
### External runtime and build requirements
|
||||
|
||||
- Production requires Linux with WireGuard support, the existing configured systemd service, and the system D-Bus needed by `zbus`. Existing `wg-quick` service dependencies remain necessary if that is how the service manages the interface.
|
||||
- The application uses library APIs rather than invoking `wg`, `systemctl`, `age`, `qrencode`, `tar`, or `openssl` for its own operations. Test fixture setup and the existing WireGuard service may use their required system tools; that does not create an application subprocess fallback.
|
||||
- Rust/Cargo and the target toolchain/linker are build requirements, not production application requirements. Verify the release binary's actual dynamic-library requirements rather than promising an automatically static executable.
|
||||
- A Docker-API-compatible runtime, test images, and container tools belong to the integration environment only. Production does not need Docker or Testcontainers.
|
||||
@@ -0,0 +1,69 @@
|
||||
# Engineering Guidelines
|
||||
|
||||
Read the relevant sections before implementing filesystem, secret-handling, terminal, or system operations. These detailed rules supplement [AGENTS.md](../AGENTS.md); they remain applicable after being moved out of the automatically loaded instructions.
|
||||
|
||||
## Product boundaries
|
||||
|
||||
- Build a native Rust TUI for root on a Linux VPN server, managing one existing WireGuard interface and a configurable systemd service.
|
||||
- Use public keys as client identities. Aliases may repeat; selection and destructive actions must resolve to a public key, not an alias or row position alone.
|
||||
- Keep the server configuration as the source of truth. Modify only client `[Peer]` sections and associated managed metadata comments. Preserve all other settings and administrator comments byte-for-byte. Do not fully reserialize the file through a generic INI writer.
|
||||
- Model draft, saved, and applied state explicitly. **Commit writes files and the vault only. It must never reload, sync, restart, or otherwise change the running VPN.** Restore also changes saved state only.
|
||||
- Restart is a separate explicit action. Check systemd completion, interface presence, and saved client correspondence before marking changes applied or releasing deleted clients' addresses.
|
||||
- Allocate IPv4 and IPv6 from configured ranges and generate full-tunnel client configurations. Preserve existing IPv4-only clients and existing connection parameters.
|
||||
- Preserve original client files during import. Report anomalies; do not silently repair discrepancies or invent unknown creation dates.
|
||||
- Do not add multi-interface support, remote management, initial VPN server setup, concurrent edit reconciliation, automatic restart rollback, traffic history, or additional connection settings to version 1.
|
||||
|
||||
## Architecture and implementation order
|
||||
|
||||
Follow [IMPLEMENTATION.md](IMPLEMENTATION.md): model/settings, preserving configuration edits, keys/vault, backups/Commit/restore, runtime adapter, delivery/TUI, then acceptance documentation and target build.
|
||||
|
||||
- Separate pure domain logic from filesystem, cryptography, WireGuard, systemd, and terminal adapters. The TUI invokes application operations rather than implementing their rules in key handlers.
|
||||
- Keep changes and state transitions testable without root, a terminal, a running VPN, or a real service manager. Prefer narrow interfaces and simple types over speculative frameworks.
|
||||
- Resolve settings relative to the executable, not the working directory. Default data paths are `Backup/data` and `Backup/archives` alongside the executable. Honor configured paths; do not substitute system-wide installation directories.
|
||||
- Distinguish current data from archives. Never include previous archives recursively in a backup.
|
||||
- Identify and document versioned formats for managed comments, the vault, and backup manifests before persisting them. Reject unsupported versions with actionable errors rather than guessing.
|
||||
- Keep runtime statistics separate from desired configuration. Missing runtime data is unknown/unavailable, not zero traffic, a successful apply, or proof of a disconnected client.
|
||||
|
||||
## Rust and dependency practices
|
||||
|
||||
- Prefer maintained Rust libraries where appropriate. A TUI library, QR library, and established cryptographic format are legitimate dependencies. A single native executable does not mean a dependency-free build.
|
||||
- New dependencies outside the approved list in [DEPENDENCIES.md](DEPENDENCIES.md) are allowed, but require prior agreement with the user. Before adding one, establish the need, compare suitable alternatives (including existing dependencies or the standard library where applicable), and recommend the best fit with its trade-offs. Add the dependency only after the user agrees to the choice; do not modify dependency manifests or lockfiles to introduce it before that agreement. This applies to runtime, build, and development dependencies.
|
||||
- Check official crate documentation and compatibility before choosing versions. Add only needed features and dependencies; record any unavoidable runtime system utility and why it is necessary.
|
||||
- Commit `Cargo.lock` for the application once the project is initialized. Keep builds reproducible; do not force dependency updates unrelated to the task.
|
||||
- Use typed errors and `Result` for recoverable failures. Add operation/path context without exposing secrets. Avoid `unwrap`, `expect`, and panics in production paths that handle files, user input, archives, cryptography, or services.
|
||||
- Validate input at boundaries: keys, aliases, endpoint, address families/ranges, paths, and service name. Reject aliases containing line breaks or control sequences that could inject configuration or terminal content. Do not enumerate an entire IPv6 subnet to find an address.
|
||||
- Avoid unnecessary `unsafe`. If required by a low-level interface, isolate it and document its safety invariants. Keep privileged operations out of build scripts.
|
||||
- Use a direct supported API where practical. If an external program is necessary, pass arguments explicitly without a shell, check its exit status, bound its execution time, and redact sensitive output. Never execute arbitrary configuration text as a shell command.
|
||||
|
||||
## Files, secrets, and backups
|
||||
|
||||
- Require root for actual management operations; ordinary builds and tests must not require root or change host services.
|
||||
- Use established asymmetric encryption and password protection with operating-system randomness. Do not design cryptographic primitives or silently weaken password protection for convenience.
|
||||
- Encrypt new client secrets with the vault public key without prompting. Require a password separately for each client reissue; do not retain an unlocked vault across unrelated operations.
|
||||
- Keep plaintext secrets short-lived and use secret-handling/zeroization facilities where supported. Exclude passwords, private keys, complete client configurations, and secret-bearing command output from logs, errors, `Debug` output, snapshots, and fixtures. Explicit file/QR delivery is the intended disclosure path.
|
||||
- Do not bypass reissue authentication by falling back to retained plaintext source files. Original files remain untouched, but their presence is not an alternative password mechanism.
|
||||
- First delivery is allowed only after a successful Commit in the client's creation session. Preserve retry eligibility after failed file output, including a change of directory. After successful delivery or application exit, require the password for reissue.
|
||||
- Always save a normal client configuration file when delivering; QR is additional. Confirm before overwriting an existing file. Create secret-bearing files with mode `0600` and private directories with mode `0700` from the start, including temporary files.
|
||||
- Use same-directory temporary files and atomic replacement where applicable. Handle write, flush, and rename errors. For operations involving multiple files, define failure/recovery behavior explicitly; a partially written state must not be reported as a successful Commit. This is write integrity, not concurrent editing support.
|
||||
- Guard privileged file operations against unintended symlink traversal and unsafe archive paths. Validate archive contents and permitted destinations before replacement; reject traversal, link escapes, and unexpected entries. Do not blindly extract an archive over the filesystem.
|
||||
- Create a completed backup before every Commit, restore, and restart. Backup failure must stop that operation before its protected mutations. Backups include settings, server configuration, internal metadata, and the complete encrypted vault; exclude drafts and original client files.
|
||||
- Restoring is a previewed, confirmed full replacement with a precautionary backup, not a merge. It requires no vault password and never implicitly restarts WireGuard. Server paths are invariant; do not add migration machinery.
|
||||
- Do not label the newest archive as known-working merely because it exists. Track verified application status separately. Do not delete old archives automatically.
|
||||
- The vault password does not encrypt the entire backup or server private key. Keep this distinction accurate in documentation and UI.
|
||||
|
||||
## Terminal and console behavior
|
||||
|
||||
- Keep the TUI responsive during filesystem, cryptographic, and service operations. Show progress and actionable failures; do not block the input/render loop indefinitely or allow duplicate submission of an operation in progress.
|
||||
- Support keyboard navigation, visible focus, discoverable shortcuts, cancellation, terminal resizing, and readable empty/error states. Do not convey draft, unapplied, or anomalous state by color alone.
|
||||
- Restore raw mode, alternate screen, and cursor visibility on normal exit, errors, and handled interruptions, including panic cleanup where feasible. Avoid mixed diagnostic output corrupting the active screen.
|
||||
- Require a suitable terminal before entering interactive mode. Provide plain diagnostics and a nonzero exit status if interactive startup is impossible. Support conventional `--help` and `--version` without requiring root or reading the vault.
|
||||
- Keep diagnostics on stderr outside the TUI, reserve stdout for intentional output, and avoid terminal escape sequences when output is redirected. Do not invent a separate scripting interface as part of version 1.
|
||||
- Treat aliases, imported comments, filenames, and external error strings as untrusted display text; escape terminal control characters. Mask password input.
|
||||
- Make destructive confirmations identify the selected client or archive unambiguously. Before restart/exit, offer the specified draft-discard confirmation; cancellation keeps the current draft. Never silently commit on exit.
|
||||
- Display last-handshake time and current byte counters, not an inferred online flag or historical totals. Bound periodic refresh work and report unavailable statistics without terminating the management session.
|
||||
|
||||
## Completion report and maintenance
|
||||
|
||||
For each delivered change, state what works, which specification behavior it covers, what was checked, and any remaining limitations. Separate unit/fixture results from dedicated real-system integration results. Do not call a milestone complete while its acceptance criteria remain unverified.
|
||||
|
||||
Keep examples synthetic and documentation synchronized with actual commands, formats, paths, and recovery behavior. Keep AGENTS.md concise; maintain detailed guidance in these supporting documents, requirements in the specification, and implementation rationale in ADRs.
|
||||
@@ -0,0 +1,63 @@
|
||||
# Project Layout
|
||||
|
||||
Read this document when creating or reorganizing modules. The paths below are planned until implemented.
|
||||
|
||||
## Target project layout
|
||||
|
||||
Start with one Cargo package containing a binary (`src/main.rs`) and a library (`src/lib.rs`). Keep startup, argument handling, and process exit in `main.rs`; place testable application logic in library modules. A library target does not require publishing a separate library package. Introduce a workspace only when independently reusable or separately built components justify it.
|
||||
|
||||
The following is the intended layout, not a claim that these files already exist. Create modules and directories as implementation requires them; do not generate empty scaffolding for the entire tree.
|
||||
|
||||
```text
|
||||
Cargo.toml
|
||||
Cargo.lock
|
||||
AGENTS.md
|
||||
CONTEXT.md
|
||||
PLANS.md
|
||||
README.md
|
||||
.gitignore
|
||||
src/
|
||||
main.rs # Startup, arguments, process exit
|
||||
lib.rs # Module declarations and application API
|
||||
config.rs # Application settings and path resolution
|
||||
domain.rs # Clients, identities, address allocation, change states
|
||||
app.rs # Application operations and orchestration
|
||||
wireguard.rs # Server configuration module boundary
|
||||
wireguard/
|
||||
document.rs # Parsing and edits preserving original text
|
||||
metadata.rs # Managed client comment blocks
|
||||
vault.rs # Encryption, import, secret retrieval
|
||||
backup.rs # Backup archives and restoration
|
||||
runtime.rs # Running WireGuard interface and statistics
|
||||
service.rs # Systemd operations and restart verification
|
||||
delivery.rs # Client configuration files and QR generation
|
||||
tui.rs # Terminal UI entry point
|
||||
tui/
|
||||
state.rs # Screen state and navigation
|
||||
events.rs # Keyboard and background events
|
||||
render.rs # Rendering
|
||||
terminal.rs # Terminal setup and cleanup
|
||||
tests/
|
||||
config_preservation.rs # Untouched server configuration remains identical
|
||||
commit_restore.rs # Persistence, backups, restore, runtime isolation
|
||||
client_lifecycle.rs # Import, creation, delivery, deletion, state transitions
|
||||
fixtures/ # Synthetic configuration and archive inputs
|
||||
support/
|
||||
mod.rs # Shared test adapters and helpers
|
||||
config/
|
||||
wireguard-admin.example.toml # Safe example; settings format chosen at implementation
|
||||
docs/
|
||||
SPEC.md
|
||||
IMPLEMENTATION.md
|
||||
adr/
|
||||
target/ # Cargo output; never commit
|
||||
```
|
||||
|
||||
- Use modules named for their responsibility. Avoid catch-all `utils`, `helpers`, or `common` modules; place supporting code with its owner.
|
||||
- Begin with a single module file and split into child modules when needed. Prefer `name.rs` with `name/child.rs` for production modules; `tests/support/mod.rs` keeps test helpers from becoming a separate integration test target.
|
||||
- Declare application modules once in the library, rather than duplicating them in both `main.rs` and `lib.rs`. Keep internals private or `pub(crate)`; expose only the library API needed by the binary and behavioral integration tests.
|
||||
- Keep focused unit tests beside their modules under `#[cfg(test)]`; put cross-module behavioral tests in `tests/`. Use `tests/support/` for test-only adapters rather than exporting test infrastructure from the production library.
|
||||
- The `config/` directory contains distributable examples, not live settings. The example filename above is illustrative and does not settle the settings format. Actual settings remain alongside the deployed executable as specified.
|
||||
- Keep live server configurations, private keys, delivered client files, and runtime `Backup/` data out of the source tree and version control. Ignore generated build output and local deployment data without hiding synthetic fixtures.
|
||||
- Add `examples/` only for runnable Rust examples and `benches/` only when benchmarks are needed. Do not add empty directories or scripts that duplicate Cargo commands.
|
||||
- Keep the layout aligned with actual module responsibilities as the code grows. Update this section when files move; do not preserve obsolete paths merely to match the initial tree.
|
||||
@@ -0,0 +1,64 @@
|
||||
# Testing and Acceptance
|
||||
|
||||
Read this document when writing tests, verifying a milestone, or preparing an integration environment. Required behavior and acceptance criteria remain governed by [the specification](SPEC.md).
|
||||
|
||||
## Validation
|
||||
|
||||
Use fixtures, temporary directories, and replaceable system adapters by default. Never modify `/etc/wireguard`, restart a host service, read production private keys, or test recovery against the live VPN during ordinary development. Real integration tests must be explicitly selected for a dedicated disposable environment; installing WireGuard on the development host is not enough.
|
||||
|
||||
Before Cargo scaffolding exists, validate documentation links and consistency only; do not report build/test commands as passing. Once the Rust project exists, run the relevant focused tests during development and these completion checks for Rust changes:
|
||||
|
||||
```sh
|
||||
cargo fmt --all -- --check
|
||||
cargo clippy --locked --all-targets -- -D warnings
|
||||
cargo test --locked
|
||||
cargo build --locked --release
|
||||
```
|
||||
|
||||
Use only supported feature combinations; do not assume `--all-features` is valid. Keep privileged integration tests out of the default test suite. If a check cannot run, report the exact limitation rather than claiming success. Documentation-only edits do not require rebuilding the application.
|
||||
|
||||
Prioritize meaningful behavioral checks:
|
||||
|
||||
- Configuration round trips preserve untouched bytes, unknown fields, and administrator comments; managed metadata cannot escape its comment block.
|
||||
- Commit/restore do not invoke runtime mutation; draft cancellation, saved/applied differences, and address reservation survive the intended transitions.
|
||||
- Allocation respects both ranges, occupied/server addresses, exhaustion, and deferred address reuse without IPv6-wide iteration.
|
||||
- Import verifies keys, preserves source files, and distinguishes missing counterparts from parameter conflicts.
|
||||
- Encryption works without a password; reissue handles correct/incorrect passwords, corruption, and first-delivery retry boundaries without leaking secrets.
|
||||
- Backup failures prevent mutation; restoration works without decryption, excludes recursive archives, and rejects unsafe archive entries.
|
||||
- Systemd success without a matching interface/client set is not marked applied; timeouts and failed restarts remain visible without automatic rollback.
|
||||
- File and QR delivery encode the same configuration; file failures, overwrite confirmation, non-TTY startup, resizing, and terminal cleanup behave correctly.
|
||||
|
||||
Test externally observable behavior and high-impact failure paths. Avoid tests that merely repeat implementation details, introduce root requirements, or assert real secrets in snapshots. Broaden testing when failures or new risks justify it.
|
||||
|
||||
## Integration testing with Alpine Testcontainers
|
||||
|
||||
Production access is limited and experimentation on the production VPN is prohibited. Use three complementary levels: ordinary unit/fixture tests, explicitly selected Alpine container integration tests, and a separate disposable Linux VM for real systemd/D-Bus acceptance. No level authorizes using production as a test environment.
|
||||
|
||||
### Alpine environment
|
||||
|
||||
- Use `testcontainers` to start separate Alpine Linux server and client containers on a dedicated test network. Keep the image minimal: `wireguard-tools`, `iproute2`, and only any additional tools actually needed by the fixture. Alpine is not a systemd test environment.
|
||||
- Build and cache the fixture image ahead of repeated test runs. Pin the Alpine base/version or digest and document the image recipe; avoid package installation and image rebuilding for every test. Reuse image layers, not mutable containers or secret-bearing volumes between tests.
|
||||
- The Docker host must provide Linux kernel WireGuard support. Containers share that kernel; installing userspace tools in Alpine does not supply it. Probe prerequisites in the disposable environment and report missing capabilities clearly. Do not automatically load host modules or change host settings.
|
||||
- Grant `NET_ADMIN` in the test containers for their own network namespaces. Do not default to `--privileged`, `SYS_MODULE`, host networking, or shared host PID namespaces. Configure IPv6 for the dedicated test network as needed; exercise both address families.
|
||||
- Run the application operations or a test driver linked to the real library inside the server container, including the real `wireguard-uapi` adapter. A host-side test harness may orchestrate containers, but must not query or modify the host's WireGuard interface as a shortcut.
|
||||
- Build the in-container executable for Alpine compatibility, preferably the matching musl target. Do not assume a glibc-linked host binary runs in Alpine. Keep compiler/toolchain layers out of the small runtime fixture image where practical.
|
||||
- Generate synthetic server/client keys and configurations for each test. Copy fixtures into container-local filesystems. Never mount production files, the host's `/etc/wireguard`, host system D-Bus sockets, or the Docker socket inside fixture containers.
|
||||
- Poll explicit readiness and handshake/traffic conditions with deadlines rather than fixed sleeps. Always clean up containers, dedicated networks, and temporary resources after success or failure. Keep diagnostic artifacts redacted.
|
||||
|
||||
### Required container scenarios
|
||||
|
||||
1. Start an isolated server and existing client, establish a tunnel, and read real peer state through the runtime adapter.
|
||||
2. Create a dual-stack client through the application, Commit, and verify saved files/vault plus unchanged running peer state. Deliver the client configuration and verify that it cannot connect before explicit application.
|
||||
3. Use a test-only fixture operation to apply the saved configuration inside the container. Establish the new tunnel, generate IPv4/IPv6 traffic, and verify handshake and increasing counters without asserting exact byte totals.
|
||||
4. Delete a client and Commit; verify it is removed from saved data but remains in running state until explicit application, and its address remains reserved. After verified application, check removal, loss of tunnel access, and address release.
|
||||
5. Exercise backups and restoration against container-local data: restoration requires no vault password and does not mutate running state. Verify that applying the restored configuration returns the expected clients.
|
||||
6. Cover mandatory-backup failure and invalid client import with assertions about unchanged protected state and preserved source files.
|
||||
|
||||
Any fixture apply/restart adapter is test-only. It must not weaken the production requirement for a separate systemd restart or be reported as testing the production `zbus` implementation. If application orchestration uses the fixture service adapter, label those results accordingly.
|
||||
|
||||
### Systemd acceptance and test execution
|
||||
|
||||
- Use a disposable Linux VM with WireGuard, systemd, and a system D-Bus to verify the actual `zbus` service adapter, job completion/timeouts, restart verification, and recovery from a selected backup. Do not substitute a mounted host D-Bus or claim Alpine tests cover systemd.
|
||||
- Keep container and VM suites out of the default `cargo test` execution. Once implemented, document their exact opt-in commands and prerequisites in this document. Do not list a planned command as available before its test target exists.
|
||||
- When integration testing is explicitly requested, unavailable Docker, WireGuard support, IPv6, or required capabilities means the suite is not executed or incomplete, not passed. Distinguish prerequisite failures from application failures in the report.
|
||||
- Report unit/fixture results, Alpine real-WireGuard results, and VM real-systemd results separately. Full acceptance requires the relevant real-system checks, not just mocks or successful container startup.
|
||||
Reference in New Issue
Block a user