Commit Graph
12 Commits
Author SHA1 Message Date
ReactorcoremeltdownandClaude Opus 5.5 318bd68908 Collect Android browser sign-ins after the app was stopped
The Android app kept a pending browser sign-in in a thread inside the
login screen. Android often kills the process while the browser is in
front, so the approval reached the server but nothing collected it, and
the app came back signed out with nothing saved.

The pending device code is now kept in Prefs and collected whenever the
login screen resumes. The app passes return_url=keeporg://device-approved
when it starts the sign-in, and the server's approval page, after a
password or single sign-on, links back to it. Only the keeporg: scheme is
accepted. Against a server older than 0.9, which rejects the field, the
app retries without it.

Verified on an Android 15 emulator: approval collected after the process
was killed, and the fallback against the 0.8 server.

Server 0.9.0, Android 0.3.0 (versionCode 3).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 13:16:23 +01:00
ReactorcoremeltdownandClaude Opus 5.5 ef6598fa15 Set the server's public URL from KEEPORG_EXTERNAL_URL
ci/woodpecker/push/build Pipeline was successful
ci/woodpecker/push/deploy Pipeline was successful
The image passes neither -config nor -url, so a deployment had no way to
set external_url and the server built invite links, device-approval pages
and the OIDC redirect URI on http://localhost:8765. The variable overrides
the configuration file and -url overrides it. The deployment values set it
to https://keeporg.tiredsysadmin.cc.

Also document every environment variable the server reads, and the
standard proxy and CA variables it honours for OIDC.

Server version 0.8.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 12:40:09 +01:00
ReactorcoremeltdownandClaude Opus 5.5 ead82dc777 Turn the desktop client into a system tray application
Started without a command, keeporg now shows a padlock in the system tray
with a menu like midi-webhook's: a status line, the mirror folder, each
database with its state, Sync Now, browser sign-in and sign-out, the web
interface, the configuration, the log, Start at Login, About and Quit. The
commands are unchanged.

config.json now carries every client setting (device_label,
request_timeout_seconds, ca_file, log_file, notifications), is written in
full on first start and is reloaded by the tray when saved.

A lock in the mirror directory admits one agent at a time, since the tray,
`keeporg run` and a service unit could otherwise race each other.

The tray uses fyne.io/systray: pure Go on Linux, BSD and Windows, cgo on
macOS only. The server keeps no third-party dependencies.

Desktop versions go to 0.5.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 12:30:28 +01:00
ReactorcoremeltdownandClaude Opus 5.5 d314188247 Deploy when versions.mk changes
The deploy pipeline watched a VERSION file that does not exist, so a
version bump built the image but never deployed it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 12:30:28 +01:00
Reactorcoremeltdown 0af5ecc5a7 Allowing manual push
ci/woodpecker/push/build Pipeline was successful
ci/woodpecker/push/deploy Pipeline was successful
2026-10-30 13:09:22 +01:00
Reactorcoremeltdown d40fc67722 Trigger deploy on editing Golang 2026-10-30 13:04:43 +01:00
ReactorcoremeltdownandClaude Opus 5 e0977a9241 Let an admin delete a vault, behind their own password
ci/woodpecker/push/build Pipeline was successful
The web interface could create a vault and never remove one, so the only
way to undo a mistake was the CLI. There is now a Delete link on every
vault you administer, leading to a page that says what is about to go —
owner, versions stored, grants pointing at it — and asks for your
account password before it goes.

The gate is re-authentication, not a confirmation checkbox. A session
token is enough to read and write a vault; it should not be enough to
erase every version of one, because a session is what an unlocked
laptop leaves lying around. The one-time code is required too when the
account has one enrolled.

It lives in confirmDeletion, so the rule holds wherever deletion is
reachable: DELETE /api/v1/databases/{id} now takes {password, totp?}
and answers 401 without it, and keeporg db -delete prompts. That is a
breaking change to the endpoint, which is why the server goes to 0.7.0
and the desktop clients to 0.4.0.

An account that signs in only through an identity provider has no
password to type. Rather than lock those deployments out of deleting
anything, they confirm by typing the vault's exact name — the weaker
gate, and deliberately the fallback.

Deleting takes the record, its grants, every stored version and the key
a merge vault left with the server, and tells the watchers over SSE.
Copies already in people's mirror directories stay where they are: the
server stops tracking a vault, it does not reach into anybody's home
directory.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-30 12:57:02 +01:00
ReactorcoremeltdownandClaude Opus 5 967d9c0e2e Let invites, SSO and health checks past Vouch
ci/woodpecker/push/build Pipeline was successful
ci/woodpecker/push/deploy Pipeline was successful
location / covered /invite/{token}, /oidc/callback, /device and
/healthz along with the web interface, so Vouch stood in front of all
of them. An invite link was the worst of it: it goes to somebody who has
no account anywhere yet, and Vouch bounced them to a login they cannot
pass. The OIDC callback was fragile for a different reason — the
authorization code it carries is single-use and short-lived, and a
second login round trip is a poor place to spend it.

Those four paths now proxy straight through. KeepOrg authenticates each
of them itself: an invite is a capability token, the callback is checked
against its state, a device code expires in ten minutes, and /healthz is
unauthenticated by design. /web keeps Vouch in front of it, and /api was
already exempt.

The proxy settings move to the server block, where every location
inherits them, and the upstream becomes a named block. location / has to
repeat the headers in full: a location that sets one proxy_set_header
replaces the inherited set rather than adding to it.

Checked with nginx -t and against a running keeporgd with a 401 standing
in for Vouch: /, /web and /web/* redirect to auth.tiredsysadmin.cc,
while /healthz, /invite/, /device and /oidc/* serve KeepOrg's own pages
and /api returns KeepOrg's 401.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-30 12:38:53 +01:00
ReactorcoremeltdownandClaude Opus 5 81094c0228 Add the administration pages to the web interface
Running the server meant running the API by hand: invites, accounts,
groups and grants existed only as endpoints and CLI commands, so the
browser could create a vault and nothing else.

/web/groups walks the group tree and opens onto one group's members,
roles and vault access, including the grants it inherits from above and
where they come from. /web/users lists the accounts you may see, and
lets a server administrator disable, enable, clear a lost second
factor, promote, demote or delete one. /web/invites shows the
outstanding links with their use counts, issues new ones and revokes
them.

Every administrative change is now a function of the state and the
caller in admin.go, which both the JSON handlers and the forms call. The
alternative was a second copy of the permission rules behind the pages,
which would have drifted on the first change. The same move gave the API
the two verbs it was missing: DELETE /api/v1/invites/{token} and
PATCH /api/v1/users/{id}.

Account changes are server-administrator only. A group administrator
decides who reaches which vault; disabling an account or clearing
somebody's second factor reaches past the group they share. Disable and
delete revoke that account's sessions, and the three changes that would
lock the caller out are refused on their own account.

Pages go through webPage and forms through webForm, so the session and
CSRF checks cannot be forgotten on a new form. No page carries any
JavaScript.

Server 0.6.0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-30 12:32:08 +01:00
Reactorcoremeltdown 0848c0186c Pass server version to container build
ci/woodpecker/push/build Pipeline was successful
ci/woodpecker/push/deploy Pipeline was successful
2026-10-30 10:08:34 +01:00
Reactorcoremeltdown 9729edfc9d Fixed a typo
ci/woodpecker/push/build Pipeline failed
ci/woodpecker/push/deploy unknown status
2026-10-30 10:03:26 +01:00
Reactorcoremeltdown da503eac2a Initial deploy
ci/woodpecker/push/build Pipeline failed
ci/woodpecker/push/deploy unknown status
2026-10-30 10:01:11 +01:00