diff --git a/docs/designs/README.md b/docs/designs/README.md index e449cc5..64bfa6d 100644 --- a/docs/designs/README.md +++ b/docs/designs/README.md @@ -91,6 +91,7 @@ new build slice becomes a numbered `iterations/iter-NNN-*.md` (per | 13 | [WireGuard + NetGuard plugins](design-13-wireguard-and-netguard-plugins.md) | Split WireGuard and nftables into two signed first-party plugins with security-group-grade graphical control: zones + reusable security groups + reality-first authoring/drift, WG networks/topologies/external-device peers, blank-machine bootstrap, and adoption of existing on-box configs | Engine (approvals, plan-hash, watchdog/rollback scaffolding, task executor) stays CORE; the plugins own domain models, compilers-as-providers, RPC interfaces, and dashboard IA via `builtin` views — the proven vpn-core pattern. **G1 landed iter-068** (model/store/read-only legacy views); **G2 landed iter-069** (compiler *lowering* into the single `GenerateNFTPlan` renderer so byte-parity with the legacy baseline is structural and mutation-checked, blocking `lockout_risk_ssh` lint, `netguard:admin` write path, plan on the existing `nft` apply path); **W1+W2 landed iter-070** (`BuildTopology` with mesh render-parity + hub-and-spoke; WireGuard apply finally gains the snapshot → dead-man watchdog → selfcheck chain nft always had, plus a `wg syncconf` fast path and a shared watchdog window). Next: G3 reality/drift, G4 dashboard, W1b store/API/discovery. | | 14 | [Plugin-owned vpn-core control](design-14-plugin-owned-vpn-core-control.md) | Restores the rich sing-box operator experience inside the vpn-core bundle while keeping the base dashboard generic and uninstall-safe | Dashboard owns only sandbox/navigation/step-up; vpn-core owns pages and workflows; server owns RBAC/approval/audit; agent remains the bounded executor. Endpoint, listen bind, and Reality SNI are distinct fields. | | 15 | [line_uuid, per-line users, chain recognition, Sub-Store integration](design-15-line-uuid-users-chain-substore.md) | Control-plane `line_uuid` identity + sidecar metadata v2, audited per-line user CRUD (adopted-first dual track), declared-edge chain joins, Sub-Store preview/persisted-endpoint/auto-sync | Merge of Sub-Store into vpn-core explicitly rejected; stock sing-box strict parsing means metadata rides a sidecar, never in-config; unique per-user `name` is the join key for auth, routing, and stats. Contract: `docs/contracts/lattice-singbox-metadata-v2.schema.json` | +| 18 | [Reviewed line-chain builder](design-18-line-chain-builder.md) | One redacted plan and one durable consumer-node task atomically apply/remove a route fragment plus source-side declaration | Projection-only planning; secret lease boundary; crash-recoverable exact-pair transaction; exact durable result replay | ## Shared architecture (all five honor) diff --git a/docs/designs/design-18-line-chain-builder.md b/docs/designs/design-18-line-chain-builder.md new file mode 100644 index 0000000..eb3d77c --- /dev/null +++ b/docs/designs/design-18-line-chain-builder.md @@ -0,0 +1,72 @@ +# Design 18 — reviewed line-chain builder + +Status: alpha implementation contract (E3 revision 9) + +## Outcome + +An operator can review and approve one redacted plan that connects one healthy +source sing-box line to one applied managed VLESS+REALITY+TCP target line. One +durable task mutates only the source/consumer node. Scheduled discovery, not the +approval itself, proves the resulting topology edge. + +V1 supports set/replace and remove. It rejects adopted targets with incomplete +private descriptors, other protocols, same-node chains, ambiguous identity +joins, and cyclic declared graphs before an executable task is leased. + +## Public plugin contract + +The vpn-core plugin exposes these methods on +`latticenet.vpn-core/lines`: + +| Method | Effect | Scope | Purpose | +| --- | --- | --- | --- | +| `chains` | read | `vpncore:read` | Secret-free desired, attempt, and reconciliation state | +| `plan_chain` | plan | `vpncore:admin` | Review a set/replace candidate | +| `plan_remove_chain` | plan | `vpncore:admin` | Review removal of the committed source edge | + +The internal approval bindings intentionally use service `network/lines` and +methods `chain_set_apply` / `chain_remove_apply`. External plugin RPC names must +never be persisted as execution authority. + +Statuses are exactly `planned`, `applying`, `applied_unobserved`, `converged`, +`drifted`, and `failed`. A failed replace/remove retains the old committed edge +while showing the failed attempt separately. + +## Safety boundary + +- Plans and reads use revision-consistent projections and make no synchronous + node, SSH, HTTP, or sing-box calls. +- Approval targets exactly the consumer node and creates exactly one E3-linked + task per approved attempt. +- Credentials appear only in the targeted lease artifact. They are absent from + plan previews, plugin reads, audits, journals, generic KV, and reveal-script. +- The agent applies the fragment and source sidecar as one crash-recoverable + transaction. Mixed pairs suppress readiness, inventory, capability + advertisement, polling, and result publication. +- Exact durable result replay is accepted; conflicting replay is rejected. +- A post-lease dependency change does not revoke frozen execution authority; + an exact success is acknowledged once and committed as drifted. + +## Compatibility and release handoff + +The implementation matrix is server `alpha-0.2.1a38` with semantic floor +`0.2.2-alpha.19`, node-agent `0.3.4-alpha.1`, and vpn-core +`0.8.0-alpha.9`. Prereleases require explicit selection; `latest` remains the +latest stable node-agent only. + +The vpn-core implementation lane produces a deterministic unsigned bundle. An +authorized release lane verifies the full two-architecture binary plus UI +bundle digest and signs only the final canonical manifest. Implementation does +not sign, tag, publish, deploy, or mutate the fleet. + +## Acceptance trace + +1. Inventories report managed target A and healthy source B. +2. Plan B → A and inspect the redacted approval. +3. Approve and lease exactly once to capable B. +4. B atomically publishes its route fragment and source sidecar. +5. B uploads one durable exact result. +6. Normal scheduled discovery proves outbound and declared downstream identity. +7. Ordinary metadata sync preserves the committed declaration. +8. A reviewed remove performs the inverse one-task transaction; discovery proves + the fragment and edge are absent. diff --git a/docs/tutorials/operator-guide.md b/docs/tutorials/operator-guide.md index 3c274f8..561af71 100644 --- a/docs/tutorials/operator-guide.md +++ b/docs/tutorials/operator-guide.md @@ -331,3 +331,31 @@ After any host-mutating change: - rollback file exists for nft/proxy/DNS paths where applicable. When in doubt, re-plan. Do not re-use stale approvals after changing intent. + +## 15. Reviewed line chains (alpha) + +Line-chain operations are explicit reviewed changes. Use vpn-core `Lines` to +inspect the secret-free current/attempt state, then create a set/replace or +remove plan. Confirm that the source and target UUIDs, consumer node, public +target fingerprints, artifact digest, and previous target (for replacement) +match the intended change before approval. + +Interpret states as follows: + +- `planned`: review exists; no task has changed a host. +- `applying`: one candidate is reserved and the durable consumer task may be in + flight. +- `applied_unobserved`: host result committed; scheduled inventory has not yet + proved the topology. +- `converged`: runtime evidence and the source declaration agree. +- `drifted`: the frozen applied baseline committed, but current dependencies or + observed evidence differ; create a fresh repair/remove plan. +- `failed`: the candidate failed. For replace/remove, the displayed `current` + edge remains active and must not be treated as removed. + +Do not retry a failed approval. Create a fresh plan and approval. Do not use +generic KV or task script reveal to recover credentials; those surfaces deny E3 +secrets by design. If readiness reports unresolved line-chain recovery, stop +host changes and inspect the agent transaction diagnostics—the agent suppresses +inventory, capability advertisement, polling, and result publication until the +exact old or desired artifact pair is recovered.