@retasc/cli 1.19.0 → 1.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/dist/commands/billing.js +4 -2
- package/dist/commands/bind.js +2 -2
- package/dist/commands/join.js +3 -2
- package/dist/index.js +4 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,13 @@ release commits and the issues they reference.
|
|
|
6
6
|
|
|
7
7
|
Dates are the npm publish date. Each entry names the RTSC issue behind it.
|
|
8
8
|
|
|
9
|
+
## 1.20.0 (2026-08-04)
|
|
10
|
+
|
|
11
|
+
- **RTSC-561** — the org gained an **admin** role, and the CLI stopped refusing it.
|
|
12
|
+
`retasc billing` gated on `role !== "owner"` client-side, so it would have refused an
|
|
13
|
+
admin locally for a call the server allows. Owner-only copy in `bind` and the command
|
|
14
|
+
help now names both roles.
|
|
15
|
+
|
|
9
16
|
## 1.19.0 (2026-08-03)
|
|
10
17
|
|
|
11
18
|
- **RTSC-495** — `retasc bind --setup <code>` sets a folder up with no sign-in and nothing
|
package/dist/commands/billing.js
CHANGED
|
@@ -44,8 +44,10 @@ export async function billingAction(opts) {
|
|
|
44
44
|
const org = me.orgs.find((o) => o.id === orgId);
|
|
45
45
|
orgLabel = org ? `${org.name}${org.slug ? ` (${org.slug})` : ""}` : String(orgId);
|
|
46
46
|
// Fail early with the actionable message rather than a raw FORBIDDEN from the server.
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
// Owner OR admin (RTSC-561) — this mirrors `requireOwnerOrAdmin`, and a stale copy of
|
|
48
|
+
// the rule here would refuse an admin locally for a call the server would have allowed.
|
|
49
|
+
if (org && org.role !== "owner" && org.role !== "admin") {
|
|
50
|
+
throw new Error(`Billing needs the owner or admin role — yours in ${orgLabel} is "${org.role}".`);
|
|
49
51
|
}
|
|
50
52
|
const [status, charges] = await Promise.all([
|
|
51
53
|
api.billingStatus({ orgId: orgId }),
|
package/dist/commands/bind.js
CHANGED
|
@@ -286,7 +286,7 @@ export async function completeWorkspaceSetup(args) {
|
|
|
286
286
|
let prefix;
|
|
287
287
|
if (!projectId && opts.project && opts.prefix) {
|
|
288
288
|
if (!args.canCreateProject) {
|
|
289
|
-
cliError("FORBIDDEN", "Only an owner can create a project.", `Ask
|
|
289
|
+
cliError("FORBIDDEN", "Only an owner or admin can create a project.", `Ask one of them to add one, then pass --project-id <id>.`);
|
|
290
290
|
}
|
|
291
291
|
const p = (await api.createProject({ orgId, name: opts.project, prefix: opts.prefix }));
|
|
292
292
|
projectId = p.projectId;
|
|
@@ -301,7 +301,7 @@ export async function completeWorkspaceSetup(args) {
|
|
|
301
301
|
// what to ask for, by name. A bare FORBIDDEN from `createProject` would be both
|
|
302
302
|
// wrong (they never asked to create anything) and unactionable.
|
|
303
303
|
if (!list.length) {
|
|
304
|
-
cliError("NO_PROJECTS", `Org ${org} has no projects yet, and only an owner can create one.`, `Ask
|
|
304
|
+
cliError("NO_PROJECTS", `Org ${org} has no projects yet, and only an owner or admin can create one.`, `Ask one of them to add a project, then finish this folder with: ${selfCommand(VERSION)} bind --org-id ${orgId}`);
|
|
305
305
|
}
|
|
306
306
|
// One project is not a choice. Asking anyway would be the only question in the
|
|
307
307
|
// common invite path, for an answer that was never in doubt.
|
package/dist/commands/join.js
CHANGED
|
@@ -223,8 +223,9 @@ export async function joinAction(link, opts) {
|
|
|
223
223
|
orgLabel,
|
|
224
224
|
opts,
|
|
225
225
|
existing: guard.existing,
|
|
226
|
-
// `createProject` is `
|
|
227
|
-
//
|
|
226
|
+
// `createProject` is `requireOwnerOrAdmin`, and an invite only ever grants `member`
|
|
227
|
+
// (admin is granted by `setMemberRole` after joining, never by a bearer code —
|
|
228
|
+
// RTSC-561). Offering "+ create new" here would be offering a refusal as a choice.
|
|
228
229
|
canCreateProject: false,
|
|
229
230
|
});
|
|
230
231
|
}
|
package/dist/index.js
CHANGED
|
@@ -211,7 +211,7 @@ program
|
|
|
211
211
|
});
|
|
212
212
|
program
|
|
213
213
|
.command("billing")
|
|
214
|
-
.description("Show the org's billing: subscription, what's owed now, and the charge + on-chain payment history across every payment link ever used (owner
|
|
214
|
+
.description("Show the org's billing: subscription, what's owed now, and the charge + on-chain payment history across every payment link ever used (owner or admin).")
|
|
215
215
|
.option("--org-id <id>", "Which org (defaults to your only one).")
|
|
216
216
|
.option("--json", "Emit the raw payload instead of the summary.")
|
|
217
217
|
.action(async (opts) => {
|
|
@@ -356,7 +356,7 @@ key
|
|
|
356
356
|
const members = program.command("members").description("Invite people to an org and manage invites.");
|
|
357
357
|
members
|
|
358
358
|
.command("invite")
|
|
359
|
-
.description("Mint a single-use invite code for an org (owner
|
|
359
|
+
.description("Mint a single-use invite code for an org (owner or admin). Shown once.")
|
|
360
360
|
.requiredOption("--org-id <id>")
|
|
361
361
|
.option("--expires-days <n>", "Days until the code expires (1–30, default 7)", (v) => parseInt(v, 10))
|
|
362
362
|
.action(async (opts) => {
|
|
@@ -377,7 +377,7 @@ members
|
|
|
377
377
|
});
|
|
378
378
|
members
|
|
379
379
|
.command("list")
|
|
380
|
-
.description("List an org's invites and their status (owner
|
|
380
|
+
.description("List an org's invites and their status (owner or admin).")
|
|
381
381
|
.requiredOption("--org-id <id>")
|
|
382
382
|
.option("--json", "Emit the raw payload instead of the table.")
|
|
383
383
|
.action(async (opts) => {
|
|
@@ -392,7 +392,7 @@ members
|
|
|
392
392
|
});
|
|
393
393
|
members
|
|
394
394
|
.command("revoke")
|
|
395
|
-
.description("Revoke an unused invite (owner
|
|
395
|
+
.description("Revoke an unused invite (owner or admin).")
|
|
396
396
|
.requiredOption("--invite-id <id>")
|
|
397
397
|
.action(async (opts) => {
|
|
398
398
|
requireLogin();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@retasc/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.20.0",
|
|
4
4
|
"description": "Retasc CLI \u2014 the issue tracker AI agents pull work from. Sign in with GitHub or Google, create projects, mint agent API keys, and wire your agent to the Retasc MCP server in one command.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|