@devdogsuga/devtools 0.1.26 → 0.1.28
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 +72 -11
- package/bin/devtools.mjs +4 -4
- package/dist/cli-CZKkNHK5.js +6619 -0
- package/dist/failure-log-BBPGejQv.js +256 -0
- package/dist/launch.js +267 -281
- package/dist/local-env-D8HC2JK_.js +351 -0
- package/dist/local-env-DrBCXqD8.js +2 -0
- package/dist/menu-CQBsQRgH.js +1684 -0
- package/dist/peer-redirect-hooks.js +15 -0
- package/dist/peers-RBplwovA.js +229 -0
- package/dist/root-C2OmZDwD.js +94 -0
- package/dist/stack-Bx-55oi_.js +2 -0
- package/dist/stack-BynCgRVS.js +181 -0
- package/dist/supabase-project-0knM0mqd.js +426 -0
- package/dist/telemetry-C4foD8MD.js +249 -0
- package/dist/telemetry.js +2 -148
- package/package.json +10 -29
- package/bin/devtools-ci-bare.mjs +0 -48
- package/bin/devtools-ci.mjs +0 -31
- package/dist/args.d.ts +0 -26
- package/dist/args.js +0 -78
- package/dist/bws/bw.d.ts +0 -18
- package/dist/bws/bw.js +0 -70
- package/dist/bws/client.d.ts +0 -43
- package/dist/bws/client.js +0 -363
- package/dist/bws/environments.d.ts +0 -96
- package/dist/bws/environments.js +0 -111
- package/dist/bws/pace.d.ts +0 -25
- package/dist/bws/pace.js +0 -43
- package/dist/bws/retry.d.ts +0 -12
- package/dist/bws/retry.js +0 -39
- package/dist/bws/store.d.ts +0 -1
- package/dist/bws/store.js +0 -32
- package/dist/bws/token.d.ts +0 -31
- package/dist/bws/token.js +0 -88
- package/dist/bws/vault.d.ts +0 -29
- package/dist/bws/vault.js +0 -200
- package/dist/catalog.d.ts +0 -57
- package/dist/catalog.js +0 -57
- package/dist/cf/build.d.ts +0 -13
- package/dist/cf/build.js +0 -65
- package/dist/cf/commands.d.ts +0 -1
- package/dist/cf/commands.js +0 -172
- package/dist/cf/local-env.d.ts +0 -58
- package/dist/cf/local-env.js +0 -177
- package/dist/ci.d.ts +0 -1
- package/dist/ci.js +0 -328
- package/dist/cli.d.ts +0 -11
- package/dist/cli.js +0 -1094
- package/dist/commands.d.ts +0 -261
- package/dist/commands.js +0 -1318
- package/dist/completions.d.ts +0 -4
- package/dist/completions.js +0 -110
- package/dist/cron/commands.d.ts +0 -47
- package/dist/cron/commands.js +0 -372
- package/dist/cron/discovery.d.ts +0 -55
- package/dist/cron/discovery.js +0 -85
- package/dist/cron/schema.d.ts +0 -45
- package/dist/cron/schema.js +0 -35
- package/dist/db/config-push.d.ts +0 -8
- package/dist/db/config-push.js +0 -11
- package/dist/db/connection.d.ts +0 -79
- package/dist/db/connection.js +0 -114
- package/dist/db/exec.d.ts +0 -1
- package/dist/db/exec.js +0 -11
- package/dist/db/generate-types.d.ts +0 -1
- package/dist/db/generate-types.js +0 -4
- package/dist/db/generated-env.d.ts +0 -69
- package/dist/db/generated-env.js +0 -113
- package/dist/db/introspect.d.ts +0 -1
- package/dist/db/introspect.js +0 -122
- package/dist/db/local-env.d.ts +0 -65
- package/dist/db/local-env.js +0 -23
- package/dist/db/new-migration.d.ts +0 -8
- package/dist/db/new-migration.js +0 -69
- package/dist/db/pooler.d.ts +0 -23
- package/dist/db/pooler.js +0 -55
- package/dist/db/run.d.ts +0 -68
- package/dist/db/run.js +0 -156
- package/dist/db/seed-buckets.d.ts +0 -2
- package/dist/db/seed-buckets.js +0 -4
- package/dist/db/seed-production.d.ts +0 -8
- package/dist/db/seed-production.js +0 -79
- package/dist/db/seed-roles.d.ts +0 -7
- package/dist/db/seed-roles.js +0 -33
- package/dist/db/session-refresh.d.ts +0 -43
- package/dist/db/session-refresh.js +0 -40
- package/dist/deploy/migrations.d.ts +0 -20
- package/dist/deploy/migrations.js +0 -68
- package/dist/deploy/orphans.d.ts +0 -20
- package/dist/deploy/orphans.js +0 -177
- package/dist/deploy/preflight.d.ts +0 -53
- package/dist/deploy/preflight.js +0 -189
- package/dist/deploy/report.d.ts +0 -26
- package/dist/deploy/report.js +0 -70
- package/dist/deploy/require-planner.d.ts +0 -2
- package/dist/deploy/require-planner.js +0 -60
- package/dist/deploy/require-token.d.ts +0 -15
- package/dist/deploy/require-token.js +0 -78
- package/dist/deploy/secrets-file.d.ts +0 -17
- package/dist/deploy/secrets-file.js +0 -166
- package/dist/deploy/write-env.d.ts +0 -40
- package/dist/deploy/write-env.js +0 -395
- package/dist/docs/index-pages.d.ts +0 -38
- package/dist/docs/index-pages.js +0 -186
- package/dist/emails/commands.d.ts +0 -15
- package/dist/emails/commands.js +0 -130
- package/dist/emails/email-types.d.ts +0 -13
- package/dist/emails/email-types.js +0 -1
- package/dist/emails/fixtures.d.ts +0 -20
- package/dist/emails/fixtures.js +0 -20
- package/dist/env/audit.d.ts +0 -206
- package/dist/env/audit.js +0 -436
- package/dist/env/cloudflare.d.ts +0 -21
- package/dist/env/cloudflare.js +0 -61
- package/dist/env/commands.d.ts +0 -99
- package/dist/env/commands.js +0 -613
- package/dist/env/discovery.d.ts +0 -15
- package/dist/env/discovery.js +0 -239
- package/dist/env/document.d.ts +0 -119
- package/dist/env/document.js +0 -323
- package/dist/env/example.d.ts +0 -68
- package/dist/env/example.js +0 -605
- package/dist/env/selection.d.ts +0 -105
- package/dist/env/selection.js +0 -228
- package/dist/env-entry.d.ts +0 -49
- package/dist/env-entry.js +0 -204
- package/dist/environment-doctor.d.ts +0 -45
- package/dist/environment-doctor.js +0 -429
- package/dist/environment.d.ts +0 -92
- package/dist/environment.js +0 -185
- package/dist/fingerprint.d.ts +0 -10
- package/dist/fingerprint.js +0 -18
- package/dist/gen/campus-map.d.ts +0 -1
- package/dist/gen/campus-map.js +0 -473
- package/dist/gen/commands.d.ts +0 -1
- package/dist/gen/commands.js +0 -25
- package/dist/gen/hypno.d.ts +0 -1
- package/dist/gen/hypno.js +0 -134
- package/dist/gh/client.d.ts +0 -80
- package/dist/gh/client.js +0 -259
- package/dist/gh/environments.d.ts +0 -83
- package/dist/gh/environments.js +0 -178
- package/dist/gh/rulesets/actors.d.ts +0 -14
- package/dist/gh/rulesets/actors.js +0 -69
- package/dist/gh/rulesets/api.d.ts +0 -15
- package/dist/gh/rulesets/api.js +0 -104
- package/dist/gh/rulesets/commands.d.ts +0 -3
- package/dist/gh/rulesets/commands.js +0 -203
- package/dist/gh/rulesets/desired.d.ts +0 -112
- package/dist/gh/rulesets/desired.js +0 -271
- package/dist/gh/rulesets/diff.d.ts +0 -65
- package/dist/gh/rulesets/diff.js +0 -170
- package/dist/gh/rulesets/types.d.ts +0 -76
- package/dist/gh/rulesets/types.js +0 -13
- package/dist/gh/settings/api.d.ts +0 -40
- package/dist/gh/settings/api.js +0 -180
- package/dist/gh/settings/commands.d.ts +0 -1
- package/dist/gh/settings/commands.js +0 -254
- package/dist/gh/settings/desired.d.ts +0 -53
- package/dist/gh/settings/desired.js +0 -43
- package/dist/gh/settings/diff.d.ts +0 -57
- package/dist/gh/settings/diff.js +0 -161
- package/dist/gh/settings/types.d.ts +0 -92
- package/dist/gh/settings/types.js +0 -11
- package/dist/gh/settings/workflows.d.ts +0 -41
- package/dist/gh/settings/workflows.js +0 -128
- package/dist/grantRoot.d.ts +0 -42
- package/dist/grantRoot.js +0 -89
- package/dist/help.d.ts +0 -18
- package/dist/help.js +0 -169
- package/dist/images/commands.d.ts +0 -32
- package/dist/images/commands.js +0 -231
- package/dist/images/events.d.ts +0 -47
- package/dist/images/events.js +0 -116
- package/dist/images/graphics.d.ts +0 -70
- package/dist/images/graphics.js +0 -234
- package/dist/images/open-graph-types.d.ts +0 -75
- package/dist/images/open-graph-types.js +0 -1
- package/dist/images/prompts.d.ts +0 -34
- package/dist/images/prompts.js +0 -100
- package/dist/images/render.d.ts +0 -21
- package/dist/images/render.js +0 -61
- package/dist/images/select.d.ts +0 -64
- package/dist/images/select.js +0 -96
- package/dist/instance.d.ts +0 -69
- package/dist/instance.js +0 -102
- package/dist/invocation.d.ts +0 -49
- package/dist/invocation.js +0 -78
- package/dist/launch-ci.d.ts +0 -1
- package/dist/launch-ci.js +0 -90
- package/dist/launch.d.ts +0 -18
- package/dist/menu.d.ts +0 -43
- package/dist/menu.js +0 -300
- package/dist/moderation.d.ts +0 -70
- package/dist/moderation.js +0 -128
- package/dist/oauth/browser.d.ts +0 -1
- package/dist/oauth/browser.js +0 -13
- package/dist/oauth/config.d.ts +0 -24
- package/dist/oauth/config.js +0 -24
- package/dist/oauth/connect-url.d.ts +0 -17
- package/dist/oauth/connect-url.js +0 -23
- package/dist/oauth/db.d.ts +0 -37
- package/dist/oauth/db.js +0 -108
- package/dist/oauth/device.d.ts +0 -93
- package/dist/oauth/device.js +0 -198
- package/dist/oauth/discovery.d.ts +0 -28
- package/dist/oauth/discovery.js +0 -54
- package/dist/oauth/env-file.d.ts +0 -6
- package/dist/oauth/env-file.js +0 -35
- package/dist/oauth/exchange.d.ts +0 -43
- package/dist/oauth/exchange.js +0 -93
- package/dist/oauth/label.d.ts +0 -1
- package/dist/oauth/label.js +0 -25
- package/dist/oauth/loopback.d.ts +0 -52
- package/dist/oauth/loopback.js +0 -168
- package/dist/oauth/pkce.d.ts +0 -6
- package/dist/oauth/pkce.js +0 -34
- package/dist/oauth/target.d.ts +0 -54
- package/dist/oauth/target.js +0 -102
- package/dist/oauth/transport.d.ts +0 -41
- package/dist/oauth/transport.js +0 -32
- package/dist/oauth/wizard.d.ts +0 -40
- package/dist/oauth/wizard.js +0 -578
- package/dist/persona.d.ts +0 -18
- package/dist/persona.js +0 -221
- package/dist/pick.d.ts +0 -6
- package/dist/pick.js +0 -64
- package/dist/pipes.d.ts +0 -1
- package/dist/pipes.js +0 -25
- package/dist/planner/checks.d.ts +0 -26
- package/dist/planner/checks.js +0 -104
- package/dist/planner/commands.d.ts +0 -10
- package/dist/planner/commands.js +0 -367
- package/dist/planner/db.d.ts +0 -15
- package/dist/planner/db.js +0 -33
- package/dist/planner/role.d.ts +0 -33
- package/dist/planner/role.js +0 -68
- package/dist/repo/peer-redirect-hooks.d.ts +0 -16
- package/dist/repo/peer-redirect-hooks.js +0 -10
- package/dist/repo/peer-redirect.d.ts +0 -4
- package/dist/repo/peer-redirect.js +0 -26
- package/dist/repo/peers.d.ts +0 -39
- package/dist/repo/peers.js +0 -139
- package/dist/repo/resolve.d.ts +0 -41
- package/dist/repo/resolve.js +0 -152
- package/dist/repo/root.d.ts +0 -23
- package/dist/repo/root.js +0 -91
- package/dist/repo/source.d.ts +0 -14
- package/dist/repo/source.js +0 -54
- package/dist/repo/supabase-project.d.ts +0 -60
- package/dist/repo/supabase-project.js +0 -124
- package/dist/repo/tsx-loader.d.ts +0 -6
- package/dist/repo/tsx-loader.js +0 -41
- package/dist/run/pick.d.ts +0 -90
- package/dist/run/pick.js +0 -664
- package/dist/setup.d.ts +0 -1
- package/dist/setup.js +0 -280
- package/dist/stack.d.ts +0 -48
- package/dist/stack.js +0 -403
- package/dist/telemetry.d.ts +0 -59
- package/dist/tier.d.ts +0 -40
- package/dist/tier.js +0 -96
- package/dist/ui.d.ts +0 -40
- package/dist/ui.js +0 -71
- package/dist/version.d.ts +0 -7
- package/dist/version.js +0 -17
- package/dist/workers.d.ts +0 -5
- package/dist/workers.js +0 -33
- package/dist/workflows/commands.d.ts +0 -54
- package/dist/workflows/commands.js +0 -763
package/dist/emails/commands.js
DELETED
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
/** `pnpm devtools emails [template…] [--format html,text] [--out dir]`. */
|
|
2
|
-
import { mkdir, writeFile } from "node:fs/promises";
|
|
3
|
-
import { homedir } from "node:os";
|
|
4
|
-
import { dirname, resolve } from "node:path";
|
|
5
|
-
import { isTTY, log, multiselect, note, text as askText } from "@clack/prompts";
|
|
6
|
-
import { positionals } from "../args.js";
|
|
7
|
-
import { explain, explainError, unwrap, UsageError } from "../ui.js";
|
|
8
|
-
import { EMAIL_FIXTURES } from "./fixtures.js";
|
|
9
|
-
import { loadEmail } from "../repo/source.js";
|
|
10
|
-
export const EMAIL_FORMATS = ["html", "text"];
|
|
11
|
-
export const EMAIL_NAMES = Object.keys(EMAIL_FIXTURES);
|
|
12
|
-
function flagValue(argv, flag) {
|
|
13
|
-
const index = argv.indexOf(flag);
|
|
14
|
-
if (index === -1)
|
|
15
|
-
return undefined;
|
|
16
|
-
const value = argv[index + 1];
|
|
17
|
-
return value && !value.startsWith("--") ? value : undefined;
|
|
18
|
-
}
|
|
19
|
-
function expandHome(value) {
|
|
20
|
-
return value === "~" || value.startsWith("~/")
|
|
21
|
-
? resolve(homedir(), value.slice(2))
|
|
22
|
-
: value;
|
|
23
|
-
}
|
|
24
|
-
export function parseEmailArgs(argv, cwd) {
|
|
25
|
-
const requested = positionals(argv);
|
|
26
|
-
const unknown = requested.filter((name) => name !== "*" && !EMAIL_NAMES.includes(name));
|
|
27
|
-
if (unknown.length) {
|
|
28
|
-
return new Error(`No email template called ${unknown.join(", ")}. Try ${EMAIL_NAMES.join(", ")}, or *.`);
|
|
29
|
-
}
|
|
30
|
-
const rawFormats = (flagValue(argv, "--format") ?? "html")
|
|
31
|
-
.split(",")
|
|
32
|
-
.map((value) => value.trim())
|
|
33
|
-
.filter(Boolean);
|
|
34
|
-
const badFormats = rawFormats.filter((value) => !EMAIL_FORMATS.includes(value));
|
|
35
|
-
if (badFormats.length)
|
|
36
|
-
return new Error(`Unknown format ${badFormats.join(", ")}. Try html or text.`);
|
|
37
|
-
const names = requested.includes("*")
|
|
38
|
-
? [...EMAIL_NAMES]
|
|
39
|
-
: requested;
|
|
40
|
-
return {
|
|
41
|
-
names,
|
|
42
|
-
formats: [...new Set(rawFormats)],
|
|
43
|
-
out: resolve(cwd, expandHome(flagValue(argv, "--out") ?? "email-previews")),
|
|
44
|
-
noOutput: argv.includes("--dry-run") || argv.includes("--no-output"),
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
async function interactive(options) {
|
|
48
|
-
if (options.names.length)
|
|
49
|
-
return options;
|
|
50
|
-
if (!isTTY(process.stdout)) {
|
|
51
|
-
throw new UsageError("No terminal to choose templates. Name one, or pass * for all.");
|
|
52
|
-
}
|
|
53
|
-
const names = unwrap(await multiselect({
|
|
54
|
-
message: "Which emails?",
|
|
55
|
-
options: EMAIL_NAMES.map((name) => ({ value: name, label: name })),
|
|
56
|
-
initialValues: [...EMAIL_NAMES],
|
|
57
|
-
required: true,
|
|
58
|
-
}));
|
|
59
|
-
const formats = unwrap(await multiselect({
|
|
60
|
-
message: "Which formats?",
|
|
61
|
-
options: [
|
|
62
|
-
{ value: "html", label: "HTML", hint: "open in a browser" },
|
|
63
|
-
{ value: "text", label: "Plain text", hint: "the email alternative" },
|
|
64
|
-
],
|
|
65
|
-
initialValues: ["html"],
|
|
66
|
-
required: true,
|
|
67
|
-
}));
|
|
68
|
-
const entered = unwrap(await askText({
|
|
69
|
-
message: "Where should these go?",
|
|
70
|
-
placeholder: "./email-previews",
|
|
71
|
-
defaultValue: "./email-previews",
|
|
72
|
-
})).trim();
|
|
73
|
-
return {
|
|
74
|
-
...options,
|
|
75
|
-
names,
|
|
76
|
-
formats,
|
|
77
|
-
out: resolve(process.cwd(), expandHome(entered || "email-previews")),
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
export function destination(out, name, format) {
|
|
81
|
-
return resolve(out, `${name}.${format === "text" ? "txt" : "html"}`);
|
|
82
|
-
}
|
|
83
|
-
export async function generateEmails(options) {
|
|
84
|
-
// Dynamic so every unrelated devtools command can still run before the
|
|
85
|
-
// generated email package has been built on a fresh checkout.
|
|
86
|
-
const { render } = await loadEmail();
|
|
87
|
-
const written = [];
|
|
88
|
-
for (const name of options.names) {
|
|
89
|
-
const email = render(name, EMAIL_FIXTURES[name]);
|
|
90
|
-
for (const format of options.formats) {
|
|
91
|
-
const file = destination(options.out, name, format);
|
|
92
|
-
await mkdir(dirname(file), { recursive: true });
|
|
93
|
-
await writeFile(file, format === "html" ? email.html : email.text);
|
|
94
|
-
written.push(file);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
return written;
|
|
98
|
-
}
|
|
99
|
-
export async function runEmails(argv) {
|
|
100
|
-
const parsed = parseEmailArgs(argv, process.cwd());
|
|
101
|
-
if (parsed instanceof Error) {
|
|
102
|
-
explain("Could not read that.", parsed.message, [
|
|
103
|
-
"pnpm devtools emails",
|
|
104
|
-
"pnpm devtools emails '*' --format html,text --out ~/emails",
|
|
105
|
-
]);
|
|
106
|
-
process.exitCode = 1;
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
try {
|
|
110
|
-
const options = await interactive(parsed);
|
|
111
|
-
if (options.noOutput) {
|
|
112
|
-
const { render } = await loadEmail();
|
|
113
|
-
note(options.names
|
|
114
|
-
.map((name) => `${name}\n ${render(name, EMAIL_FIXTURES[name]).subject}\n ${options.formats.map((f) => destination(options.out, name, f)).join("\n ")}`)
|
|
115
|
-
.join("\n"), `${options.names.length} email template${options.names.length === 1 ? "" : "s"}`);
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
const written = await generateEmails(options);
|
|
119
|
-
for (const file of written)
|
|
120
|
-
log.success(file);
|
|
121
|
-
log.info(`${written.length} preview file${written.length === 1 ? "" : "s"} written.`);
|
|
122
|
-
}
|
|
123
|
-
catch (err) {
|
|
124
|
-
explainError("Could not render those emails.", err, [
|
|
125
|
-
"Build the email package with `pnpm --filter @devdogsuga/email build`.",
|
|
126
|
-
"Then try `pnpm devtools emails '*' --out ~/emails`.",
|
|
127
|
-
]);
|
|
128
|
-
process.exitCode = 1;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Type-only stand-in for `@devdogsuga/email`'s generated `Templates` map.
|
|
3
|
-
*
|
|
4
|
-
* `@devdogsuga/email` is `"private": true` and never published — it stays
|
|
5
|
-
* in DevDogsUGA and devtools resolves it FROM the repo at runtime
|
|
6
|
-
* (`repo/source.ts`'s `loadEmail()`). Backstage has no copy to pull the
|
|
7
|
-
* real generated type from, so `fixtures.ts`'s `satisfies` check is
|
|
8
|
-
* loosened to "every template's fixture is a flat string-prop object"
|
|
9
|
-
* instead of the real per-template exact prop shape. A prop typo here is
|
|
10
|
-
* caught at runtime (the real `render()` throws on a missing required
|
|
11
|
-
* prop), not at Backstage's typecheck time.
|
|
12
|
-
*/
|
|
13
|
-
export type EmailTemplates = Record<string, Record<string, string>>;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Credible, non-sensitive values for local previews.
|
|
3
|
-
*
|
|
4
|
-
* `satisfies` is the maintenance mechanism: a new template or prop cannot be
|
|
5
|
-
* shipped without deciding what its preview should say.
|
|
6
|
-
*/
|
|
7
|
-
export declare const EMAIL_FIXTURES: {
|
|
8
|
-
JoinRequest: {
|
|
9
|
-
leadName: string;
|
|
10
|
-
applicantName: string;
|
|
11
|
-
teamName: string;
|
|
12
|
-
reviewUrl: string;
|
|
13
|
-
};
|
|
14
|
-
TeamInvite: {
|
|
15
|
-
inviteeName: string;
|
|
16
|
-
teamName: string;
|
|
17
|
-
leadName: string;
|
|
18
|
-
acceptUrl: string;
|
|
19
|
-
};
|
|
20
|
-
};
|
package/dist/emails/fixtures.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Credible, non-sensitive values for local previews.
|
|
3
|
-
*
|
|
4
|
-
* `satisfies` is the maintenance mechanism: a new template or prop cannot be
|
|
5
|
-
* shipped without deciding what its preview should say.
|
|
6
|
-
*/
|
|
7
|
-
export const EMAIL_FIXTURES = {
|
|
8
|
-
JoinRequest: {
|
|
9
|
-
leadName: "Jordan",
|
|
10
|
-
applicantName: "Avery",
|
|
11
|
-
teamName: "Byte Bulldogs",
|
|
12
|
-
reviewUrl: "https://devdogsuga.org/teams/requests",
|
|
13
|
-
},
|
|
14
|
-
TeamInvite: {
|
|
15
|
-
inviteeName: "Avery",
|
|
16
|
-
teamName: "Byte Bulldogs",
|
|
17
|
-
leadName: "Jordan",
|
|
18
|
-
acceptUrl: "https://devdogsuga.org/teams/requests",
|
|
19
|
-
},
|
|
20
|
-
};
|
package/dist/env/audit.d.ts
DELETED
|
@@ -1,206 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Four-way drift detection: local `.env`, Bitwarden, GitHub, Cloudflare.
|
|
3
|
-
*
|
|
4
|
-
* Each store answers a different question, and only one of them answers it
|
|
5
|
-
* completely:
|
|
6
|
-
*
|
|
7
|
-
* | Store | Exposes | So it can be checked for |
|
|
8
|
-
* |--------------------|-------------------|--------------------------|
|
|
9
|
-
* | local .env | names AND values | value drift |
|
|
10
|
-
* | Bitwarden | names AND values | value drift (the truth) |
|
|
11
|
-
* | GitHub *secrets* | names + updatedAt | presence, staleness |
|
|
12
|
-
* | GitHub *variables* | names AND values | value drift |
|
|
13
|
-
* | Cloudflare | names only | presence, orphans |
|
|
14
|
-
*
|
|
15
|
-
* That asymmetry is the whole design. A GitHub *secret* is write-only, so a
|
|
16
|
-
* clean audit of one does not mean "the values match". It means "nothing
|
|
17
|
-
* detectable is wrong", and the report says which is which rather than implying
|
|
18
|
-
* the stronger claim.
|
|
19
|
-
*
|
|
20
|
-
* Timestamps are what rescue that row from being presence-only. Bitwarden
|
|
21
|
-
* reports a `revisionDate` per secret and `gh secret list` reports `updatedAt`,
|
|
22
|
-
* so "was GitHub updated after Bitwarden last changed?" IS answerable. That is
|
|
23
|
-
* the failure this design actually has: a credential rotated in Bitwarden and
|
|
24
|
-
* never propagated, which a name-only check calls healthy right up until the old
|
|
25
|
-
* one is revoked.
|
|
26
|
-
*
|
|
27
|
-
* ⚠️ GitHub *variables* are the one downstream store that needs none of that
|
|
28
|
-
* reasoning: `gh variable list` returns the value, so the public per-environment
|
|
29
|
-
* keys are compared exactly the way the local file is. Staleness is deliberately
|
|
30
|
-
* NOT applied to them: a timestamp is a proxy for a comparison that could not
|
|
31
|
-
* be made, and using the proxy where the real answer is available would report a
|
|
32
|
-
* variable re-pushed with an identical value as drift. The security plan's §3.6
|
|
33
|
-
* limitation ("names only… a changed value is undetectable") now holds for the
|
|
34
|
-
* secret row alone.
|
|
35
|
-
*
|
|
36
|
-
* ⚠️ One scope sits outside that table altogether: the repository's OWN
|
|
37
|
-
* variables. Push writes environment-scoped values only, and an environment
|
|
38
|
-
* variable SHADOWS a repository one of the same name, so a repository-level
|
|
39
|
-
* copy of a managed key is read by nothing, drifts forever, and becomes the
|
|
40
|
-
* live value on the day somebody deletes the environment copy. It is checked
|
|
41
|
-
* here for the same reason §3.6's orphans are: nothing manages it, so nothing
|
|
42
|
-
* else in this system would ever mention it.
|
|
43
|
-
*/
|
|
44
|
-
export type Severity = "error" | "warning" | "info";
|
|
45
|
-
export interface Finding {
|
|
46
|
-
key: string;
|
|
47
|
-
severity: Severity;
|
|
48
|
-
/** Where the problem is, for grouping. */
|
|
49
|
-
store: "local" | "github" | "cloudflare";
|
|
50
|
-
summary: string;
|
|
51
|
-
}
|
|
52
|
-
export interface BwsEntry {
|
|
53
|
-
value: string;
|
|
54
|
-
/** ISO 8601. Absent when the CLI did not report one. */
|
|
55
|
-
revisionDate?: string;
|
|
56
|
-
}
|
|
57
|
-
export interface GithubEntry {
|
|
58
|
-
/** Which GitHub environment this copy sits in. */
|
|
59
|
-
environment: string;
|
|
60
|
-
name: string;
|
|
61
|
-
/** ISO 8601. */
|
|
62
|
-
updatedAt?: string;
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* A GitHub environment *variable*: the same shape plus the thing that makes
|
|
66
|
-
* variables worth having, a readable value.
|
|
67
|
-
*/
|
|
68
|
-
export interface GithubVariableEntry extends GithubEntry {
|
|
69
|
-
value: string;
|
|
70
|
-
}
|
|
71
|
-
export interface AuditInput {
|
|
72
|
-
/** Active assignments in the local `.env`. */
|
|
73
|
-
local: Map<string, string>;
|
|
74
|
-
/** Keys present in the local `.env` but commented out. */
|
|
75
|
-
localCommented?: Set<string>;
|
|
76
|
-
/** The source of truth. */
|
|
77
|
-
bws: Map<string, BwsEntry>;
|
|
78
|
-
/**
|
|
79
|
-
* Every GitHub copy found, across every environment this project feeds.
|
|
80
|
-
*
|
|
81
|
-
* A list rather than a map keyed by name, because one Bitwarden project can
|
|
82
|
-
* feed two GitHub environments and the interesting case is a key appearing in
|
|
83
|
-
* BOTH, which a name-keyed map would quietly collapse to one.
|
|
84
|
-
*/
|
|
85
|
-
github: GithubEntry[];
|
|
86
|
-
/**
|
|
87
|
-
* Every GitHub environment *variable* found, across the same environments.
|
|
88
|
-
*
|
|
89
|
-
* Separate from `github` rather than merged with a discriminator, because
|
|
90
|
-
* GitHub genuinely allows one name to exist as both a secret and a variable
|
|
91
|
-
* in one environment and resolves the ambiguity by never telling you. See
|
|
92
|
-
* `deploy/write-env.ts`, which refuses that case outright. Two lists can
|
|
93
|
-
* represent it; one list keyed by name cannot, and would silently pick a
|
|
94
|
-
* winner.
|
|
95
|
-
*/
|
|
96
|
-
githubVariables?: GithubVariableEntry[];
|
|
97
|
-
/**
|
|
98
|
-
* Keys that belong in the variable store rather than the secret store, from
|
|
99
|
-
* `variableKeys()` in the registry.
|
|
100
|
-
*
|
|
101
|
-
* Drives two things at once: which store a key is compared against, and the
|
|
102
|
-
* pair of misplacement errors. Absent, every key is treated as a secret,
|
|
103
|
-
* which is the pre-variables behaviour.
|
|
104
|
-
*/
|
|
105
|
-
variables?: ReadonlySet<string>;
|
|
106
|
-
/**
|
|
107
|
-
* Where a key is supposed to live: the PRIMARY environment, the one whose
|
|
108
|
-
* absence is an error. `null` means "nowhere in this environment", which is
|
|
109
|
-
* ordinary rather than wrong.
|
|
110
|
-
*/
|
|
111
|
-
route: (key: string) => string | null;
|
|
112
|
-
/**
|
|
113
|
-
* Whether a copy found in some OTHER environment is legitimate.
|
|
114
|
-
*
|
|
115
|
-
* Separate from `route` because the two questions stopped having the same
|
|
116
|
-
* answer when `production-apply` became a superset of `production`: an
|
|
117
|
-
* ordinary production key is now pushed to both, so "not where `route` says"
|
|
118
|
-
* no longer means "misplaced". Folding them back together reports every
|
|
119
|
-
* correctly-pushed copy as a stray to delete, and a reviewer who deletes 46
|
|
120
|
-
* of those learns to skim the stray finding, which is the one finding that
|
|
121
|
-
* catches an apply-tier credential sitting in the unreviewed environment.
|
|
122
|
-
*
|
|
123
|
-
* Defaults to the old behaviour (`only where route says`), so a caller that
|
|
124
|
-
* has not thought about fan-out gets the strict answer rather than a
|
|
125
|
-
* permissive one.
|
|
126
|
-
*/
|
|
127
|
-
accepted?: (key: string, environment: string) => boolean;
|
|
128
|
-
/** Worker name → secret names on it. Values are unreadable. */
|
|
129
|
-
cloudflare?: Map<string, Set<string>>;
|
|
130
|
-
/** Keys that legitimately live outside Bitwarden: the non-secrets. */
|
|
131
|
-
ignore?: ReadonlySet<string>;
|
|
132
|
-
/**
|
|
133
|
-
* Credentials that must never be stored remotely at all.
|
|
134
|
-
*
|
|
135
|
-
* Distinct from `ignore`, and the opposite of it: an ignored key is expected
|
|
136
|
-
* somewhere else, whereas one of these appearing in ANY remote store is a
|
|
137
|
-
* finding. Being in the local `.env` and nowhere else is the correct state,
|
|
138
|
-
* so the ordinary "not in Bitwarden" warning must not fire for them.
|
|
139
|
-
*/
|
|
140
|
-
neverStore?: ReadonlySet<string>;
|
|
141
|
-
/**
|
|
142
|
-
* Credentials signed at deploy time, whose only copy is on the deploy target.
|
|
143
|
-
*
|
|
144
|
-
* The third category, and it sits between the other two rather than beside
|
|
145
|
-
* them: unlike `ignore` it is a secret, and unlike `neverStore` there is one
|
|
146
|
-
* remote store it BELONGS in. A key like this is signed at deploy time and
|
|
147
|
-
* written straight to the Worker, so being on Cloudflare and nowhere else is
|
|
148
|
-
* exactly right. `SANDBOX_PROXY_TOKEN` is still declared this way in
|
|
149
|
-
* `apps/sandbox/env.ts` — nothing mints it any more, since the deploy that
|
|
150
|
-
* did was removed with the sandbox integration it authenticated, but the
|
|
151
|
-
* declaration is what keeps this category from reading "on production-
|
|
152
|
-
* sandbox, not in Bitwarden" the day someone does fill it in by hand.
|
|
153
|
-
*
|
|
154
|
-
* Without this set the Cloudflare pass below reports a key like that as an
|
|
155
|
-
* orphan, which the plan doc's §3.6 prune path then offers to delete.
|
|
156
|
-
* Marking it the other obvious way, as `never-store`, inverts the error into
|
|
157
|
-
* "must NEVER be a Worker secret" and is just as wrong in the opposite
|
|
158
|
-
* direction.
|
|
159
|
-
*/
|
|
160
|
-
minted?: ReadonlySet<string>;
|
|
161
|
-
/**
|
|
162
|
-
* Every key the registry knows. When provided, a local key outside it is
|
|
163
|
-
* reported as UNDECLARED: its own category, not folded into drift, because
|
|
164
|
-
* the fix is different: drift wants a push or a pull, an undeclared key
|
|
165
|
-
* wants a `define()` in the owning manifest (or the line removed). It is
|
|
166
|
-
* also why `env push` skipped it, and the audit should say so rather
|
|
167
|
-
* than let "not in Bitwarden" imply pushing would help.
|
|
168
|
-
*/
|
|
169
|
-
declared?: ReadonlySet<string>;
|
|
170
|
-
/**
|
|
171
|
-
* The repository's OWN variables, the scope with no environment, or the fact
|
|
172
|
-
* that they could not be listed.
|
|
173
|
-
*
|
|
174
|
-
* A union rather than a list, because three states have to stay apart and a
|
|
175
|
-
* list can only hold two of them: nobody looked (absent: the pre-existing
|
|
176
|
-
* behaviour, no claim either way), looked and saw these names
|
|
177
|
-
* (`readable`), and TRIED TO LOOK AND COULD NOT (`readable: false`). Listing
|
|
178
|
-
* repository variables can fail where listing environment ones succeeds, so
|
|
179
|
-
* the third state is ordinary rather than exotic, and collapsing it into an
|
|
180
|
-
* empty list is precisely the bug this check was added to catch, one scope
|
|
181
|
-
* up: a report that says "checked, nothing found" about a check that never
|
|
182
|
-
* ran.
|
|
183
|
-
*
|
|
184
|
-
* Names only. See `GhRepositoryVariable` for why the value is deliberately
|
|
185
|
-
* not fetched.
|
|
186
|
-
*/
|
|
187
|
-
repositoryVariables?: RepositoryVariableScan;
|
|
188
|
-
}
|
|
189
|
-
/**
|
|
190
|
-
* What `gh variable list` (no `--env`) returned, or why it returned nothing.
|
|
191
|
-
*
|
|
192
|
-
* `reason` is carried rather than dropped because the two failures need
|
|
193
|
-
* different next steps and look identical from a finding that omits it: a
|
|
194
|
-
* missing permission is fixed by an admin, an unauthenticated CLI by the person
|
|
195
|
-
* reading the report.
|
|
196
|
-
*/
|
|
197
|
-
export type RepositoryVariableScan = {
|
|
198
|
-
readable: true;
|
|
199
|
-
names: readonly string[];
|
|
200
|
-
} | {
|
|
201
|
-
readable: false;
|
|
202
|
-
reason: string;
|
|
203
|
-
};
|
|
204
|
-
export declare function audit(input: AuditInput): Finding[];
|
|
205
|
-
export declare function hasErrors(findings: Finding[]): boolean;
|
|
206
|
-
export declare function renderFindings(findings: Finding[]): string;
|