torb deprecate: flag a whole package as deprecated #279
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Goal
torb deprecate <owner/name> [--use <owner/name>] [--reason "..."]flags a whole package as deprecated, asRELEASE.md section 7.3 describes: shown by
torb addand on the package page, withdraws nothing. Split from #22.Why it is its own issue
Unlike
yank, the registry has no API for it: it needs an endpoint, a stored flag, an index record and a client display.Scope
POST /api/1/packages/<owner>/<name>/deprecate {reason?, use?}andDELETEto undo, for a member with a new or existing action (decide:yankcovers it unless a reason appears to split it); an event in the log.deprecate "acme/http", use: "acme/http2", reason: "..."and anundeprecateline) in the style ofyank/unyank;readIndexandsigning.trbhandle it. Readers already skip a word they do not know (recordsOf), so a client without it keeps resolving; verify that with a test.torb deprecate(and--undo),torb addprints the notice,torb update/installstay silent about it (it withdraws nothing).file:registry: appended unsigned likeyankon afile:registry.Acceptance criteria
torb deprecateand--undoround-trip against the registry over loopback (a temporary database andfile:storage) and on afile:registryrecordsOfon a file with the new line)torb add acme/httpprints the deprecation and its replacement; resolution is unchangeddocs/tooling/torb-deprecate.md, RELEASE.md 7.3/7.4 (index format), registry README API table; skills regeneratedDesign record point
RELEASE.md 7.3 ("Deprecating a whole package") and 7.4 (the index lines). Seed impact: none (TorbScript only). Size: if the registry and the client do not fit one PR of two commits, split the client into a second issue.
Depends on #22 (the registry-resolution and token lookup it introduces).
login,logout,ownerandyankcommands #22login,logout,ownerandyankcommands #22[loop:torbscript] intake: in scope (author orion, label loop, split from #22), not a duplicate, no collision with a design record (RELEASE.md 7.3). Depends on #22 and needs refine (registry endpoint, stored flag, index record, client display). next: waiting (dependency #22)
[loop:torbscript] claim refine by session:loop-torbscript-20261009 until 2026-10-09T23:40Z (dependency #22 landed in
6f9d340b)[loop:torbscript] refine: ready, one PR of two commits (read against main at
6f9d340b, after #22).Goal.
torb deprecate <owner/name> [--use <owner/name>] [--reason <text>] [--undo]flags a whole package as deprecated (RELEASE.md 7.3, "Deprecating a whole package"):torb addshows the notice, nothing is withdrawn, resolution andupdate/installare unchanged.Acceptance criteria (testable, each with its test below)
POST /api/1/packages/<owner>/<name>/deprecate {reason?, use?}appends a signeddeprecateline to the package's index file and stores the flag; a secondPOSTreplaces the notice (the last line holds);DELETEappends a signedundeprecateline and clears the flag,409when the package is not deprecated,404for an unknown package,400for ausethat is not a package name or is the package itself,401/403likeyank. An eventdeprecate/undeprecateis logged with the package as subject.readIndexfolds the two lines intoPackageIndex.deprecation: IndexDeprecation?(use,reason);renderDeprecate/renderUndeprecatewrite them in the style ofrenderYank/renderUnyank.verifyIndex, and a client that does not know the two words keeps verifying and resolving (see decision 4; tested with a frozen reader that skips the words).torb deprecateand--undoround-trip against the write service over loopback (stored token, temporary database,file:storage) and on afile:registry (appended unsigned, refused whereindex/config.trblists keys, exactly asyank).torb add acme/http(alsoacme/http@^1) prints that the package is deprecated, the reason and the replacement; the lock is the one it would have written without the notice;torb update/torb installprint nothing about it.owner/name,--undowith--useor--reason, an unknown flag,--usethat is not a package name), refusals exit 1.docs/tooling/torb-deprecate.md(+index.md,the-torb-command.md,torb-yank.md"Related"), RELEASE.md 7.3/7.4/7.13/7.14, registry README (API table, "Not built yet" losesdeprecate),skills/regenerated.Design record point. RELEASE.md 7.3 (the bullet "Deprecating a whole package"), 7.4 (the index lines), 7.14 (what a signature is over); ROADMAP.md section on the package manager only needs the one-line mention next to
torb yank.Seed impact: none. No syntax change, no new native, no driver flag, no std name looked up by string. The new
IndexRecordcases andPackageIndex.deprecationare compiler-internal TorbScript; the registry builds them through thepath:dependency on the compiler.Size. One PR, two Conventional Commits:
feat(registry): deprecate records in the index and the registry API(index.trb, signing.trb, registry service, API, database, their tests, README).feat(package): torb deprecate and the notice of torb add(CLI, usage,file:registry,addnotice, docs, skills).Files touched.
compiler/src/package/index.trb:IndexDeprecation,IndexRecord.Deprecate/Undeprecate,recordsOf/readIndexfold,recordMessage,renderDeprecate/renderUndeprecate,deprecatedIndex(likeyankedIndex, forfile:), a helper that counts old-kind positions.compiler/src/package/signing.trb:verifyIndexposition/sequence counters.tools/registry/src/registry.trb(deprecatebesideyank,positionIn),api.trb(route["packages", owner, name, "deprecate"],DeprecateRequest),database.trb(columns and migration).compiler/src/cli/registry.trb(deprecatecommand,--use),cli/usage.trb,main.trb(command list at thelogin|logout|owner|yankarm),cli/packages.trb(notice inrunAdd),tools/command-line.sh,tests/command-line/arguments.expected.compiler/tests/packages.test.trb,compiler/tests/registry-commands.test.trb,tools/registry/tests/server.test.trb,tools/registry/tests/commands.test.trb.docs/tooling/torb-deprecate.md(new),docs/tooling/index.md,the-torb-command.md,torb-yank.md,docs/design/RELEASE.md,docs/ROADMAP.md,tools/registry/README.md,docs/skills/torbscript-projects/SKILL.md, regeneratedskills/**,.pdisc-sidecar.yaml/INDEX.mdaspdiscasks.Test plan (forge CI, no local suites).
compiler/tests/packages.test.trb: render/read round trip; fold (deprecate, replace, undeprecate, a line naming another package is an error);verifyIndexon a filerelease, deprecate, yank, undeprecate, unyankwith keys; a replayed olderundeprecateand a moveddeprecateare refused; a frozen "previous reader" (local function that skips the two words and counts only release/yank/unyank) computes the same positions and the samecandidatesOfresult.compiler/tests/registry-commands.test.trb: option parsing and every usage error; thefile:registry append, undo, signed-registry refusal.tools/registry/tests/server.test.trb: the endpoint (success, replace, undo, each refusal above, token withoutyankrefused, event logged, columns set and cleared), every record of the resulting file verifying.tools/registry/tests/commands.test.trb: extend the loopback round: deprecate with the stored token,torb addprints notice and replacement and writes the same lock,--undo, token in no curl argument (existing assertions keep holding).command-line.shagainstarguments.expected,docs skill --check,format --check, pdisc.Implementer. opus / high (compiler/src and signed-index code of the registry).
Dependencies and overlap. #22 landed (
6f9d340b). PR #282 (#276) editstools/registry/src/registry.trb,api.trb,database.trb,tools/registry/README.md,docs/design/RELEASE.md,.pdisc-sidecar.yaml,INDEX.md: start from main after #282 merged, or rebase onto it before opening the PR. #280 editscompiler/src/cli/registry.trb,cli/usage.trb, RELEASE.md 7.13 and the registry README as well (textual overlap only; whichever lands second rebases).[loop:torbscript] decided by the loop: the
yankaction covers deprecation, no new action. A new action would leave every existing token unable to deprecate, change the token/everyActioncontract and the account page for one rarely used call; a deprecation is the same kind of power as a yank (a publisher or owner of the package). Authorization ismayWritePackage(caller, package, "yank").[loop:torbscript] decided by the loop: record shape and semantics.
deprecate "acme/http", use: "acme/http2", reason: "...", signature: "..."andundeprecate "acme/http", signature: "..."(the issue's form); the positional package must equal the file'spackageorreadIndexfails.useandreasonare both optional and trimmed;usemust be a valid package name other than the package itself but need not exist on this registry (it may live elsewhere). The last of the two words holds; deprecating again replaces the notice (no409), undoing when not deprecated is a409.[loop:torbscript] decided by the loop: signature positions, so old clients keep working. Today a record's signed
positionis the count of recordsrecordsOfreturned before it, and an old client counts onlyrelease/yank/unyankbecause it skips unknown words. If deprecation lines counted inposition, every record after the firstdeprecatewould fail verification in every existingtorb(RELEASE.md 7.14: "a record the registry did not sign is never seen"), i.e. a deprecation would break resolution of that package for all current clients. Therefore:positioncounts only the three old kinds (so no existing signature changes), and a deprecation record is signed overtorb index record 1, the package,position(old kinds before it),sequence(deprecation records before it), then its own fields.sequencestops a mirror from replaying an oldundeprecateafter a laterdeprecate;positionpins it between the same neighbours.positionInin the registry andverifyIndexcount the same way. 7.14's "What a signature is over" row records this.[loop:torbscript] decided by the loop: the stored flag is three columns on
packages(deprecated,deprecated_use,deprecated_reason), added by anALTER TABLEmigration in the style oftokens.factor; the index stays the truth, as for yanks. Search results and the package page do not show it in this PR: the page is slice 13 and does not exist, search is #241.[loop:torbscript] decided by the loop: client display.
torb addprints one notice per package named on its command line (not transitive ones), after the resolution succeeded, from the index it already reads and verifies (the cached copy offline).updateandinstallstay silent, as the issue says. No split of the client into a second issue: the pieces are small enough for the two commits.next: implement
torb owner --step-up: approve owner changes with a passkey #280[loop:torbscript] implement: deferred until PR #282 lands (shared registry files, per the refine). next: waiting (PR #282 merge)
login,logout,ownerandyankcommands #22[loop:torbscript] claim implement by session:loop-torbscript-20261010 until 2026-10-10T05:50Z (PR #282 landed as
765a6218, the dependency named in the refine)[loop:torbscript] claim released by session:loop-torbscript-20261010: no worker was started (sessions_spawn was not available in this tick), so the claim until 2026-10-10T05:50Z is void. PR #282 landed as
765a6218, #279 is unblocked. next: implement[loop:torbscript] claim implement by session:loop-torbscript-20261010 until 2026-10-10T06:10Z (a worker for this item is running since 00:09Z; the release in the previous comment was written by a tick that could not spawn)
[loop:torbscript] implement: PR #292, CI success (all jobs green on the first run), worker usage unknown, next: waiting (review by the merge gate argus)
[loop:torbscript] done: PR #292 merged by argus as
e74cdc49(PR CI green on head0b6138e6; the PR has no After-merge steps). Issue closed by the PR. Merge-commit CI on main still running at 02:59 Berlin.