gatewayd: config, [approvals] users and socket
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
This commit is contained in:
@@ -6,6 +6,7 @@ reviewer adds findings under "Reviews" once per milestone.
|
||||
|
||||
| Task | Date | Status | Gate runs | First gate | Deviations | Notes | Model |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| M4b/07-gatewayd-config-approvals | 2026-09-24 | done | 1 | pass | none | Copied `docs/plans/M4b/files/crates/gatewayd/tests/config_approvals.rs` into `crates/gatewayd/tests/`. In `config.rs`: added `#[serde(default)] pub approvals: ApprovalsConfig,` after `pub limits: Limits,` in `Config`, the `ApprovalsConfig { users: Vec<String>, socket: PathBuf }` struct (`#[serde(deny_unknown_fields, default)]`, with the doc comments) after `struct Config`, the `[approvals] users` check in `problem` right before the `[limits] queue` check (each id must be in `allow.users`), and the three methods before `state_path`: `approvers` (`&self.approvals.users`, or `&self.allow.users` when empty), `first_approver` (`.first().map(String::as_str)`), and `gateway_socket` (`self.approvals.socket`, or `<home>/run/gateway/gateway.sock` when `as_os_str().is_empty()`). The `ApprovalsConfig` derives `Default` so the empty `socket` deserialises from an absent field; `PathBuf`'s default is empty, matching the runbook's "empty" rule. `cargo fmt --all` then `cargo test -p gatewayd --test config_approvals --test config` green (4 and 7 passed); `make gate` prints `gate: ok` on the first run. | ? |
|
||||
| M4b/06-brokerd-courier | 2026-09-24 | done | 1 | pass | none | Filled the four `todo!()`s in the copied `courier.rs`: `finished` (`stop.load(SeqCst) || !broker.table().contains(id)`); `pause` (a `while Instant::now() < until && !finished` loop sleeping `timing.tick.min(until.saturating_duration_since(now))`); `frames` (`try_clone` the stream, spawn a reader thread that hands whole frames over an mpsc channel so the courier can `recv_timeout` without losing half a frame, `Ok(rx)`); `answer` (`take` the entry → `Gone {}` if gone, build the `Answer` from `reply.approved`, call `admin::answer`, map the returned `DecisionRecord` through the five-arm match to `Runs`/`Denied`/`Refused`/`Denied`/`Refused`). The four `broker.rs` changes: `RecvTimeoutError` import widened to include `Receiver`, `use crate::courier;` after the `config` use, `let shown = info.clone();` before the insert, step 4 replaced by `courier::alongside(broker, &shown, || wait_for_verdict(...))` matching `Waited`, and the old step 4 moved to `wait_for_verdict` (with the `Waited` enum) before `pub fn alive`. `cargo build -p brokerd` clean; courier test went 1 pass/9 fail then 10 passed three times running; full brokerd suite green; `cargo fmt --all` then `make gate` prints `gate: ok` on the first run. | ? |
|
||||
| M4b/05-brokerd-config-gateway | 2026-09-24 | done | 1 | pass | none | Copied `docs/plans/M4b/files/crates/brokerd/tests/config_gateway.rs` and the new `support/rig.rs` (whose `Config` gained `gateway: None`) into `crates/brokerd/tests/`. In `config.rs`: added the `Gateway { socket: PathBuf }` struct (`#[serde(deny_unknown_fields, default)]`) before `default_podman`, the `gateway: Option<Gateway>` field (with `#[serde(default)]`) after `runner` in `Config`, and the `gateway_socket()` method before `audit_dir` — `None` when the section is absent, the default `<home>/run/gateway/gateway.sock` when the socket is empty, else the path as given. `cargo fmt --all` then `cargo test -p brokerd` green with `config_gateway` 4 passed; `make gate` prints `gate: ok` on the first run. | ? |
|
||||
| M4b/04-brokerd-answer-post | 2026-09-24 | done | 1 | pass | none | Moved `enum Answer` and `struct Answered` from `ledger.rs` into `approvals.rs` before `pub struct Entry` (with doc comments), added `pub use crate::approvals::{Answer, Answered};` next to the `Verdict` use and `DecisionRecord` to the `use proto` line in `approvals.rs`. Added the `post` field to `Answer::Approved`/`Answer::Refused`, threaded it through `ledger::answer` (step 3 binds `post`, step 6 writes it into `AuditEvent::Approval` instead of `None`), and gave the two `bxctl` answers in `admin.rs` `post: None`. Added `Table::contains` before `take`. Copied `ledger_post.rs`, `broker_pending.rs`, `broker_sequence.rs` and `ledger_answer.rs` into `crates/brokerd/tests/`; every suite passes, `ledger_post` 3 passed, `ledger.rs` is 487 lines, and `make gate` prints `gate: ok` on the first run. | ? |
|
||||
|
||||
+9
-5
@@ -423,13 +423,17 @@ file or a directory, then this entry.
|
||||
|
||||
**Why.** `gatewayd` could not read or parse `gatewayd.toml`, or a value in it is not allowed: a
|
||||
`url` that is not `http://` or `https://` with a host and an optional port, an id that is not 26
|
||||
characters of `a-z0-9`, an empty `[allow] users`, or a secret with not exactly one of `credential`,
|
||||
`env` and `file`. Or it could not create `<home>/gateway/`. It will not guess at a configuration
|
||||
that decides who it answers.
|
||||
characters of `a-z0-9`, an empty `[allow] users`, an id in `[approvals] users` that is not also in
|
||||
`[allow] users`, or a secret with not exactly one of `credential`, `env` and `file`. Or it could
|
||||
not create `<home>/gateway/`, or could not listen on `gateway.sock` (its directory is made 0700
|
||||
and the socket 0600, as `brokerd`'s are; a path of 108 bytes or more cannot be a socket). It will
|
||||
not guess at a configuration that decides who it answers and who approves.
|
||||
|
||||
**Confirm.** The line says which: `<config path>: …` for the file (unknown keys are errors; check
|
||||
it against `docs/specs/2026-09-23-m4a-gateway.md`, section 3), or `cannot prepare <dir>: …` for the
|
||||
directory (`ls -ld <dir> "$(dirname <dir>)"`).
|
||||
it against `docs/specs/2026-09-23-m4a-gateway.md`, section 3, and
|
||||
`docs/specs/2026-09-24-m4b-approvals.md`, section 3), `cannot prepare <dir>: …` for a directory
|
||||
(`ls -ld <dir> "$(dirname <dir>)"`), or `cannot listen on <socket>: …` for `gateway.sock`
|
||||
(`Address already in use` means another `gatewayd` runs: `pgrep -x gatewayd`).
|
||||
|
||||
**Fix.** Correct the file or the directory's ownership. A user id is shown in Mattermost under the
|
||||
user's profile, or by `GET /api/v4/users/username/<name>`.
|
||||
|
||||
Reference in New Issue
Block a user