Skeletons for new files only; existing files change by exact edits, so no task overwrites an earlier one's work. Each task's tests were run against a reference built in order from master, with the gate at each step and mutations checked; each skeleton compiles and fails its tests, and every todo!() comment was read beside its signature. The reference is kept off this machine. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
59 lines
2.9 KiB
Markdown
59 lines
2.9 KiB
Markdown
# M4b task 10: the text of an approval's posts
|
|
|
|
**Branch:** `m4b` (run `git switch m4b`; `git status --short` must be empty, otherwise stop)
|
|
**Commit subject:** `gatewayd: approvals::text, the posts that show an approval`
|
|
|
|
## Goal
|
|
|
|
What an approval looks like in Mattermost (M4b spec, section 6). Pure: text in, text out.
|
|
|
|
```text
|
|
**Approval 42** · tool `shell` · grant `ops-shell` · taint private · expires 2026-09-24 14:47 UTC
|
|
```
|
|
{"command":"ls -la /srv/backups"}
|
|
```
|
|
Reply in this thread with `!approve 42` or `!deny 42 <reason>`.
|
|
```
|
|
|
|
- The arguments are escaped with `proto::escape::escape_json_text` (task 01) and fenced with a run
|
|
of backticks longer than any inside them, so nothing in them renders or mentions anyone.
|
|
- **Nothing is shortened.** Arguments over 15,000 characters come in parts (at most 4), and only
|
|
the last carries the reply line, with the count and the SHA-256 of the whole. More than that, or
|
|
a part whose post would be over 15,500 characters, is one post saying it is too long to show,
|
|
answerable only in `bxctl`.
|
|
- When an approval ends, a line is added to its last post (`Ended`, `ended_line`, `with_ending`).
|
|
|
|
## Files
|
|
|
|
- Copy: `crates/gatewayd/src/approvals/mod.rs` from `mod.rs-task10` (three lines: the module
|
|
comment and `pub mod text;`), the skeleton `crates/gatewayd/src/approvals/text.rs`, and
|
|
`crates/gatewayd/tests/approvals_text.rs`
|
|
- Modify: `crates/gatewayd/src/lib.rs` (`pub mod approvals;` first, before `pub mod config;`),
|
|
`docs/implementer-log.md`
|
|
|
|
## The skeleton
|
|
|
|
Written: the constants, `Shown`, `Ended`, and **`render`**, which builds the posts from the
|
|
helpers below (read it first). To fill, each with its code in its comment: `code`, `fence`,
|
|
`longest_run`, `minute`, `name`, `reply_line`, `ended_line`, `with_ending`.
|
|
|
|
## Steps
|
|
|
|
- [ ] **1. Copy.** `git switch m4b`, then
|
|
`mkdir -p crates/gatewayd/src/approvals && cp docs/plans/M4b/files/crates/gatewayd/src/approvals/mod.rs-task10 crates/gatewayd/src/approvals/mod.rs && cp docs/plans/M4b/files/crates/gatewayd/src/approvals/text.rs crates/gatewayd/src/approvals/ && cp docs/plans/M4b/files/crates/gatewayd/tests/approvals_text.rs crates/gatewayd/tests/`.
|
|
Add `pub mod approvals;` to `lib.rs`.
|
|
- [ ] **2. See it fail.** `cargo test -p gatewayd --test approvals_text`. Expected: it compiles and
|
|
6 tests fail.
|
|
- [ ] **3. Fill the eight functions**, `longest_run` first, `cargo check -p gatewayd` after each.
|
|
- [ ] **4. See it pass.** `cargo test -p gatewayd --test approvals_text`. Expected: 6 passed.
|
|
- [ ] **5. Run the gate.** `cargo fmt --all`, then `make gate`. Expected last line: `gate: ok`.
|
|
- [ ] **6. Log and commit.** `git add crates/gatewayd docs/implementer-log.md Cargo.lock && git commit`
|
|
|
|
## Done when
|
|
|
|
- `cargo test -p gatewayd --test approvals_text` passes; `make gate` prints `gate: ok`.
|
|
|
|
## Stop and report if
|
|
|
|
- A comment above a `todo!()` does not fit its function, or contradicts a test: quote it.
|