diff options
| author | Anders Betts <anders.betts@gmail.com> | 2026-09-23 10:08:44 +0200 |
|---|---|---|
| committer | Anders Betts <anders.betts@gmail.com> | 2026-09-23 10:08:44 +0200 |
| commit | e06248ef69b33d102a57aaa31fffcde3240dad9c (patch) | |
| tree | d2b82eb5a5e2918336f89e241efdeed8bed5ca95 /docs | |
| parent | 79b27457125dc2e259783359085021eea1d26e3a (diff) | |
| download | bokf-e06248ef69b33d102a57aaa31fffcde3240dad9c.tar.gz bokf-e06248ef69b33d102a57aaa31fffcde3240dad9c.zip | |
user.set_password: change your own password; TUI "Byt lösenord"v0.1.68
Needs the current password (wrong ones rate limited like logins) and a
password session, requires at least 10 characters, closes the user's
other sessions and is audited without secrets. The TUI main menu gets
"Byt lösenord" with masked prompts; ^R keeps working with the new
password. Masked prompt buffers are wiped before they are freed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/PROTOCOL.md | 15 | ||||
| -rw-r--r-- | docs/STATE.md | 7 | ||||
| -rw-r--r-- | docs/TUI-GUIDELINES.md | 7 |
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. |
