Skip to content

design-15 S4a: adopted-track per-line user write path - #14

Merged
lr00rl merged 1 commit into
alpha/v0.2.2from
feat/design-15-line-users
Jul 22, 2026
Merged

design-15 S4a: adopted-track per-line user write path#14
lr00rl merged 1 commit into
alpha/v0.2.2from
feat/design-15-line-users

Conversation

@lr00rl

@lr00rl lr00rl commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Summary

design-15 D3 server slice (adopted track first; managed re-render deferred per D6):

  • users-admin.plan_add / plan_remove (in-core, core-backed — same pattern as netguard's plan): compiles a pending approval. Plan is redacted (op/line/user/protocol/credential SHA — no secrets); Action binds the exact credential SHA-256.
  • Apply: applyScriptFor routes singbox-lineuser approvals to a script that re-derives the credential from the write-only store and fails closed on any drift since approval, then runs sb user add|del <line> <payload> (the 233boy fork's atomic jq + sing-box check + rollback + restart path).
  • users-admin.rotate: regenerates one protocol credential, one-time reveal, write-only read model preserved.
  • User name rule (design-15 §5): u_<sha256(user_id|line_uuid)[:16]> — single join key for auth, auth_user routing, and per-user stats.
  • Applied remove drops the server-side binding; managed lines are explicitly rejected with a pointer to the later slice.

Stacked on #13 (linemeta). Plugin manifest/UI wiring is the next slice.

Verification

  • gofmt/go vet clean; go test ./... all ok (server pkg 20s)
  • New tests: name rule shape/determinism, plan_add happy path (no secret in Plan, SHA-bound Action), rejections (unbound/disabled/unknown), apply script embeds reviewed credential + fail-closed on drift, rotate (uuid + password protocols, untouched credentials preserved), task-result ladder (failed task not applied; applied remove drops binding)

Refs LatticeNet/lattice#2, #13.

vpn-core users-admin gains plan_add/plan_remove (in-core, core-backed):
each compiles a pending approval whose Plan is a redacted payload
(op/line/user/credential SHA — never secret material) and whose Action
binds the exact credential bytes. The approval executor renders the
on-box `sb user add|del <line> <payload>` invocation, re-deriving the
credential from the write-only store and failing closed when the bytes
moved since approval.

Also adds rotate: regenerate one protocol credential with a one-time
reveal, preserving the write-only read model. Every on-line user carries
the design-15 §5 derived name (u_<sha256(user|line_uuid)[:16]>) — the
single join key for auth, auth_user routing, and per-user stats.

A successful remove drops the server-side binding so the read model
stops claiming the user belongs on the line. Managed-track user writes
(whole-config re-render) are explicitly rejected with a pointer to the
later slice.
@lr00rl
lr00rl force-pushed the feat/design-15-line-users branch from 0b39e33 to 9812a3c Compare July 22, 2026 13:29
@lr00rl
lr00rl marked this pull request as ready for review July 22, 2026 13:40
@lr00rl
lr00rl merged commit c235bb8 into alpha/v0.2.2 Jul 22, 2026
1 check passed
@lr00rl
lr00rl deleted the feat/design-15-line-users branch July 22, 2026 13:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant