Co-present the Commons, re-validate the instance on login, group accounts #279

Merged
stephen merged 4 commits from feat/spec-parity-fjord into main 2026-10-08 20:22:14 +00:00
Owner

Six fjord-client-spec requirements across instances (#210) and accounts
(#208).

Commons. The descriptor now carries memberCount, membership.namespace and
membership.orgSlug, all optional. fj instances lists a joined Commons
beside the account's own forges: a gateway-routable one is an ordinary
selectable row marked as the shared community forge, and one with no
gatewayForgeId is a "browser only" row. fj instances use commons on the
latter hands off to the browser and never writes hosts.toml.

The Commons lookup is now best-effort. It used to be joined with the
instance list through try_join!, so a Commons 5xx, an undecodable body or
a slow answer failed or stalled the whole listing. The list no longer
waits more than two seconds on it, and a failure is only visible under
--debug.

Re-login. After a Fjord Account sign-in the remembered instance is
checked against a fresh listing. It is kept when still present and ready;
otherwise the default_instance_* fields are cleared and the ready
instances are printed with the fj instances use <id> hint. fj has no
interactive picker, so that printed list stands in for one. A listing
that cannot be fetched keeps the selection unverified instead of failing
the login.

Groups. fj auth group list|create|rename|delete|assign|unassign keep
user-named groups in a top-level [groups] table in hosts.toml. Grouping
never changes host resolution, a re-login keeps the assignment, and
logout drops it. fj auth status and fj auth list show the group once
one exists.

fj instances list --json gains kind, routing and a commons
descriptor; a browser-only Commons entry has a null id.

Covered by unit and wiremock tests only; the Commons and re-login paths were not run against a live Fjord Account.

The accounts requirement "Restore the previously-picked instance" is why #208 is a Refs and not a Closes: the fallback here is a printed list plus fj instances use <id>, not an interactive picker. Whether that counts as implemented for the spec is a call to make at review.

Part 2 of 8 in the spec-parity stack. Based on feat/spec-parity-notifications, so the diff here is this slice alone; it needs a rebase onto main once the PR below it is squash-merged.

Closes #210
Refs #208

Verified on macOS at this commit: cargo fmt --all clean, cargo clippy --all-targets --all-features -- -D warnings clean, cargo test --all green.

Six fjord-client-spec requirements across instances (#210) and accounts (#208). Commons. The descriptor now carries memberCount, membership.namespace and membership.orgSlug, all optional. `fj instances` lists a joined Commons beside the account's own forges: a gateway-routable one is an ordinary selectable row marked as the shared community forge, and one with no gatewayForgeId is a "browser only" row. `fj instances use commons` on the latter hands off to the browser and never writes hosts.toml. The Commons lookup is now best-effort. It used to be joined with the instance list through try_join!, so a Commons 5xx, an undecodable body or a slow answer failed or stalled the whole listing. The list no longer waits more than two seconds on it, and a failure is only visible under --debug. Re-login. After a Fjord Account sign-in the remembered instance is checked against a fresh listing. It is kept when still present and ready; otherwise the default_instance_* fields are cleared and the ready instances are printed with the `fj instances use <id>` hint. fj has no interactive picker, so that printed list stands in for one. A listing that cannot be fetched keeps the selection unverified instead of failing the login. Groups. `fj auth group list|create|rename|delete|assign|unassign` keep user-named groups in a top-level [groups] table in hosts.toml. Grouping never changes host resolution, a re-login keeps the assignment, and logout drops it. `fj auth status` and `fj auth list` show the group once one exists. `fj instances list --json` gains `kind`, `routing` and a `commons` descriptor; a browser-only Commons entry has a null id. Covered by unit and wiremock tests only; the Commons and re-login paths were not run against a live Fjord Account. The accounts requirement "Restore the previously-picked instance" is why #208 is a Refs and not a Closes: the fallback here is a printed list plus `fj instances use <id>`, not an interactive picker. Whether that counts as implemented for the spec is a call to make at review. Part 2 of 8 in the spec-parity stack. Based on `feat/spec-parity-notifications`, so the diff here is this slice alone; it needs a rebase onto main once the PR below it is squash-merged. Closes #210 Refs #208 Verified on macOS at this commit: `cargo fmt --all` clean, `cargo clippy --all-targets --all-features -- -D warnings` clean, `cargo test --all` green.
Six fjord-client-spec requirements across instances (#210) and accounts
(#208).

Commons. The descriptor now carries memberCount, membership.namespace and
membership.orgSlug, all optional. `fj instances` lists a joined Commons
beside the account's own forges: a gateway-routable one is an ordinary
selectable row marked as the shared community forge, and one with no
gatewayForgeId is a "browser only" row. `fj instances use commons` on the
latter hands off to the browser and never writes hosts.toml.

The Commons lookup is now best-effort. It used to be joined with the
instance list through try_join!, so a Commons 5xx, an undecodable body or
a slow answer failed or stalled the whole listing. The list no longer
waits more than two seconds on it, and a failure is only visible under
--debug.

Re-login. After a Fjord Account sign-in the remembered instance is
checked against a fresh listing. It is kept when still present and ready;
otherwise the default_instance_* fields are cleared and the ready
instances are printed with the `fj instances use <id>` hint. fj has no
interactive picker, so that printed list stands in for one. A listing
that cannot be fetched keeps the selection unverified instead of failing
the login.

Groups. `fj auth group list|create|rename|delete|assign|unassign` keep
user-named groups in a top-level [groups] table in hosts.toml. Grouping
never changes host resolution, a re-login keeps the assignment, and
logout drops it. `fj auth status` and `fj auth list` show the group once
one exists.

`fj instances list --json` gains `kind`, `routing` and a `commons`
descriptor; a browser-only Commons entry has a null id.

Closes #210
Refs #208
stephen changed target branch from feat/spec-parity-notifications to main 2026-10-08 19:42:28 +00:00
Add fj admin and fj profile (#280)
Some checks failed
ci / coverage (pull_request) Has been cancelled
ci / live-e2e (pull_request) Has been cancelled
ci / check (pull_request) Has been cancelled
6c0aa3d3a7
Four fjord-client-spec requirements with nothing behind them on main:
three under forge-instance-administration and one under profiles.

`fj admin settings` reads the four /settings/* sections and prints only
what the server sent; a section answering 404, 405 or 501 is labelled
unavailable. `fj admin cron list` reads /admin/cron. A 403 is never
folded into "unavailable": it reads as "requires an instance
administrator" and keeps exit code 4. Both are read-only.

`fj admin user create` needs exactly one of --password-stdin,
--password-prompt or --no-password, and explicit --send-notify and
--must-change-password choices. There is no --password flag. Stdin on a
TTY and a prompt without one are both refused, so it can neither echo
nor hang. /admin/users joins the sensitive paths, which keeps the
request body out of --debug, and credential-shaped keys are stripped
from the response before anything prints.

`fj admin unadopted list|adopt|delete` page the unadopted repositories.
The two mutations print the repository and the consequence, ask for the
name to be typed back, refuse a non-TTY run without --yes, and only say
"Server confirmed" after the 204.

`fj profile view|edit`, `fj profile email list|add|remove` and
`fj profile avatar set|delete`. An edit sends only the fields that were
passed and warns about any the response does not reflect. Email
verification state comes from the server and prints "unknown" when it is
not reported. An avatar is checked for size and image magic bytes before
it is uploaded.

scripts/e2e-smoke.sh now runs `profile view` and `profile email list`,
so the smoke token needs the read:user scope.

Covered by unit and wiremock tests only; nothing here was run against a live forge, and the admin routes need a site administrator to check for real. The CI smoke token needs `read:user` before the two new `profile` lines in `scripts/e2e-smoke.sh` pass.

Part 3 of 8 in the spec-parity stack. Based on `feat/spec-parity-fjord`, so the diff here is this slice alone; it needs a rebase onto main once the PR below it is squash-merged.

Verified on macOS at this commit: `cargo fmt --all` clean, `cargo clippy --all-targets --all-features -- -D warnings` clean, `cargo test --all` green.

Reviewed-on: #280
Merge main into feat/spec-parity-fjord
Some checks failed
ci / check (pull_request) Successful in 11m58s
ci / coverage (pull_request) Has been cancelled
ci / live-e2e (pull_request) Has been cancelled
b05381d190
stephen deleted branch feat/spec-parity-fjord 2026-10-08 20:22:15 +00:00
Sign in to join this conversation.
No description provided.