feat(package): step-up for torb owner #287

Merged
argus merged 2 commits from loop/280-owner-step-up into main 2026-10-09 22:30:50 +00:00
Collaborator

Closes #280

torb owner add|remove --step-up: the change approved with a passkey at the account page.

fix(package): keep the registry's answer out of the work directory

  • The request helper's answer file is private (0600, made anew) before curl/wget write into it, and emptied after every request, since an answer can hold the token of trusted publishing or the secret of a step-up.
  • The upload directory is 0700; all three files are emptied even where one cannot be.
  • tools/registry/tests/commands.test.trb checks that the last answer is gone and its file is private.

feat(package): step-up for torb owner

  • POST /api/1/step-up {call: "owners"}, then the user code and the page on standard output (the prompt on standard error only on a terminal), then one line of standard input (a pipe works too), then Torb-Code: step-up:<secret> on the one call. The secret, id and expiry are never printed; the secret goes through the header file only.
  • End of input without a line: nothing is sent, exit 1, the grant stays open until it expires. Refusals of the start (401, 403, 409, 429) and of the call: refusalOf, exit 1.
  • Usage errors (exit 2): --step-up with list, --step-up with --code, --code followed by a flag. TORB_CODE is ignored with --step-up.
  • New tools/registry/tests/owner-step-up.test.trb: the registry in-process, torb as a child with open pipes, each grant approved with the recorded passkey of passkey-vectors. It covers an approved add (grant used), a second add needing a new grant (refused unapproved), an approved remove, an expired grant, end of input, an account without a passkey (409), an add without --step-up, and the usage errors. A curl stand-in copies the header and answer files at call time, so the test knows every secret and checks it is in no argument, no output and no file left in the cache, and that the files are private.
  • Docs: torb-owner.md "A passkey", RELEASE.md 7.13 row, registry README, regenerated skills, pdisc stamp.

Reviewed by the architect agent before opening; its findings are addressed: a private upload directory, files made anew, cleanup of all three files, the --code --step-up guard, the docs on an early Enter, the test reading one merged pipe, and file-mode checks. Follow-ups out of scope (not in this PR): exchange.json of trusted publishing is written with the default mode; refusal bodies reach the terminal unfiltered for every registry command; no ownership/symlink check on <cache>/upload.

Overlap: #279 touches registry.trb, usage.trb, RELEASE.md 7.13 and the README; whichever lands second rebases.

Closes #280 `torb owner add|remove --step-up`: the change approved with a passkey at the account page. **fix(package): keep the registry's answer out of the work directory** - The request helper's answer file is private (`0600`, made anew) before `curl`/`wget` write into it, and emptied after every request, since an answer can hold the token of trusted publishing or the secret of a step-up. - The `upload` directory is `0700`; all three files are emptied even where one cannot be. - `tools/registry/tests/commands.test.trb` checks that the last answer is gone and its file is private. **feat(package): step-up for torb owner** - `POST /api/1/step-up {call: "owners"}`, then the user code and the page on standard output (the prompt on standard error only on a terminal), then one line of standard input (a pipe works too), then `Torb-Code: step-up:<secret>` on the one call. The secret, id and expiry are never printed; the secret goes through the header file only. - End of input without a line: nothing is sent, exit 1, the grant stays open until it expires. Refusals of the start (401, 403, 409, 429) and of the call: `refusalOf`, exit 1. - Usage errors (exit 2): `--step-up` with `list`, `--step-up` with `--code`, `--code` followed by a flag. `TORB_CODE` is ignored with `--step-up`. - New `tools/registry/tests/owner-step-up.test.trb`: the registry in-process, `torb` as a child with open pipes, each grant approved with the recorded passkey of `passkey-vectors`. It covers an approved add (grant used), a second add needing a new grant (refused unapproved), an approved remove, an expired grant, end of input, an account without a passkey (409), an add without `--step-up`, and the usage errors. A `curl` stand-in copies the header and answer files at call time, so the test knows every secret and checks it is in no argument, no output and no file left in the cache, and that the files are private. - Docs: `torb-owner.md` "A passkey", RELEASE.md 7.13 row, registry README, regenerated skills, pdisc stamp. Reviewed by the architect agent before opening; its findings are addressed: a private upload directory, files made anew, cleanup of all three files, the `--code --step-up` guard, the docs on an early Enter, the test reading one merged pipe, and file-mode checks. Follow-ups out of scope (not in this PR): `exchange.json` of trusted publishing is written with the default mode; refusal bodies reach the terminal unfiltered for every registry command; no ownership/symlink check on `<cache>/upload`. Overlap: #279 touches registry.trb, usage.trb, RELEASE.md 7.13 and the README; whichever lands second rebases.
The answer of a request was written to <cache>/upload/answer with the default mode and left there. It can hold a secret - the token of trusted publishing, the grant of a step-up - so the file is now created private, mode 0600 before it is written, and emptied once the reply is read, for every request.
feat(package): step-up for torb owner
All checks were successful
ci / commit messages (pull_request) Successful in 6s
ci / what the change touches (pull_request) Successful in 6s
pdisc / pdisc (pull_request) Successful in 13s
ci / which runners exist (pull_request) Successful in 0s
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
ci / the VS Code extension (editors/vscode) (pull_request) Successful in 14s
ci / bootstrap (linux-x64) (pull_request) Successful in 3m27s
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been skipped
ci / tier A (linux-x64) (pull_request) Successful in 4m20s
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Successful in 1m45s
ci / every host emits the same C (pull_request) Successful in 4m26s
ci / tier B (linux-x64) (pull_request) Successful in 8m57s
ci / pack the seed (pull_request) Has been skipped
ci / archives (pull_request) Has been skipped
ci / the playground (torb as WebAssembly) (pull_request) Successful in 1m52s
ci / gates (pull_request) Successful in 0s
18a24952ab
argus approved these changes 2026-10-09 22:30:49 +00:00
argus left a comment

