Add Codex specific files
This commit is contained in:
@@ -0,0 +1,13 @@
|
|||||||
|
name = "explorer"
|
||||||
|
description = "Read-only discovery of repository paths, APIs, prerequisites, and bounded task context before implementation."
|
||||||
|
model = "gpt-6-luna"
|
||||||
|
model_reasoning_effort = "high"
|
||||||
|
developer_instructions = """
|
||||||
|
Read AGENTS.md and the assigned PLANS.md context. Investigate only the requested
|
||||||
|
repository paths, official API documentation, or disposable test prerequisites.
|
||||||
|
Use targeted searches and report facts with file/symbol or primary-source links.
|
||||||
|
Do not edit files, install dependencies, run mutating probes, inspect production
|
||||||
|
secrets, start milestones, delegate, or change host services/network settings.
|
||||||
|
Identify uncertain assumptions and concrete blockers separately from verified
|
||||||
|
facts. Return a concise handoff with relevant interfaces and next checks.
|
||||||
|
"""
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
name = "implementer"
|
||||||
|
description = "Implement one bounded task in the active milestone, with focused tests and reproducible evidence."
|
||||||
|
model = "gpt-6-luna"
|
||||||
|
model_reasoning_effort = "high"
|
||||||
|
developer_instructions = """
|
||||||
|
You are the implementation worker, not the coordinator. Read AGENTS.md, PLANS.md,
|
||||||
|
and the specification/ADRs relevant to the assigned task. Work only within the
|
||||||
|
coordinator's file ownership and scope. Preserve unrelated changes and interfaces.
|
||||||
|
Use only approved dependencies. Ask the coordinator to resolve missing scope or
|
||||||
|
interface decisions; do not invent new product requirements or delegate further.
|
||||||
|
Write meaningful behavioral tests and run the assigned available checks.
|
||||||
|
Commit saves files only; restore never implicitly applies; restart is separate.
|
||||||
|
Protect secrets and untouched server configuration. No production access or host
|
||||||
|
service/network changes. Container tests use the approved isolated Alpine setup.
|
||||||
|
Do not mark milestones accepted, change PLANS.md, create Git commits, or deploy.
|
||||||
|
Report changed files, exact commands/results, assumptions, remaining limitations,
|
||||||
|
and the next action. Redact secrets; never claim unexecuted tests passed.
|
||||||
|
"""
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
name = "repairer"
|
||||||
|
description = "Resolve specific review findings in assigned files and verify fixes without broadening milestone scope."
|
||||||
|
model = "gpt-6-luna"
|
||||||
|
model_reasoning_effort = "high"
|
||||||
|
developer_instructions = """
|
||||||
|
Read AGENTS.md, the active PLANS.md milestone, governing requirements, and the
|
||||||
|
assigned review findings. Reproduce or establish each issue, fix its cause in
|
||||||
|
owned files, and add focused regression coverage where useful. Preserve unrelated
|
||||||
|
changes. Use approved dependencies only; do not silently change requirements,
|
||||||
|
remove failing assertions to hide defects, or weaken security/integration gates.
|
||||||
|
No production access, host service/network changes, further delegation, plan
|
||||||
|
acceptance updates, Git commits, or deployment. Follow the isolated Alpine/VM
|
||||||
|
methodology when integration checks are assigned and available.
|
||||||
|
Report each finding ID as fixed, unresolved, or disputed with concrete evidence.
|
||||||
|
Include changed files, exact checks/results, remaining risks, and re-review needs.
|
||||||
|
Return to the coordinator/reviewer; your report does not close the milestone.
|
||||||
|
"""
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
name = "reviewer"
|
||||||
|
description = "Independently inspect implementation and repair results against milestone acceptance criteria; do not edit files."
|
||||||
|
model = "gpt-6-luna"
|
||||||
|
model_reasoning_effort = "high"
|
||||||
|
developer_instructions = """
|
||||||
|
Act as an independent reviewer. Read AGENTS.md, the assigned PLANS.md milestone,
|
||||||
|
and governing specification/ADRs. Inspect the actual changes and affected paths;
|
||||||
|
do not rely on an implementer's summary. Do not edit files, accept milestones,
|
||||||
|
change plans, or delegate. Safe tests may create temporary/generated output only.
|
||||||
|
Prioritize correctness, regressions, secret handling, byte preservation, backup
|
||||||
|
failure behavior, saved/applied separation, and meaningful acceptance coverage.
|
||||||
|
Check test claims against evidence; mocks and Alpine cannot establish real
|
||||||
|
systemd behavior. Never access production or change host network/services.
|
||||||
|
Return actionable findings with stable IDs, severity, file/line, impact,
|
||||||
|
reproduction or evidence, and expected correction. Avoid speculative/style-only
|
||||||
|
findings. Re-review repairs and affected regressions when asked. Report no
|
||||||
|
findings explicitly when justified, together with checks and coverage limits.
|
||||||
|
The coordinator alone decides milestone acceptance.
|
||||||
|
"""
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
# Project-scoped defaults. Existing sessions may retain their model overrides.
|
||||||
|
model = "gpt-6-sol"
|
||||||
|
model_reasoning_effort = "medium"
|
||||||
|
|
||||||
|
developer_instructions = """
|
||||||
|
Coordinate implementation using AGENTS.md and PLANS.md. Do not start milestones
|
||||||
|
merely because this configuration was loaded; act on the user's current request.
|
||||||
|
When milestone execution is requested, execute milestones in ascending order and
|
||||||
|
advance only after acceptance. Own task boundaries, interface decisions, plan
|
||||||
|
updates, and acceptance evidence. Delegate bounded implementation to implementer,
|
||||||
|
independent read-only review to reviewer, targeted fixes to repairer, and optional
|
||||||
|
read-only prerequisite research to explorer. All subagents use GPT-6-Luna/high;
|
||||||
|
do not silently substitute models or reasoning levels. Do not review a worker's
|
||||||
|
own implementation using that same worker as the independent reviewer.
|
||||||
|
Use the loop prepare -> implement -> review -> repair -> re-review -> accept.
|
||||||
|
Continue until acceptance checks pass or a concrete external blocker is recorded.
|
||||||
|
Keep one implementation writer at a time unless tasks have disjoint ownership.
|
||||||
|
Dispatch milestone/task IDs, relevant document sections, owned files, preserved
|
||||||
|
interfaces, approved dependencies, exact checks, and required report contents.
|
||||||
|
Verify actual changed files and evidence; worker confidence is not acceptance.
|
||||||
|
Only the coordinator updates PLANS.md acceptance state. Report unavailable
|
||||||
|
required checks as incomplete. Do not access production, use real private keys,
|
||||||
|
or weaken sandbox/approval policies. Use the approved Alpine Testcontainers and
|
||||||
|
disposable systemd VM strategy; Alpine results do not prove systemd behavior.
|
||||||
|
"""
|
||||||
|
|
||||||
|
[agents]
|
||||||
|
enabled = true
|
||||||
|
max_concurrent_threads_per_session = 3
|
||||||
|
default_subagent_model = "gpt-6-luna"
|
||||||
|
default_subagent_reasoning_effort = "high"
|
||||||
@@ -16,3 +16,4 @@ target/
|
|||||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
#.idea/
|
#.idea/
|
||||||
|
/.obsidian/
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
# Agent Instructions
|
||||||
|
|
||||||
|
## Start here
|
||||||
|
|
||||||
|
These instructions apply to the entire repository. Keep documentation, code comments, and identifiers in English; use the user's language in conversation.
|
||||||
|
|
||||||
|
The project currently contains design/configuration documents, not an implemented Rust application. Update this statement when scaffolding is created. Do not report planned code, tests, or commands as already working.
|
||||||
|
|
||||||
|
- Read [SPEC.md](docs/SPEC.md) and [CONTEXT.md](CONTEXT.md) before implementing behavior. The approved specification is the product contract; do not change it to make tests pass.
|
||||||
|
- For milestone execution, read and maintain [PLANS.md](PLANS.md), following [IMPLEMENTATION.md](docs/IMPLEMENTATION.md). Execute numbered milestones sequentially through implementation, independent review, repair, and acceptance with evidence.
|
||||||
|
- Read the relevant ADRs: [explicit restart](docs/adr/0001-explicit-restart.md), [client secrets](docs/adr/0002-client-secret-storage.md), [server configuration authority](docs/adr/0003-server-config-authority.md).
|
||||||
|
- Read task-specific supporting documents below before editing that area. Their requirements remain applicable; moving them out of this file does not make them optional.
|
||||||
|
- Preserve unrelated user changes. Resolve specific requirement conflicts before implementing affected behavior; continue independent work. Do not reopen settled decisions or seek approval for routine implementation choices.
|
||||||
|
|
||||||
|
## Non-negotiable behavior
|
||||||
|
|
||||||
|
- Native Rust TUI, root management, one existing WireGuard interface, configurable systemd service. No production experimentation, remote management, server bootstrap, concurrent edit reconciliation, or automatic restart rollback.
|
||||||
|
- Public keys identify clients; aliases may repeat. The server configuration is authoritative. Modify only client `[Peer]` sections and managed metadata blocks; preserve all other settings and administrator comments byte-for-byte. Do not fully reserialize through a generic INI writer.
|
||||||
|
- **Commit saves files/vault only. Restore also changes saved state only. Neither may reload, sync, restart, or mutate the running VPN.** Keep draft, saved, and applied states distinct.
|
||||||
|
- Restart is explicit. Require successful systemd job completion and interface/client verification before marking applied or releasing deleted-client addresses.
|
||||||
|
- Complete a backup before every Commit, restore, and restart; backup failure stops the operation before protected mutations. Restore is a previewed, confirmed full replacement without a vault password or implicit restart.
|
||||||
|
- Preserve original imported files. Report anomalies rather than repairing them silently. New clients get IPv4/IPv6 and full-tunnel routes; preserve existing client parameters and IPv4-only clients.
|
||||||
|
- Settings are executable-relative; default working data is `Backup/data`, archives `Backup/archives`. Never substitute working-directory or system-wide defaults.
|
||||||
|
- Encrypt new secrets without a password using the vault public key. Protect the separate vault secret key with a password. Reissue requires a password per client; retained plaintext files must not bypass it. First delivery follows Commit and supports retry after file failure within the creation session.
|
||||||
|
- Never expose secrets through logs, errors, Debug, or snapshots. Explicit file/QR delivery is the disclosure path. Use synthetic fixtures only; keep real keys/configs/output and working backups out of version control.
|
||||||
|
|
||||||
|
## Development rules and reference map
|
||||||
|
|
||||||
|
| When working on | Read first |
|
||||||
|
| --------------------------------------------------------- | ------------------------------------------- |
|
||||||
|
| Module layout and boundaries | [PROJECT_LAYOUT.md](docs/PROJECT_LAYOUT.md) |
|
||||||
|
| Dependencies, Cargo features, build/runtime requirements | [DEPENDENCIES.md](docs/DEPENDENCIES.md) |
|
||||||
|
| Rust, persistence, secrets, archives, terminal behavior | [DEVELOPMENT.md](docs/DEVELOPMENT.md) |
|
||||||
|
| Tests, acceptance evidence, Alpine containers, systemd VM | [TESTING.md](docs/TESTING.md) |
|
||||||
|
| Codex model configuration and custom roles | [CODEX.md](docs/CODEX.md) |
|
||||||
|
|
||||||
|
- Start with one Cargo package, thin `main.rs`, and testable library modules. Separate domain/application logic from filesystem, cryptography, WireGuard, systemd, and TUI adapters. Create modules as needed, not as empty scaffolding.
|
||||||
|
- **Dependencies outside the approved list require comparison of alternatives and explicit user agreement before changing manifests/lockfiles.** Approved crates may be added when needed without asking again. Apply the rule to runtime, build, and development dependencies.
|
||||||
|
- Select compatible versions/minimal features using official documentation; retain Cargo.lock and avoid unrelated upgrades. Use established cryptography, not custom primitives.
|
||||||
|
- Use typed errors/Result; avoid panics for recoverable input/I/O failures. Validate boundary inputs, escape terminal control text, and keep errors secret-free. Bound external operations; never execute configuration text through a shell.
|
||||||
|
- Create secret files/private directories with `0600`/`0700`, including temporary files. Handle partial writes honestly; validate archive destinations and reject traversal/link escapes.
|
||||||
|
- Keep TUI input/rendering responsive, restore the terminal on errors/exit, mask passwords, and identify destructive targets unambiguously. Cancel preserves drafts; never silently commit on exit. Help/version require neither root nor vault access.
|
||||||
|
|
||||||
|
## Agents and acceptance
|
||||||
|
|
||||||
|
Coordinator: **GPT-6-Sol / medium**. Implementation, independent review, repairs, and optional exploration: **GPT-6-Luna / high**, using the configured `implementer`, `reviewer`, `repairer`, and `explorer` roles. Configure actual models through the harness; do not impersonate or silently substitute them.
|
||||||
|
|
||||||
|
The coordinator owns task boundaries, PLANS.md updates, and acceptance. Default to one writer; parallel writes require disjoint ownership. Use a separate reviewer from the implementer, repair actionable findings, and verify integrated results before advancing. Do not create Git commits, publish, or deploy merely because a milestone is accepted.
|
||||||
|
|
||||||
|
Build/test without root by default. Never read production private keys, modify production configuration, restart host services, or use the live VPN for testing. Alpine Testcontainers suites are opt-in and isolated; actual systemd/D-Bus acceptance requires a disposable VM. Unavailable prerequisites mean incomplete validation, not success.
|
||||||
|
|
||||||
|
After Rust scaffolding exists, run focused behavioral checks and these completion gates for Rust changes:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cargo fmt --all -- --check
|
||||||
|
cargo clippy --locked --all-targets -- -D warnings
|
||||||
|
cargo test --locked
|
||||||
|
cargo build --locked --release
|
||||||
|
```
|
||||||
|
|
||||||
|
Do not assume all feature combinations are supported. Documentation-only edits require link/consistency checks, not an application rebuild. Report what changed, actual checks/results, and remaining limitations; distinguish fixture, Alpine, and VM evidence. Maintain the plan before handoff and never claim a milestone complete with unmet acceptance criteria.
|
||||||
@@ -0,0 +1,188 @@
|
|||||||
|
# Execution Plan
|
||||||
|
|
||||||
|
## Purpose and authority
|
||||||
|
|
||||||
|
This is the living execution plan for WireGuard Admin version 1. It records milestone scope, progress, review findings, and evidence so a new agent can resume from repository files without relying on chat history.
|
||||||
|
|
||||||
|
Read [AGENTS.md](AGENTS.md), [the specification](docs/SPEC.md), [architectural decisions](docs/adr/), [implementation order](docs/IMPLEMENTATION.md), and [the glossary](CONTEXT.md) before execution. The specification defines behavior; this plan schedules its delivery. Approved dependencies and Alpine/VM testing rules are in AGENTS.md. Do not change requirements to make a milestone pass.
|
||||||
|
|
||||||
|
Creating this plan does not start implementation or change the active model. All milestones below are initially pending, and no validation results are claimed.
|
||||||
|
|
||||||
|
## Model roles
|
||||||
|
|
||||||
|
| Role | Required model | Reasoning effort | Responsibility |
|
||||||
|
| --------------------- | ------------------------- | ---------------- | --------------------------------------------------------------------------------------------------------- |
|
||||||
|
| Coordinator | GPT-6-Sol (`gpt-6-sol`) | `medium` | Refine tasks, dispatch workers, resolve interfaces, verify results, maintain this plan, accept milestones |
|
||||||
|
| Implementation worker | GPT-6-Luna (`gpt-6-luna`) | `high` | Implement a bounded task and its meaningful tests |
|
||||||
|
| Independent reviewer | GPT-6-Luna (`gpt-6-luna`) | `high` | Review the actual changes and evidence against acceptance criteria |
|
||||||
|
| Repair worker | GPT-6-Luna (`gpt-6-luna`) | `high` | Fix review findings and regressions, then report new evidence |
|
||||||
|
|
||||||
|
These are the user's explicit model choices, not suggestions. Configure them through the execution harness, not by merely telling an agent to impersonate a model. In a harness using `spawn_agent`, use `model="gpt-6-luna"`, `reasoning_effort="high"`, and `fork_turns="none"` for workers; supply their context explicitly. Do not silently substitute another model. If the required model or effort is unavailable, report the limitation before starting affected execution. This Markdown file cannot switch the calling coordinator's model.
|
||||||
|
|
||||||
|
## Sequential execution and ownership
|
||||||
|
|
||||||
|
- Number milestones with integers starting at **1**. Keep IDs stable, never renumber accepted work or reuse IDs. Append new milestones using the next available integer; add bounded tasks within a milestone when finer scope is needed.
|
||||||
|
- Execute milestones in ascending order. Start the next milestone only after the current milestone is accepted. Do not bypass an unmet gate because a later task looks independent.
|
||||||
|
- The coordinator owns PLANS.md, task boundaries, interface agreements, and acceptance. Workers report proposed plan updates; they do not independently mark milestones accepted.
|
||||||
|
- Default to one implementation writer at a time. Independent tasks within the active milestone may run concurrently only with explicit disjoint file ownership and agreed interfaces. Do not let agents overwrite one another's edits or run competing Cargo manifest/lockfile changes.
|
||||||
|
- Use subagents for current-task work, not new user-owned chats. Reviewers should be separate agents from implementers and initially read-only. Further delegation must remain within the coordinator's assigned scope and model policy.
|
||||||
|
- Preserve unrelated user changes. Do not create commits, publish, deploy, or access production merely because a milestone is accepted.
|
||||||
|
|
||||||
|
## Milestone lifecycle and review loop
|
||||||
|
|
||||||
|
Use states `pending`, `in_progress`, `in_review`, `needs_changes`, `blocked`, and `accepted`. A blocked milestone records the concrete missing prerequisite; it is not accepted and its successors remain pending.
|
||||||
|
|
||||||
|
1. **Prepare.** Inspect the actual repository. Expand the active milestone using the template below: concrete files/interfaces, small steps, observable outcomes, exact available commands, and expected results. Identify missing prerequisites before dispatch.
|
||||||
|
2. **Implement.** Give a worker a bounded task brief. It implements only the assigned scope, adds focused behavioral tests, and reports changed files, commands/results, assumptions, and unfinished work.
|
||||||
|
3. **Verify and review.** The coordinator examines the actual files/diff and checks evidence. A fresh reviewer evaluates correctness, regressions, specification/ADR compliance, security-relevant failure paths, and test coverage. Agent confidence or a prose summary is not acceptance evidence.
|
||||||
|
4. **Repair.** Record each actionable finding with an ID, location, impact, expected behavior, and reproduction or validation. Assign a worker to fix it and rerun affected tests. The reviewer rechecks fixes and newly affected behavior.
|
||||||
|
5. **Repeat.** Continue review and repair until findings are resolved and acceptance checks pass. Do not stop at an arbitrary iteration count or repeat an unchanged failing approach. Investigate repeated failures, reduce the task, or record a real external blocker. Settled requirements remain unchanged.
|
||||||
|
6. **Accept.** The coordinator runs milestone gates against the integrated files, records reviewer disposition and validation evidence, updates progress/outcomes, and marks the milestone accepted. Only then advance. Routine acceptance does not require another user approval; new dependencies outside the approved set and unresolved product decisions retain their existing approval rules.
|
||||||
|
|
||||||
|
If a revision invalidates earlier acceptance evidence, record which milestones are affected and reopen the earliest affected milestone before advancing. Keep the integrated state buildable at each accepted milestone.
|
||||||
|
|
||||||
|
## Worker task brief
|
||||||
|
|
||||||
|
Every dispatch must include:
|
||||||
|
|
||||||
|
- Milestone ID, task ID, required model/effort, and role.
|
||||||
|
- User-visible objective, relevant specification sections/ADRs, and prerequisite state.
|
||||||
|
- Explicit read list, owned files, interfaces to preserve, and out-of-scope work.
|
||||||
|
- Approved dependencies needed by this task; no permission to add unapproved dependencies.
|
||||||
|
- Acceptance criteria and commands with expected outcomes; identify tests requiring Docker/VM access.
|
||||||
|
- Safety boundary: synthetic fixtures only, no production keys/services/configuration, no host-network shortcuts.
|
||||||
|
- Required report: changed files, checks actually run and their results, findings/risks, and remaining work. No secrets in reports.
|
||||||
|
|
||||||
|
For reviewers, provide the same objective and criteria plus the change baseline or exact changed-file list. Ask for independent inspection rather than confirmation of the implementer's conclusions.
|
||||||
|
|
||||||
|
## Milestone record template
|
||||||
|
|
||||||
|
Use this structure when expanding each active milestone. Replace placeholders before dispatch; do not interpret them as completed work.
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Milestone <next integer> — <observable outcome>
|
||||||
|
|
||||||
|
Status: pending
|
||||||
|
Prerequisites: <accepted milestone IDs and environment requirements>
|
||||||
|
|
||||||
|
### Outcome and scope
|
||||||
|
<What becomes possible, boundaries, and links to governing requirements.>
|
||||||
|
|
||||||
|
### Context and implementation steps
|
||||||
|
<Actual paths, current state, interfaces, task ownership, and ordered steps.>
|
||||||
|
|
||||||
|
### Acceptance and validation
|
||||||
|
- [ ] <Observable behavior and test/demonstration proving it.>
|
||||||
|
- [ ] <Relevant failure behavior and how it is verified.>
|
||||||
|
Commands: <exact commands, working directory, prerequisites, expected results>
|
||||||
|
|
||||||
|
### Progress
|
||||||
|
- [ ] <Task ID and owner/agent ID; timestamp when updated>
|
||||||
|
|
||||||
|
### Review and repair
|
||||||
|
| Finding | Iteration | Location and impact | Owner | Resolution and evidence | State |
|
||||||
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
|
||||||
|
### Evidence and handoff
|
||||||
|
<Commands actually run, exit/results, artifact paths, reviewer disposition,
|
||||||
|
remaining limitations, next concrete action.>
|
||||||
|
|
||||||
|
### Decisions and discoveries
|
||||||
|
<New facts/trade-offs, reasons, and ADR references when warranted.>
|
||||||
|
|
||||||
|
### Outcome
|
||||||
|
<Coordinator acceptance decision and timestamp, or exact blocker.>
|
||||||
|
```
|
||||||
|
|
||||||
|
Use ISO 8601 timestamps with offsets for progress. Keep evidence concise and reproducible, with redacted excerpts or artifact paths rather than large logs. Distinguish planned commands from executed commands and unavailable checks from passing checks. Keep the plan self-contained by summarizing discoveries that affect the next task, not just linking to an agent conversation.
|
||||||
|
|
||||||
|
## Validation gates
|
||||||
|
|
||||||
|
For Rust milestones, use the relevant focused tests and the formatting, Clippy, default tests, and release-build commands in AGENTS.md. Add exact commands when targets exist; do not invent passing outputs. Unit and fixture checks run without root. Use standard-library test adapters rather than an additional mock framework.
|
||||||
|
|
||||||
|
Container suites are opt-in and use pinned/cached Alpine images, fresh server/client containers, synthetic keys, isolated dual-stack networking, and scoped `NET_ADMIN`. The real runtime adapter executes inside the server container. Missing Docker/kernel/IPv6 prerequisites are incomplete validation, not success. Alpine fixture application is not a production systemd test.
|
||||||
|
|
||||||
|
Actual systemd/D-Bus acceptance runs in a disposable VM. Never use production to fill gaps in test coverage. Final release acceptance requires relevant unit, Alpine WireGuard, and VM systemd results reported separately. Document blockers without silently weakening the gate.
|
||||||
|
|
||||||
|
## Milestone register
|
||||||
|
|
||||||
|
Each row is a delivery milestone, not a completion claim. Expand its record before execution; retain its original ID and acceptance scope.
|
||||||
|
|
||||||
|
| ID | Milestone | Prerequisites | State |
|
||||||
|
| --- | -------------------------------------------------------- | ----------------------------------------- | ------- |
|
||||||
|
| 1 | Rust foundation, settings, and domain states | None | pending |
|
||||||
|
| 2 | Server configuration editing with byte preservation | 1 | pending |
|
||||||
|
| 3 | Client keys, encrypted vault, and existing-client import | 2 | pending |
|
||||||
|
| 4 | Backups, safe Commit, and full restoration | 3 | pending |
|
||||||
|
| 5 | Runtime observation and systemd restart adapter | 4 | pending |
|
||||||
|
| 6 | Client configuration delivery and reissue lifecycle | 5 | pending |
|
||||||
|
| 7 | Complete terminal management workflow | 6 | pending |
|
||||||
|
| 8 | Alpine Testcontainers integration | 7; suitable disposable Docker environment | pending |
|
||||||
|
| 9 | Real systemd acceptance and release readiness | 8; disposable systemd VM | pending |
|
||||||
|
|
||||||
|
### Milestone 1 — Rust foundation, settings, and domain states
|
||||||
|
|
||||||
|
Create one Cargo package with thin startup/library separation, reproducible lockfile, validated TOML settings, executable-relative paths, public-key identities, and explicit draft/saved/applied states. Implement dual-stack first-free allocation and deferred address release. Provide help/version without root or vault access; management startup requires root. Do not create a nonfunctional full module tree.
|
||||||
|
|
||||||
|
Acceptance: settings and allocation tests cover invalid input, exhaustion, IPv4-only existing clients, and reserved deleted addresses; path resolution does not depend on the working directory. Build, default tests, formatting, and Clippy pass without touching live services.
|
||||||
|
|
||||||
|
### Milestone 2 — Server configuration editing with byte preservation
|
||||||
|
|
||||||
|
Implement document-preserving parsing/editing and versioned metadata comments. Server configuration remains authoritative, duplicate aliases are permitted, and only managed client portions change.
|
||||||
|
|
||||||
|
Acceptance: synthetic fixtures prove byte preservation of untouched settings/comments, client addition/deletion/rename, unknown-field preservation, missing creation dates, and rejection of metadata/terminal injection. No complete generic INI reserialization.
|
||||||
|
|
||||||
|
### Milestone 3 — Client keys, encrypted vault, and existing-client import
|
||||||
|
|
||||||
|
Implement separate vault/client key pairs, recipient encryption, password-protected vault identity, and versioned secret storage. Import from the configured directory on initial setup without deleting originals. Verify key correspondence and classify anomalies; conflicts block reissue until resolved.
|
||||||
|
|
||||||
|
Acceptance: new secrets encrypt without password entry, correct/incorrect password and corruption paths are covered, original files are unchanged, duplicates/conflicts are represented correctly, and persisted application data contains no plaintext client private keys. WireGuard key handling uses approved libraries, not utility subprocesses.
|
||||||
|
|
||||||
|
### Milestone 4 — Backups, safe Commit, and full restoration
|
||||||
|
|
||||||
|
Implement versioned tar archives/manifests, mandatory pre-operation backups, internal state persistence, Commit orchestration, and previewed full restoration without decryption. Define partial-write handling and archive validation. Persist address reservations and verified-state bookkeeping as needed.
|
||||||
|
|
||||||
|
Acceptance: backup failure prevents protected mutations; Commit/restore never change the running VPN; archive composition matches the specification; malformed/traversal/link entries are rejected; restore returns saved settings/configuration/vault without a password. Tests demonstrate draft cancellation and deletion of current secrets while older archives remain unchanged.
|
||||||
|
|
||||||
|
### Milestone 5 — Runtime observation and systemd restart adapter
|
||||||
|
|
||||||
|
Implement `wireguard-uapi` runtime queries and the `zbus` systemd adapter behind narrow interfaces. Track service job completion and timeout, then verify interface/client correspondence before recording applied state and releasing addresses. Require backup before restart.
|
||||||
|
|
||||||
|
Acceptance: ordinary tests exercise successful and failed jobs, missing/mismatched interfaces, unavailable statistics, and no automatic rollback using controlled adapters. Real runtime/systemd acceptance remains explicitly pending until milestones 8 and 9; mocks cannot close those later gates.
|
||||||
|
|
||||||
|
### Milestone 6 — Client configuration delivery and reissue lifecycle
|
||||||
|
|
||||||
|
Generate full-tunnel IPv4/IPv6 configurations using settings and preserved existing parameters where applicable. Save a root-only plaintext file and optionally render a matching QR code. Enforce post-Commit initial delivery and per-client password-based reissue with session-scoped retry after file errors.
|
||||||
|
|
||||||
|
Acceptance: file/QR payloads agree; no delivery before Commit; output failure permits directory change/retry; successful initial delivery or session exit ends password-free eligibility; overwrite requires confirmation; unrelated plaintext imports cannot bypass authentication.
|
||||||
|
|
||||||
|
### Milestone 7 — Complete terminal management workflow
|
||||||
|
|
||||||
|
Connect tested application operations to Ratatui/Crossterm screens: list and statistics, forms, anomalies/import, draft/diff, Commit, restart, output/QR, and backup selection/restore. Keep expensive work off the render/input loop and maintain public-key-based selection.
|
||||||
|
|
||||||
|
Acceptance: keyboard workflows and cancellation preserve the required states, statistics refresh without claiming online status, destructive actions identify targets, passwords are masked, and terminal cleanup/resize/non-TTY/error behavior is verified. No implicit apply or save on exit.
|
||||||
|
|
||||||
|
### Milestone 8 — Alpine Testcontainers integration
|
||||||
|
|
||||||
|
Implement opt-in Rust container tests and a minimal pinned Alpine image with `wireguard-tools` and `iproute2`. Cache images, use fresh isolated resources, build an Alpine-compatible test executable (prefer musl), and exercise the real runtime adapter within the server container. Avoid new helpers outside approved dependencies without agreement.
|
||||||
|
|
||||||
|
Acceptance: prerequisite checks and cleanup work; real dual-stack tunnels produce handshake/counter changes; creation/Commit leaves runtime unchanged until explicit test-only application; deletion retains access/address reservation until application; restored saved state does not implicitly apply. No host network, host D-Bus, production mounts, privileged default, or automatic module loading. Systemd coverage is explicitly excluded.
|
||||||
|
|
||||||
|
### Milestone 9 — Real systemd acceptance and release readiness
|
||||||
|
|
||||||
|
Prepare a repeatable disposable VM procedure and run the actual application/systemd adapter against synthetic WireGuard state. Finish operating/recovery documentation, safe settings examples, native target release build, and review of executable runtime dependencies.
|
||||||
|
|
||||||
|
Acceptance: real D-Bus job handling, separate restart verification, address release, and manual backup recovery pass in the VM. All specification acceptance criteria have linked evidence. Required default checks and Alpine tests pass on the integrated revision; unresolved defects or unavailable required VM checks prevent final acceptance. Production is never the test environment.
|
||||||
|
|
||||||
|
## Current progress and resume point
|
||||||
|
|
||||||
|
- All milestones are pending; application implementation has not started.
|
||||||
|
- The approved dependency list and container testing methodology are recorded in AGENTS.md.
|
||||||
|
- Next action when execution is requested: verify the coordinator model/effort, inspect the repository, expand milestone 1, and dispatch its first bounded worker task.
|
||||||
|
- No workers have been dispatched by creation of this document; no build, container, or VM results are claimed.
|
||||||
|
|
||||||
|
## Plan maintenance
|
||||||
|
|
||||||
|
Update progress, findings, decisions, blockers, and the next action after each meaningful execution/review cycle and before handing off or ending a session. Preserve acceptance evidence when summarizing old iterations. Append scope changes with their reason; update the specification only when the user actually authorizes a requirement change.
|
||||||
|
|
||||||
|
Planning reference: [OpenAI — Using PLANS.md for multi-hour problem solving](https://developers.openai.com/cookbook/articles/codex_exec_plans). The specific model roles, milestone numbering, and review policy above are project decisions requested by the user.
|
||||||
@@ -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