summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/PROTOCOL.md15
-rw-r--r--docs/STATE.md7
-rw-r--r--docs/TUI-GUIDELINES.md7
3 files changed, 26 insertions, 3 deletions
diff --git a/docs/PROTOCOL.md b/docs/PROTOCOL.md
index ae1098f..9ab9620 100644
--- a/docs/PROTOCOL.md
+++ b/docs/PROTOCOL.md
@@ -86,6 +86,13 @@ and returns an opaque, high-entropy session id:
- Sliding TTL, `session_ttl` default 8 h. `session.close` ends one explicitly.
- Passwords are stored as Argon2id hashes. Failed logins are rate limited per
peer (default: 5 failures per 15 minutes, then `RATE_LIMITED`).
+- A user changes their own password with `user.set_password` from a
+ password session (a token session gets `FORBIDDEN`). The current password
+ is required — 5 wrong ones per 15 minutes give `RATE_LIMITED` — and the
+ new one must have at least 10 characters and differ from it. On success
+ every other session of the user is closed (`sessions_closed`); the call's
+ own session stays. The audit entry (`user.set_password`, also for a wrong
+ current password) carries no password.
- Token lookups compare SHA-256 hashes in constant time. Token values are
shown exactly once at creation and are never logged.
@@ -97,7 +104,7 @@ and returns an opaque, high-entropy session id:
- Tokens are the intended mechanism for agents and for accountant/viewer
access. They can be revoked immediately (`token.revoke`). Scopes are
enforced for every command, including admin commands: `backup.snapshot`
- and `user.*` need a token with the `admin` scope.
+ and `user.create`/`user.list` need a token with the `admin` scope.
### 4.3 Roles and permissions
@@ -115,6 +122,7 @@ Scopes on a token can narrow but never widen the user's role.
| `payroll.agi` (decrypted personnummer), `payroll.tax_tables_fetch/import` | | | ● | |
| `org.member_*`, `token.create` for others | | | ● | |
| `user.create`, any org | | | | ● |
+| `user.set_password` (own password) | ● | ● | ● | ● |
| `backup.snapshot` | | | ● | ● |
Any authenticated user may create a new org (config `allow_org_create`,
@@ -295,6 +303,7 @@ Arguments are shown abbreviated; `describe` is authoritative.
| `board.add` / `board.update` / `board.remove` | `name`,`title?` / `id`,`name?`,`title?` / `id` | owner; audited |
| `user.create` | `username`, `password`, `display_name`, `is_admin?` | `user` (system admin) |
| `user.list` | — | `items[]` (system admin) |
+| `user.set_password` | `current_password`, `new_password` | `sessions_closed` (own password; password session only) |
| `token.create` | `label`, `scopes[]`, `org`, `expires_at?` | `token` (shown once), `id` |
| `token.list` / `token.revoke` | — / `id` | `items[]` / `{}` |
@@ -826,6 +835,7 @@ Args: `name:type(values)[!][=default]`, `!` = required.
| `session.whoami` | viewer | no | no | no | — |
| `session.list_orgs` | viewer | no | no | no | — |
| `session.use_org` | viewer | no | no | no | `org:int!` |
+| `user.set_password` | viewer | no | yes | no | `current_password:string!`, `new_password:string!` |
| `org.create` | viewer | no | yes | yes | `name:string!`, `org_nr:string`, `fiscal_year_start_month:int=1`, `moms_period:enum(month\|quarter\|year)=month`, `framework:enum(K2\|K3)=K2` |
| `org.list` | viewer | no | no | no | — |
| `org.get` | viewer | yes | no | no | — |
@@ -935,7 +945,8 @@ Args: `name:type(values)[!][=default]`, `!` = required.
commands. Implemented screens (0.1.0-dev):
- **Inloggning** — server, user, password; org picker when several exist.
- **Byt bolag** in the main menu reopens the picker during the session.
+ **Byt bolag** in the main menu reopens the picker during the session;
+ **Byt lösenord** calls `user.set_password`.
- **Dashboard** — status line with org, fiscal year, role and user.
- **Verifikat** — list and detail view (rows with column headers, an
underlag section separated by a rule, hash, link to corrected voucher); `c`
diff --git a/docs/STATE.md b/docs/STATE.md
index 31d6b14..128e824 100644
--- a/docs/STATE.md
+++ b/docs/STATE.md
@@ -14,6 +14,13 @@ unit tests and the docs consistency check.
## Resume here (2026-09-22)
+- **Byt lösenord (2026-09-23, branch `eff/set-password`, needs a server
+ deploy)**: new command `user.set_password` (own password, password
+ session only, current password required and rate limited like logins,
+ ≥ 10 characters, other sessions closed, audited without secrets) and a
+ main-menu item in the TUI. Until the server is deployed the TUI item
+ answers `UNKNOWN_COMMAND`. Follow-up to consider: an admin reset of
+ another user's password (today only `user.create` sets one).
- **Byt bolag (2026-09-23, branch `eff/switch-org`)**: a main-menu item
reopens the org picker and switches org in the running session (context
reloaded, list selections cleared). `app_refresh_context` now clears the
diff --git a/docs/TUI-GUIDELINES.md b/docs/TUI-GUIDELINES.md
index 68316e3..28b7f89 100644
--- a/docs/TUI-GUIDELINES.md
+++ b/docs/TUI-GUIDELINES.md
@@ -130,7 +130,12 @@ opens the same picker, with the cursor on the current org, and switches the
session to the chosen one: `session.use_org`, then the org's name, role,
current fiscal year and series are reloaded and the remembered list
selections are cleared; `Esc` keeps the current org. `Ctrl+R` keeps the
-switched org. The fiscal year is chosen from the dashboard and is changeable
+switched org. "Byt lösenord" asks for the current password, the new one
+and the new one again in masked prompts (`Esc` in any of them cancels),
+checks length (≥ 10), match and difference before calling
+`user.set_password`, and reports that the user's other logins were logged
+out and that a Bitwarden item has to be updated; `Ctrl+R` keeps working
+with the new password. The fiscal year is chosen from the dashboard and is changeable
during the session; the `Räkenskapsår` screen also closes and reopens years
there.