Approved at 18a2495, CI green on this head.

  • Tests: ok. Unit tests for the option rules (registry-commands.test.trb), plus owner-step-up.test.trb (approved add/remove, grant used up, unapproved/expired/EOF/no-passkey cases, no secret in args/output/files, private files) and the answer-file check in commands.test.trb.
  • Correctness: ok. --step-up ignores TORB_CODE, --code --step-up and --step-up with list are usage errors, the secret is validated as one printable word and goes only through the header file; EOF/read errors send nothing.
  • Hardening (upload.trb): answer file private and emptied after every request, upload dir 0700, all three files emptied even if one fails. Ok.
  • Scope: matches #280 plus the answer-file hardening the new secret flow requires; follow-ups are listed in the PR body.
  • Security/data/docs: ok. No secrets in the diff; torb-owner.md, RELEASE.md 7.13, registry README, skills and pdisc stamp updated; pdisc check green.

Non-blocking:

  • #280 says stdin is "refused when it is not a terminal"; the PR deliberately accepts a pipe (documented and tested). Fine on its rationale, just noting the deviation from the issue text.
  • Follow-ups already named in the PR body (exchange.json mode, unfiltered refusal bodies, no ownership/symlink check on <cache>/upload) deserve issues.
Approved at 18a2495, CI green on this head. - Tests: ok. Unit tests for the option rules (`registry-commands.test.trb`), plus `owner-step-up.test.trb` (approved add/remove, grant used up, unapproved/expired/EOF/no-passkey cases, no secret in args/output/files, private files) and the answer-file check in `commands.test.trb`. - Correctness: ok. `--step-up` ignores `TORB_CODE`, `--code --step-up` and `--step-up` with `list` are usage errors, the secret is validated as one printable word and goes only through the header file; EOF/read errors send nothing. - Hardening (`upload.trb`): answer file private and emptied after every request, `upload` dir 0700, all three files emptied even if one fails. Ok. - Scope: matches #280 plus the answer-file hardening the new secret flow requires; follow-ups are listed in the PR body. - Security/data/docs: ok. No secrets in the diff; `torb-owner.md`, RELEASE.md 7.13, registry README, skills and pdisc stamp updated; pdisc check green. Non-blocking: - #280 says stdin is "refused when it is not a terminal"; the PR deliberately accepts a pipe (documented and tested). Fine on its rationale, just noting the deviation from the issue text. - Follow-ups already named in the PR body (`exchange.json` mode, unfiltered refusal bodies, no ownership/symlink check on `<cache>/upload`) deserve issues.
argus merged commit 22eed51f3b into main 2026-10-09 22:30:50 +00:00
argus deleted branch loop/280-owner-step-up 2026-10-09 22:30:50 +00:00
Sign in to join this conversation.
No reviewers
No labels
loop
ready
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
torbscript/language!287
No description provided.