@devdogsuga/backstage 0.1.4 → 0.1.5
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/README.md
CHANGED
|
@@ -112,8 +112,10 @@ entry for them (`envFree` in the command tree).
|
|
|
112
112
|
## Shared logins: `creds`
|
|
113
113
|
|
|
114
114
|
The club's shared logins (Instagram, Canva, ArchPass, Linktree, later project
|
|
115
|
-
API keys) live
|
|
116
|
-
|
|
115
|
+
API keys) live in the DevDogs Bitwarden organization, in whatever collection
|
|
116
|
+
suits them. `creds` hands any login or secure note there to officers as a
|
|
117
|
+
Bitwarden Send. Personal items, other organizations' items and production
|
|
118
|
+
secrets (which are in Secrets Manager, not the vault) are out of its reach.
|
|
117
119
|
|
|
118
120
|
- **`send`** picks items and recipients (officers by name or by role, read live
|
|
119
121
|
from production: everyone holding a role other than `Member`, by UGA MyID
|
|
@@ -122,16 +124,18 @@ Bitwarden organization. `creds` hands them to officers as Bitwarden Sends:
|
|
|
122
124
|
recipients and deleted 30 days out. Removing an address revokes it. Addresses
|
|
123
125
|
off the roster need `--allow-email`. Non-interactive: `--item`, `--to`,
|
|
124
126
|
`--role`, `--yes`.
|
|
125
|
-
- **`add`** saves a new login
|
|
126
|
-
|
|
127
|
-
|
|
127
|
+
- **`add`** saves a new login to the organization, then sends it. It goes in
|
|
128
|
+
the one collection you can see, or the one you pick (`--collection` with no
|
|
129
|
+
terminal). The password is typed at a hidden prompt, or read with
|
|
130
|
+
`--password-stdin`; never argv.
|
|
128
131
|
- **`renew`** pushes each Send's deletion 30 days out in place (the link stays)
|
|
129
132
|
and re-syncs its recipients and body from the item. It asks first for any Send
|
|
130
133
|
with more than 7 days left.
|
|
131
134
|
- **`list`** prints items, recipients and expiry (`--json` for scripts).
|
|
132
135
|
- **`report`** regenerates the **Shared Accounts** Linear document (Platform &
|
|
133
|
-
DevOps initiative), which `send`, `add` and `renew` also do. It
|
|
134
|
-
whole; edits there are
|
|
136
|
+
DevOps initiative), which `send`, `add` and `renew` also do. It lists only
|
|
137
|
+
items that have been shared, and is generated whole; edits there are
|
|
138
|
+
overwritten.
|
|
135
139
|
|
|
136
140
|
Each item's custom fields are the only access record: `Recipients`, `Owner`,
|
|
137
141
|
`Send ID`, `Send link`, `Send expires`, `Send account`. Sends belong to the
|
|
@@ -928,7 +928,7 @@ const completionsCommand = {
|
|
|
928
928
|
const ITEM = {
|
|
929
929
|
flag: "--item",
|
|
930
930
|
value: "<name>",
|
|
931
|
-
summary: "A
|
|
931
|
+
summary: "A DevDogs organization item, by name or id. Repeat for several."
|
|
932
932
|
};
|
|
933
933
|
const TO = {
|
|
934
934
|
flag: "--to",
|
|
@@ -982,7 +982,7 @@ const credsCommand = {
|
|
|
982
982
|
{
|
|
983
983
|
name: "add",
|
|
984
984
|
envFree: true,
|
|
985
|
-
summary: "Save a new
|
|
985
|
+
summary: "Save a new login to the DevDogs organization, then send it.",
|
|
986
986
|
options: [
|
|
987
987
|
{
|
|
988
988
|
flag: "--name",
|
|
@@ -1004,6 +1004,11 @@ const credsCommand = {
|
|
|
1004
1004
|
value: "<name>",
|
|
1005
1005
|
summary: "The officer responsible for the account."
|
|
1006
1006
|
},
|
|
1007
|
+
{
|
|
1008
|
+
flag: "--collection",
|
|
1009
|
+
value: "<name>",
|
|
1010
|
+
summary: "Where to save it, when you can see more than one."
|
|
1011
|
+
},
|
|
1007
1012
|
{
|
|
1008
1013
|
flag: "--password-stdin",
|
|
1009
1014
|
summary: "Read the password from stdin, for scripts."
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { C as discoverRepoRoot, T as cliName, b as ownPackageDir, c as reportDevtoolsError, f as isNoEnv, l as reportDevtoolsFailure, n as captureDevtoolsError, o as initDevtoolsTelemetry, p as isNonInteractive, w as findRepoRoot, x as ownVersion } from "./telemetry-Bjoz29Hl.js";
|
|
2
|
-
import { a as recordEnteredTier, f as helpPath, i as beginInvocation, l as dbPush, m as renderHelp, n as bareGroupStartPath, o as recordResolved, p as renderCommandList, r as runMenu, s as reproducibleCommand, t as catalog, u as dbPushDryRun } from "./catalog-
|
|
2
|
+
import { a as recordEnteredTier, f as helpPath, i as beginInvocation, l as dbPush, m as renderHelp, n as bareGroupStartPath, o as recordResolved, p as renderCommandList, r as runMenu, s as reproducibleCommand, t as catalog, u as dbPushDryRun } from "./catalog-BUOwCd2Q.js";
|
|
3
3
|
import { a as repoPeerUrl, n as loadEnv, r as loadEnvLoad, t as getEnvSync } from "./peers-B0KDkI6a.js";
|
|
4
4
|
import { t as nonEmpty } from "./connection-D3XsOE3S.js";
|
|
5
5
|
import { a as dryRunKind, l as wouldRunLine, o as isDryRun } from "./options-BTjOf5KP.js";
|
|
@@ -5270,7 +5270,7 @@ const HANDLERS = {
|
|
|
5270
5270
|
graphics: async (rest) => (await import("./commands-Dv5TXjvb.js")).handleGraphics(rest),
|
|
5271
5271
|
qr: async (rest) => (await import("./commands-Bk7IbhPD.js")).handleQr(rest),
|
|
5272
5272
|
newsletter: async (rest) => (await import("./commands-D345F-Od.js")).handleNewsletter(rest),
|
|
5273
|
-
creds: async (rest) => (await import("./commands-
|
|
5273
|
+
creds: async (rest) => (await import("./commands-BMQ1OZIr.js")).handleCreds(rest)
|
|
5274
5274
|
};
|
|
5275
5275
|
/**
|
|
5276
5276
|
* Names that were commands of the contributor CLI, refused with where they
|
|
@@ -4,7 +4,7 @@ import { a as explainError, i as explain, o as unwrap, r as errorMessage, t as U
|
|
|
4
4
|
import { c as EnvDocument, i as readPasswordFromVault, n as bwArgs, r as openVault, s as bwCommand } from "./vault-C8LYJFOQ.js";
|
|
5
5
|
import { t as DONE } from "./dispatch-D048O65I.js";
|
|
6
6
|
import { resolve } from "node:path";
|
|
7
|
-
import { confirm, log, multiselect, note, password, text } from "@clack/prompts";
|
|
7
|
+
import { confirm, log, multiselect, note, password, select, text } from "@clack/prompts";
|
|
8
8
|
import { readFile } from "node:fs/promises";
|
|
9
9
|
import { spawn } from "node:child_process";
|
|
10
10
|
import { parseArgs } from "node:util";
|
|
@@ -51,12 +51,12 @@ var CredsError = class extends Error {
|
|
|
51
51
|
//#endregion
|
|
52
52
|
//#region src/creds/item.ts
|
|
53
53
|
/**
|
|
54
|
-
* A shared account as `creds` sees it: a
|
|
55
|
-
*
|
|
54
|
+
* A shared account as `creds` sees it: a login or secure note in the DevDogs
|
|
55
|
+
* Bitwarden organization, plus the custom fields that record who has it.
|
|
56
56
|
*
|
|
57
57
|
* Those fields are the only access record. The Send, the Linear report and
|
|
58
58
|
* every "who has Canva?" answer are generated from them, so they are plain
|
|
59
|
-
* text fields anyone
|
|
59
|
+
* text fields anyone with the item can read and correct in Bitwarden
|
|
60
60
|
* itself:
|
|
61
61
|
*
|
|
62
62
|
* Recipients comma-separated UGA emails, the Send's `--emails` list
|
|
@@ -194,8 +194,8 @@ function isoDay(date) {
|
|
|
194
194
|
//#endregion
|
|
195
195
|
//#region src/creds/bitwarden.ts
|
|
196
196
|
/**
|
|
197
|
-
* The
|
|
198
|
-
* bundled `bw` on the officer's personal session (`bws/vault.ts`).
|
|
197
|
+
* The DevDogs Bitwarden organization's items and the Sends made from them,
|
|
198
|
+
* through the bundled `bw` on the officer's personal session (`bws/vault.ts`).
|
|
199
199
|
*
|
|
200
200
|
* Sends belong to the account that creates them, not to the organization, so
|
|
201
201
|
* this always runs as a person and never on CI.
|
|
@@ -203,20 +203,23 @@ function isoDay(date) {
|
|
|
203
203
|
* ## Secret handling
|
|
204
204
|
*
|
|
205
205
|
* * Every value travels to `bw` on **stdin**, base64 JSON as `bw create`,
|
|
206
|
-
* `bw edit` and `bw send create|edit` document. argv carries only ids
|
|
207
|
-
* the
|
|
206
|
+
* `bw edit` and `bw send create|edit` document. argv carries only ids and
|
|
207
|
+
* the session key `bwArgs` already passes.
|
|
208
208
|
* * `bw`'s stdout is parsed and never printed: an item or a Send read back
|
|
209
209
|
* holds the password.
|
|
210
210
|
* * `bw`'s stderr is only shown through `CredsError`, which scrubs every value
|
|
211
211
|
* registered so far.
|
|
212
212
|
*
|
|
213
|
-
* ## The
|
|
213
|
+
* ## The organization fence
|
|
214
214
|
*
|
|
215
|
-
* `creds` reads and writes
|
|
216
|
-
*
|
|
217
|
-
* never edited and never sent;
|
|
215
|
+
* `creds` reads and writes the logins and secure notes of ONE organization,
|
|
216
|
+
* found by name. Anything else the account can see (a personal login, another
|
|
217
|
+
* organization's item) is never listed, never edited and never sent;
|
|
218
|
+
* `updateItem` re-checks before every write. Production secrets are not
|
|
219
|
+
* vault items at all: they live in Secrets Manager, which `bw` cannot read.
|
|
218
220
|
*/
|
|
219
|
-
|
|
221
|
+
/** Matched case-insensitively against the organizations the account belongs to. */
|
|
222
|
+
const ORGANIZATION_NAME = "DevDogs";
|
|
220
223
|
function encode(value) {
|
|
221
224
|
return Buffer.from(JSON.stringify(value)).toString("base64");
|
|
222
225
|
}
|
|
@@ -249,7 +252,7 @@ function spawnRunner(key) {
|
|
|
249
252
|
});
|
|
250
253
|
}
|
|
251
254
|
let runnerOverride;
|
|
252
|
-
/** Opens the vault (asking first) and the
|
|
255
|
+
/** Opens the vault (asking first) and finds the DevDogs organization in it. */
|
|
253
256
|
async function connectSharedVault() {
|
|
254
257
|
let runner = runnerOverride;
|
|
255
258
|
if (!runner) {
|
|
@@ -259,7 +262,7 @@ async function connectSharedVault() {
|
|
|
259
262
|
}
|
|
260
263
|
const shared = new SharedVault(runner);
|
|
261
264
|
await shared.sync();
|
|
262
|
-
await shared.
|
|
265
|
+
await shared.organization();
|
|
263
266
|
return shared;
|
|
264
267
|
}
|
|
265
268
|
var SharedVault = class {
|
|
@@ -287,34 +290,45 @@ var SharedVault = class {
|
|
|
287
290
|
async account() {
|
|
288
291
|
return (await this.json(["status"])).userEmail ?? "unknown";
|
|
289
292
|
}
|
|
290
|
-
/** The one
|
|
291
|
-
async
|
|
293
|
+
/** The one organization named like {@link ORGANIZATION_NAME} this account belongs to. */
|
|
294
|
+
async organization() {
|
|
292
295
|
if (this.found) return this.found;
|
|
293
|
-
const matches = (await this.json(["list", "
|
|
294
|
-
if (matches.length !== 1) throw new CredsError(matches.length === 0 ? `
|
|
296
|
+
const matches = (await this.json(["list", "organizations"])).filter((o) => o.name.toLowerCase().includes(ORGANIZATION_NAME.toLowerCase()));
|
|
297
|
+
if (matches.length !== 1) throw new CredsError(matches.length === 0 ? `Your Bitwarden account is not in the ${ORGANIZATION_NAME} organization. Ask an organization admin to invite you.` : `Your Bitwarden account is in ${matches.length} organizations named like "${ORGANIZATION_NAME}" (${matches.map((o) => o.name).join(", ")}); creds cannot tell which one to use.`);
|
|
295
298
|
this.found = matches[0];
|
|
296
299
|
return this.found;
|
|
297
300
|
}
|
|
298
|
-
|
|
299
|
-
return raw.organizationId ===
|
|
301
|
+
shareable(raw, org) {
|
|
302
|
+
return raw.organizationId === org.id && (raw.type === ITEM_TYPE.login || raw.type === ITEM_TYPE.secureNote);
|
|
300
303
|
}
|
|
301
|
-
/** Every
|
|
304
|
+
/** Every login and secure note in the organization, by name. */
|
|
302
305
|
async listItems() {
|
|
303
|
-
const
|
|
306
|
+
const org = await this.organization();
|
|
304
307
|
return (await this.json([
|
|
305
308
|
"list",
|
|
306
309
|
"items",
|
|
307
|
-
"--
|
|
308
|
-
|
|
309
|
-
])).filter((item) => this.
|
|
310
|
+
"--organizationid",
|
|
311
|
+
org.id
|
|
312
|
+
])).filter((item) => this.shareable(item, org)).map(parseItem).sort((a, b) => a.name.localeCompare(b.name));
|
|
310
313
|
}
|
|
311
|
-
/**
|
|
314
|
+
/** The organization's collections this account can see, by name. */
|
|
315
|
+
async collections() {
|
|
316
|
+
const org = await this.organization();
|
|
317
|
+
return (await this.json([
|
|
318
|
+
"list",
|
|
319
|
+
"collections",
|
|
320
|
+
"--organizationid",
|
|
321
|
+
org.id
|
|
322
|
+
])).filter((c) => c.organizationId === org.id).sort((a, b) => a.name.localeCompare(b.name));
|
|
323
|
+
}
|
|
324
|
+
/** A new login, owned by the organization and placed in `collection`. */
|
|
312
325
|
async createLogin(input) {
|
|
313
326
|
registerSecret(input.password);
|
|
314
|
-
const
|
|
327
|
+
const org = await this.organization();
|
|
328
|
+
if (input.collection.organizationId !== org.id) throw new CredsError(`The "${input.collection.name}" collection is not in the ${org.name} organization.`);
|
|
315
329
|
const item = {
|
|
316
|
-
organizationId:
|
|
317
|
-
collectionIds: [collection.id],
|
|
330
|
+
organizationId: org.id,
|
|
331
|
+
collectionIds: [input.collection.id],
|
|
318
332
|
folderId: null,
|
|
319
333
|
type: 1,
|
|
320
334
|
name: input.name,
|
|
@@ -338,10 +352,10 @@ var SharedVault = class {
|
|
|
338
352
|
};
|
|
339
353
|
return parseItem(await this.json(["create", "item"], encode(item)));
|
|
340
354
|
}
|
|
341
|
-
/** Saves `raw`, which must still be
|
|
355
|
+
/** Saves `raw`, which must still be a login or secure note of the organization. */
|
|
342
356
|
async updateItem(raw) {
|
|
343
|
-
const
|
|
344
|
-
if (!this.
|
|
357
|
+
const org = await this.organization();
|
|
358
|
+
if (!this.shareable(raw, org)) throw new CredsError(`"${raw.name}" is not a login or secure note of the ${org.name} organization; creds will not change it.`);
|
|
345
359
|
return parseItem(await this.json([
|
|
346
360
|
"edit",
|
|
347
361
|
"item",
|
|
@@ -420,7 +434,7 @@ function sendName(item) {
|
|
|
420
434
|
}
|
|
421
435
|
/** Private to the sender: how to find the item this Send came from. */
|
|
422
436
|
function sendNotes(item) {
|
|
423
|
-
return `Made by backstage creds from the ${
|
|
437
|
+
return `Made by backstage creds from the ${ORGANIZATION_NAME} item "${item.name}" (${item.id}).`;
|
|
424
438
|
}
|
|
425
439
|
function deletionDate(now) {
|
|
426
440
|
return new Date(now.getTime() + 2592e6).toISOString();
|
|
@@ -653,17 +667,18 @@ function cell(text) {
|
|
|
653
667
|
/** The document's markdown. Pure: `now` decides the statuses. */
|
|
654
668
|
function renderReport(items, now, roster) {
|
|
655
669
|
const lines = [
|
|
656
|
-
"> Generated by `backstage creds` from the
|
|
670
|
+
"> Generated by `backstage creds` from the DevDogs Bitwarden organization: every item shared as a Send. Manual edits are overwritten on the next run; change the item's fields in Bitwarden, or run `backstage creds send`.",
|
|
657
671
|
"",
|
|
658
672
|
`Last generated ${now.toISOString().slice(0, 16).replace("T", " ")} UTC. Sends are deleted 30 days after they were last renewed; **Expires Soon** means within 7 days, so run \`backstage creds renew\`.`,
|
|
659
673
|
""
|
|
660
674
|
];
|
|
661
|
-
|
|
662
|
-
|
|
675
|
+
const shared = items.filter((i) => i.recipients.length > 0 || i.send !== void 0);
|
|
676
|
+
if (shared.length === 0) {
|
|
677
|
+
lines.push("Nothing has been shared yet.");
|
|
663
678
|
return `${lines.join("\n")}\n`;
|
|
664
679
|
}
|
|
665
680
|
lines.push("| Credential | Account | Recipients | Owner | Status | Expires | Send |", "| --- | --- | --- | --- | --- | --- | --- |");
|
|
666
|
-
for (const item of
|
|
681
|
+
for (const item of shared) {
|
|
667
682
|
const recipients = item.recipients.length > 0 ? item.recipients.map((e) => describeRecipient(roster, e)).join(", ") : "—";
|
|
668
683
|
const link = item.send?.link ? `[Open](${item.send.link})` : "—";
|
|
669
684
|
lines.push(`| ${[
|
|
@@ -729,7 +744,7 @@ async function writeReport(token, documentId, content, fetchImpl = fetch) {
|
|
|
729
744
|
* shared as Bitwarden Sends that only the officers they name can open.
|
|
730
745
|
*
|
|
731
746
|
* send pick shared accounts and officers; create or update one Send each
|
|
732
|
-
* add save a new login
|
|
747
|
+
* add save a new login to the DevDogs organization, then send it
|
|
733
748
|
* renew push every Send's deletion 30 days out and re-sync its recipients
|
|
734
749
|
* list what is shared with whom, until when
|
|
735
750
|
* report regenerate the Shared Accounts Linear document
|
|
@@ -738,8 +753,8 @@ async function writeReport(token, documentId, content, fetchImpl = fetch) {
|
|
|
738
753
|
*
|
|
739
754
|
* ## Where things live
|
|
740
755
|
*
|
|
741
|
-
* The values live only in the DevDogs Bitwarden organization
|
|
742
|
-
*
|
|
756
|
+
* The values live only in the DevDogs Bitwarden organization: any login or
|
|
757
|
+
* secure note in it can be shared. Each item's custom fields record its recipients and its
|
|
743
758
|
* Send (`item.ts`); the Linear document is generated from them (`report.ts`);
|
|
744
759
|
* the roster of who may receive one is read live from production
|
|
745
760
|
* (`roster.ts`).
|
|
@@ -790,6 +805,7 @@ function parse(argv) {
|
|
|
790
805
|
url: { type: "string" },
|
|
791
806
|
username: { type: "string" },
|
|
792
807
|
owner: { type: "string" },
|
|
808
|
+
collection: { type: "string" },
|
|
793
809
|
"password-stdin": { type: "boolean" },
|
|
794
810
|
document: { type: "string" },
|
|
795
811
|
"dry-run": { type: "boolean" }
|
|
@@ -831,7 +847,7 @@ function findItem(items, typed) {
|
|
|
831
847
|
}
|
|
832
848
|
async function pickItems(items, typed, message) {
|
|
833
849
|
if (typed && typed.length > 0) return typed.map((t) => findItem(items, t));
|
|
834
|
-
if (items.length === 0) throw new UsageError("The
|
|
850
|
+
if (items.length === 0) throw new UsageError("The DevDogs organization has no logins you can see. Add one with `backstage creds add`.");
|
|
835
851
|
if (!interactive()) throw new UsageError("Name the accounts with --item <name>.");
|
|
836
852
|
const ids = unwrap(await multiselect({
|
|
837
853
|
message,
|
|
@@ -1023,17 +1039,40 @@ async function ask(given, message, required) {
|
|
|
1023
1039
|
validate: required ? (v) => v?.trim() ? void 0 : "Required." : void 0
|
|
1024
1040
|
}))?.trim() || void 0;
|
|
1025
1041
|
}
|
|
1042
|
+
/** `--collection`, the only one there is, or a choice. Every organization item needs one. */
|
|
1043
|
+
async function pickCollection(vault, typed) {
|
|
1044
|
+
const all = await vault.collections();
|
|
1045
|
+
if (typed !== void 0) {
|
|
1046
|
+
const needle = typed.trim().toLowerCase();
|
|
1047
|
+
const match = all.find((c) => c.name.toLowerCase() === needle);
|
|
1048
|
+
if (!match) throw new UsageError(`No collection called "${typed}" that you can see. There are: ${all.map((c) => c.name).join(", ") || "none"}.`);
|
|
1049
|
+
return match;
|
|
1050
|
+
}
|
|
1051
|
+
if (all.length === 0) throw new UsageError("You cannot see any collection in the DevDogs organization to save to. Ask an organization admin for access to one.");
|
|
1052
|
+
if (all.length === 1) return all[0];
|
|
1053
|
+
if (!interactive()) throw new UsageError(`Name the collection with --collection: ${all.map((c) => c.name).join(", ")}.`);
|
|
1054
|
+
const id = unwrap(await select({
|
|
1055
|
+
message: "Which collection?",
|
|
1056
|
+
options: all.map((c) => ({
|
|
1057
|
+
value: c.id,
|
|
1058
|
+
label: c.name
|
|
1059
|
+
}))
|
|
1060
|
+
}));
|
|
1061
|
+
return all.find((c) => c.id === id);
|
|
1062
|
+
}
|
|
1026
1063
|
async function runAdd(vault, values, deps) {
|
|
1027
1064
|
const existing = await vault.listItems();
|
|
1028
1065
|
const name = await ask(values.name, "Name? (e.g. Instagram)", true);
|
|
1029
|
-
if (existing.some((i) => i.name.toLowerCase() === name.toLowerCase())) throw new UsageError(`"${name}" is already in the
|
|
1066
|
+
if (existing.some((i) => i.name.toLowerCase() === name.toLowerCase())) throw new UsageError(`"${name}" is already in the organization. Use \`backstage creds send --item "${name}"\`.`);
|
|
1030
1067
|
const url = await ask(values.url, "Login page URL? (optional)", false);
|
|
1031
1068
|
const username = await ask(values.username, "Username or email? (optional)", false);
|
|
1032
1069
|
const password = await readPassword(values, deps);
|
|
1033
1070
|
registerSecret(password);
|
|
1034
1071
|
const notes = interactive() ? await ask(void 0, "Notes for recipients? (optional, never printed)", false) : void 0;
|
|
1035
1072
|
const owner = await ask(values.owner, "Owner? (the officer responsible)", false);
|
|
1073
|
+
const collection = await pickCollection(vault, values.collection);
|
|
1036
1074
|
const item = await vault.createLogin({
|
|
1075
|
+
collection,
|
|
1037
1076
|
name,
|
|
1038
1077
|
url,
|
|
1039
1078
|
username,
|
|
@@ -1041,7 +1080,7 @@ async function runAdd(vault, values, deps) {
|
|
|
1041
1080
|
notes,
|
|
1042
1081
|
owner
|
|
1043
1082
|
});
|
|
1044
|
-
say(`Saved ${item.name} to the
|
|
1083
|
+
say(`Saved ${item.name} to the ${collection.name} collection.`, "success");
|
|
1045
1084
|
await sendItems(vault, [item], values, deps);
|
|
1046
1085
|
}
|
|
1047
1086
|
async function runRenew(vault, values, deps) {
|
package/dist/launch.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { C as discoverRepoRoot, E as setCliName, S as RepoNotFoundError, T as cliName, _ as installFailureLog, d as hasYes, g as stripTierFlag, h as stripNoEnvFlag, m as setNoEnv, n as captureDevtoolsError, o as initDevtoolsTelemetry, p as isNonInteractive, s as lastSentryEventId } from "./telemetry-Bjoz29Hl.js";
|
|
2
|
-
import { c as setMenuEnvHook, d as formatCommand, f as helpPath, n as bareGroupStartPath, t as catalog } from "./catalog-
|
|
2
|
+
import { c as setMenuEnvHook, d as formatCommand, f as helpPath, n as bareGroupStartPath, t as catalog } from "./catalog-BUOwCd2Q.js";
|
|
3
3
|
import { i as loadEnvSession, r as loadEnvLoad } from "./peers-B0KDkI6a.js";
|
|
4
4
|
import { t as nonEmpty } from "./connection-D3XsOE3S.js";
|
|
5
5
|
import { c as setDryRun, o as isDryRun, s as resolveDryRun } from "./options-BTjOf5KP.js";
|
|
@@ -322,7 +322,7 @@ async function launchWith(argv, options) {
|
|
|
322
322
|
*/
|
|
323
323
|
async function launch(argv) {
|
|
324
324
|
await launchWith(argv, { dispatch: async (args) => {
|
|
325
|
-
const { main } = await import("./cli-
|
|
325
|
+
const { main } = await import("./cli-B2S6gw9o.js");
|
|
326
326
|
await main(args);
|
|
327
327
|
} });
|
|
328
328
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devdogsuga/backstage",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Officer and production CLI for DevDogsUGA: deploys, env sync with Bitwarden and GitHub, the migration planner role, club graphics and QR codes, GitHub rulesets and settings, and the newsletter. Ships built JS; run it anywhere with `pnpm dlx @devdogsuga/backstage` (no checkout needed to start; commands that read a checkout say so).",
|
|
@@ -40,10 +40,10 @@
|
|
|
40
40
|
"tsx": "^4.23.12",
|
|
41
41
|
"typescript": "^6.0.3",
|
|
42
42
|
"zod": "4.4.3",
|
|
43
|
-
"@devdogsuga/telemetry": "0.1.3",
|
|
44
|
-
"@devdogsuga/brand": "0.1.5",
|
|
45
43
|
"@devdogsuga/events": "0.1.5",
|
|
46
|
-
"@devdogsuga/newsletter": "0.1.
|
|
44
|
+
"@devdogsuga/newsletter": "0.1.10",
|
|
45
|
+
"@devdogsuga/brand": "0.1.5",
|
|
46
|
+
"@devdogsuga/telemetry": "0.1.3"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"@devdogsuga/db": "*",
|
|
@@ -65,8 +65,8 @@
|
|
|
65
65
|
"tsdown": "^0.23.0",
|
|
66
66
|
"vitest": "^4.1.11",
|
|
67
67
|
"@devdogsuga/cli-core": "0.0.0",
|
|
68
|
-
"@devdogsuga/db": "0.1.3",
|
|
69
68
|
"@devdogsuga/config": "0.1.2",
|
|
69
|
+
"@devdogsuga/db": "0.1.3",
|
|
70
70
|
"@devdogsuga/env": "0.1.5"
|
|
71
71
|
},
|
|
72
72
|
"scripts": {
|