authflow-cli 0.5.0 → 0.6.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.
@@ -0,0 +1,105 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { requireIssuer } from "../config.js";
3
+ import { login, logout } from "../login.js";
4
+ import { currentWorkspacePath, managementRequest, managementResourceActions, redactToolSecrets } from "../management.js";
5
+ import { secretDelivery, secretTargets } from "../secrets.js";
6
+ const print = (value) => { process.stdout.write(`${JSON.stringify(value, null, 2)}\n`); };
7
+ export function accountCommands(program) {
8
+ program.command("login").description("Sign in in the browser and store a workspace login in your OS credential store")
9
+ .option("--issuer <url>", "Authflow issuer (default: AUTHFLOW_ISSUER)")
10
+ .option("--workspace <id>", "Workspace to authorize; otherwise choose in the browser")
11
+ .option("--no-browser", "Print the login URL without opening a browser")
12
+ .action(async (options) => print(await login(requireIssuer(options.issuer), options.workspace, options.browser !== false)));
13
+ program.command("logout").description("Revoke and remove the saved Authflow login")
14
+ .option("--issuer <url>", "Authflow issuer")
15
+ .option("--local-only", "Clear this device only; server authorization is not revoked")
16
+ .action(async (options) => { await logout(requireIssuer(options.issuer), { localOnly: options.localOnly }); print({ signed_out: true, authorization_revoked: !options.localOnly }); });
17
+ const workspace = program.command("workspace").description("Manage your verified workspace");
18
+ workspace.command("list").option("--issuer <url>").action(async (options) => print(await managementRequest(requireIssuer(options.issuer), "/workspaces")));
19
+ for (const operation of ["overview", "usage", "earnings"])
20
+ workspace.command(operation).option("--issuer <url>").option("--workspace <id>").action(async (options) => {
21
+ const issuer = requireIssuer(options.issuer);
22
+ print(await managementRequest(issuer, `${await currentWorkspacePath(issuer, options.workspace)}/${operation}`));
23
+ });
24
+ workspace.command("rename <name>").option("--issuer <url>").option("--workspace <id>").action(async (name, options) => {
25
+ const issuer = requireIssuer(options.issuer);
26
+ print(await managementRequest(issuer, await currentWorkspacePath(issuer, options.workspace), "PATCH", { name }));
27
+ });
28
+ const docs = program.command("docs").description("Search and read Authflow's indexed public documentation");
29
+ docs.command("search <query>").option("--issuer <url>").action(async (query, options) => {
30
+ print(await managementRequest(requireIssuer(options.issuer), "/docs/search", "GET", undefined, { q: query }));
31
+ });
32
+ docs.command("get <path>").option("--issuer <url>").action(async (path, options) => {
33
+ print(await managementRequest(requireIssuer(options.issuer), "/docs/page", "GET", undefined, { path }));
34
+ });
35
+ const resource = program.command("resource").description("Create, configure, verify, and explicitly publish an MCP");
36
+ for (const operation of ["list", "get", "create", "update", "origin", "domain", ...managementResourceActions, "rotate-key"]) {
37
+ const command = resource.command(operation.replace("/", "-"));
38
+ if (!["list", "create"].includes(operation))
39
+ command.argument("<slug>");
40
+ command.option("--issuer <url>").option("--workspace <id>");
41
+ if (["create", "update", "origin", "domain"].includes(operation))
42
+ command.requiredOption("--file <path>", "Resource input JSON");
43
+ if (["create", "rotate-key"].includes(operation))
44
+ command.option("--write-secrets <target>", secretTargets.join(" | ")).option("--secret-destination <value>", "Explicit project, env-file path, or vault for origin-reported usage");
45
+ command.action(async (...args) => {
46
+ const hasSlug = !["list", "create"].includes(operation);
47
+ const slug = hasSlug ? String(args[0]) : undefined;
48
+ const options = args[hasSlug ? 1 : 0];
49
+ const issuer = requireIssuer(options.issuer);
50
+ const workspacePath = await currentWorkspacePath(issuer, options.workspace);
51
+ const path = `${workspacePath}/resources${slug ? `/${encodeURIComponent(slug)}` : ""}`;
52
+ const body = options.file ? JSON.parse((await readFile(options.file, "utf8")).replace(/^\uFEFF/, "")) : undefined;
53
+ let prepared;
54
+ if (operation === "create" || operation === "rotate-key") {
55
+ // Resolve ownership and the actual metering policy before rotating or touching a destination.
56
+ const resource = operation === "rotate-key" ? await managementRequest(issuer, path) : body;
57
+ if (requiresOriginCredential(resource)) {
58
+ if (operation === "rotate-key" || options.writeSecrets || options.secretDestination) {
59
+ if (!options.writeSecrets || !secretTargets.includes(options.writeSecrets) || !options.secretDestination?.trim())
60
+ throw new Error("Choose both --write-secrets <target> and --secret-destination <destination>. The origin key is never printed.");
61
+ const resourceSlug = slug ?? resource.slug;
62
+ prepared = await secretDelivery.prepare({ target: options.writeSecrets, destination: options.secretDestination,
63
+ resource: { issuer, workspaceId: decodeURIComponent(workspacePath.split("/")[2]), slug: resourceSlug } });
64
+ }
65
+ }
66
+ else if (operation === "rotate-key") {
67
+ print({ result: redactToolSecrets(resource), origin_key_delivery: { status: "not_required" } });
68
+ return;
69
+ }
70
+ }
71
+ const method = ["get", "list"].includes(operation) ? "GET" : operation === "update" ? "PATCH" : "POST";
72
+ const suffix = ["get", "list", "create", "update"].includes(operation) ? "" : `/${operation}`;
73
+ const result = await managementRequest(issuer, path + suffix, method, body);
74
+ let storedAt;
75
+ if (prepared) {
76
+ if (!result || typeof result !== "object" || !("origin_api_key" in result) || typeof result.origin_api_key !== "string")
77
+ throw new Error("The resource operation completed without a deliverable origin key. Inspect the resource before explicitly requesting another rotation.");
78
+ try {
79
+ await prepared.write(result.origin_api_key);
80
+ storedAt = prepared.description;
81
+ }
82
+ catch {
83
+ throw new Error("The resource operation completed, but origin-key delivery failed. The previous key may already be revoked. Check the destination and explicitly run resource rotate-key when ready; no mutation was retried.");
84
+ }
85
+ }
86
+ print({ result: redactToolSecrets(result), ...(storedAt ? { origin_key_stored_at: storedAt, deployment_updated: false } : {}),
87
+ ...(operation === "create" && !storedAt ? { origin_key_delivery: { status: requiresOriginCredential(result) ? "required" : "not_required" } } : {}) });
88
+ });
89
+ }
90
+ const stripe = program.command("stripe").description("Inspect payout readiness or open signed-in Stripe setup");
91
+ for (const operation of ["status", "onboard", "connect-existing"]) {
92
+ stripe.command(operation).option("--issuer <url>").option("--workspace <id>").action(async (options) => {
93
+ const issuer = requireIssuer(options.issuer);
94
+ const path = `${await currentWorkspacePath(issuer, options.workspace)}/stripe`;
95
+ print(await managementRequest(issuer, operation === "status" ? path : `${path}/actions`, operation === "status" ? "GET" : "POST", operation === "status" ? undefined : { kind: operation === "onboard" ? "onboard" : "connect_existing" }));
96
+ });
97
+ }
98
+ }
99
+ function requiresOriginCredential(value) {
100
+ if (!value || typeof value !== "object")
101
+ return false;
102
+ const resource = value;
103
+ return resource.access_mode === "paid" && resource.metering_mode === "origin_reported";
104
+ }
105
+ //# sourceMappingURL=account.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account.js","sourceRoot":"","sources":["../../src/commands/account.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACzH,OAAO,EAAE,cAAc,EAAE,aAAa,EAAqD,MAAM,eAAe,CAAC;AAGjH,MAAM,KAAK,GAAG,CAAC,KAAc,EAAQ,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAEzG,MAAM,UAAU,eAAe,CAAC,OAAgB;IAC9C,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,gFAAgF,CAAC;SACnH,MAAM,CAAC,gBAAgB,EAAE,4CAA4C,CAAC;SACtE,MAAM,CAAC,kBAAkB,EAAE,yDAAyD,CAAC;SACrF,MAAM,CAAC,cAAc,EAAE,+CAA+C,CAAC;SACvE,MAAM,CAAC,KAAK,EAAE,OAAgB,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC;IACvI,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,4CAA4C,CAAC;SAChF,MAAM,CAAC,gBAAgB,EAAE,iBAAiB,CAAC;SAC3C,MAAM,CAAC,cAAc,EAAE,6DAA6D,CAAC;SACrF,MAAM,CAAC,KAAK,EAAE,OAAgB,EAAE,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,qBAAqB,EAAE,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAClM,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,WAAW,CAAC,gCAAgC,CAAC,CAAC;IAC7F,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,OAAgB,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,iBAAiB,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC;IACpK,KAAK,MAAM,SAAS,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,UAAU,CAAU;QAAE,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,OAAgB,EAAE,EAAE;YACrL,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAAC,KAAK,CAAC,MAAM,iBAAiB,CAAC,MAAM,EAAE,GAAG,MAAM,oBAAoB,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,IAAI,SAAS,EAAE,CAAC,CAAC,CAAC;QAChK,CAAC,CAAC,CAAC;IACH,SAAS,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,OAAgB,EAAE,EAAE;QACrI,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAAC,KAAK,CAAC,MAAM,iBAAiB,CAAC,MAAM,EAAE,MAAM,oBAAoB,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACjK,CAAC,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,yDAAyD,CAAC,CAAC;IAC5G,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,KAAa,EAAE,OAAgB,EAAE,EAAE;QACvG,KAAK,CAAC,MAAM,iBAAiB,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,cAAc,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IAChH,CAAC,CAAC,CAAC;IACH,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,OAAgB,EAAE,EAAE;QAClG,KAAK,CAAC,MAAM,iBAAiB,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC1G,CAAC,CAAC,CAAC;IACH,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,WAAW,CAAC,0DAA0D,CAAC,CAAC;IACrH,KAAK,MAAM,SAAS,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,yBAAyB,EAAE,YAAY,CAAU,EAAE,CAAC;QACrI,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;QAC9D,IAAI,CAAC,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC;YAAE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACxE,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAC5D,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC;YAAE,OAAO,CAAC,cAAc,CAAC,eAAe,EAAE,qBAAqB,CAAC,CAAC;QACjI,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC;YAAE,OAAO,CAAC,MAAM,CAAC,0BAA0B,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,8BAA8B,EAAE,qEAAqE,CAAC,CAAC;QACtO,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,IAAe,EAAE,EAAE;YAC1C,MAAM,OAAO,GAAG,CAAC,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;YACxD,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YACnD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAY,CAAC;YACjD,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAC7C,MAAM,aAAa,GAAG,MAAM,oBAAoB,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;YAC5E,MAAM,IAAI,GAAG,GAAG,aAAa,aAAa,IAAI,CAAC,CAAC,CAAC,IAAI,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;YACvF,MAAM,IAAI,GAAY,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAC3H,IAAI,QAA+C,CAAC;YACpD,IAAI,SAAS,KAAK,QAAQ,IAAI,SAAS,KAAK,YAAY,EAAE,CAAC;gBACzD,8FAA8F;gBAC9F,MAAM,QAAQ,GAAG,SAAS,KAAK,YAAY,CAAC,CAAC,CAAC,MAAM,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;gBAC3F,IAAI,wBAAwB,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACvC,IAAI,SAAS,KAAK,YAAY,IAAI,OAAO,CAAC,YAAY,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC;wBACpF,IAAI,CAAC,OAAO,CAAC,YAAY,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,YAA4B,CAAC,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,IAAI,EAAE;4BAC9H,MAAM,IAAI,KAAK,CAAC,+GAA+G,CAAC,CAAC;wBACnI,MAAM,YAAY,GAAG,IAAI,IAAK,QAA6B,CAAC,IAAI,CAAC;wBACjE,QAAQ,GAAG,MAAM,cAAc,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,YAA4B,EAAE,WAAW,EAAE,OAAO,CAAC,iBAAiB;4BAC5H,QAAQ,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,kBAAkB,CAAC,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,CAAC,CAAC;oBAC9G,CAAC;gBACH,CAAC;qBAAM,IAAI,SAAS,KAAK,YAAY,EAAE,CAAC;oBACtC,KAAK,CAAC,EAAE,MAAM,EAAE,iBAAiB,CAAC,QAAQ,CAAC,EAAE,mBAAmB,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE,EAAE,CAAC,CAAC;oBAChG,OAAO;gBACT,CAAC;YACH,CAAC;YACD,MAAM,MAAM,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;YACvG,MAAM,MAAM,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,SAAS,EAAE,CAAC;YAC9F,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,MAAM,EAAE,IAAI,GAAG,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;YAC5E,IAAI,QAA4B,CAAC;YACjC,IAAI,QAAQ,EAAE,CAAC;gBACb,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,gBAAgB,IAAI,MAAM,CAAC,IAAI,OAAO,MAAM,CAAC,cAAc,KAAK,QAAQ;oBACrH,MAAM,IAAI,KAAK,CAAC,wIAAwI,CAAC,CAAC;gBAC5J,IAAI,CAAC;oBAAC,MAAM,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;oBAAC,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC;gBAAC,CAAC;gBACrF,MAAM,CAAC;oBAAC,MAAM,IAAI,KAAK,CAAC,8MAA8M,CAAC,CAAC;gBAAC,CAAC;YAC5O,CAAC;YACD,KAAK,CAAC,EAAE,MAAM,EAAE,iBAAiB,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,oBAAoB,EAAE,QAAQ,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC3H,GAAG,CAAC,SAAS,KAAK,QAAQ,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,mBAAmB,EAAE,EAAE,MAAM,EAAE,wBAAwB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QAC3J,CAAC,CAAC,CAAC;IACL,CAAC;IACD,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,yDAAyD,CAAC,CAAC;IAChH,KAAK,MAAM,SAAS,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,kBAAkB,CAAU,EAAE,CAAC;QAC3E,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,OAAgB,EAAE,EAAE;YAC9G,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAC7C,MAAM,IAAI,GAAG,GAAG,MAAM,oBAAoB,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,SAAS,CAAC;YAC/E,KAAK,CAAC,MAAM,iBAAiB,CAAC,MAAM,EAAE,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,UAAU,EAAE,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC;QAC9O,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,SAAS,wBAAwB,CAAC,KAAc;IAC9C,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,QAAQ,GAAG,KAAyD,CAAC;IAC3E,OAAO,QAAQ,CAAC,WAAW,KAAK,MAAM,IAAI,QAAQ,CAAC,aAAa,KAAK,iBAAiB,CAAC;AACzF,CAAC"}
@@ -1,8 +1,10 @@
1
1
  import { runStdioServer } from "../mcp/server.js";
2
+ import { runManagementStdioServer } from "../mcp/management-server.js";
2
3
  export function mcpCommand(program) {
3
4
  program
4
5
  .command("mcp")
5
- .description("Run the Authflow onboarding MCP server on stdio")
6
+ .description("Run workspace-scoped Authflow management using your OS-stored login")
7
+ .option("--legacy-admin", "Use the legacy operator-admin adapter for migration and recovery")
6
8
  .addHelpText("after", [
7
9
  "",
8
10
  "Add to an MCP client (Cursor, Claude Desktop) so a coding agent can onboard a server",
@@ -10,15 +12,18 @@ export function mcpCommand(program) {
10
12
  "",
11
13
  ' { "mcpServers": { "authflow": {',
12
14
  ' "command": "npx", "args": ["-y", "-p", "authflow-cli", "authflow", "mcp"],',
13
- ' "env": { "AUTHFLOW_ISSUER": "https://…", "AUTHFLOW_ADMIN_API_KEY": "…" } } } }',
15
+ ' "env": { "AUTHFLOW_ISSUER": "https://…" } } } }',
14
16
  "",
15
- "Mint AUTHFLOW_ADMIN_API_KEY with `authflow signup --email you@example.com` if you do not",
16
- "already have one. The onboarding server can also mint it via authflow_signup.",
17
+ "Run authflow login first. The credential stays in your operating system's keyring.",
18
+ "You can also connect a remote MCP client directly to <issuer>/management/mcp.",
17
19
  "",
18
20
  "stdout is the MCP transport, so this command writes nothing else to it.",
19
21
  ].join("\n"))
20
- .action(async () => {
21
- await runStdioServer();
22
+ .action(async (options) => {
23
+ if (options.legacyAdmin)
24
+ await runStdioServer();
25
+ else
26
+ await runManagementStdioServer();
22
27
  });
23
28
  }
24
29
  //# sourceMappingURL=mcp.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/commands/mcp.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,MAAM,UAAU,UAAU,CAAC,OAAgB;IACzC,OAAO;SACJ,OAAO,CAAC,KAAK,CAAC;SACd,WAAW,CAAC,iDAAiD,CAAC;SAC9D,WAAW,CACV,OAAO,EACP;QACE,EAAE;QACF,sFAAsF;QACtF,2CAA2C;QAC3C,EAAE;QACF,mCAAmC;QACnC,kFAAkF;QAClF,sFAAsF;QACtF,EAAE;QACF,0FAA0F;QAC1F,+EAA+E;QAC/E,EAAE;QACF,yEAAyE;KAC1E,CAAC,IAAI,CAAC,IAAI,CAAC,CACb;SACA,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,cAAc,EAAE,CAAC;IACzB,CAAC,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/commands/mcp.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAEvE,MAAM,UAAU,UAAU,CAAC,OAAgB;IACzC,OAAO;SACJ,OAAO,CAAC,KAAK,CAAC;SACd,WAAW,CAAC,qEAAqE,CAAC;SAClF,MAAM,CAAC,gBAAgB,EAAE,kEAAkE,CAAC;SAC5F,WAAW,CACV,OAAO,EACP;QACE,EAAE;QACF,sFAAsF;QACtF,2CAA2C;QAC3C,EAAE;QACF,mCAAmC;QACnC,kFAAkF;QAClF,uDAAuD;QACvD,EAAE;QACF,oFAAoF;QACpF,+EAA+E;QAC/E,EAAE;QACF,yEAAyE;KAC1E,CAAC,IAAI,CAAC,IAAI,CAAC,CACb;SACA,MAAM,CAAC,KAAK,EAAE,OAAkC,EAAE,EAAE;QACnD,IAAI,OAAO,CAAC,WAAW;YAAE,MAAM,cAAc,EAAE,CAAC;;YAC3C,MAAM,wBAAwB,EAAE,CAAC;IACxC,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -1,6 +1,6 @@
1
- import { requireAdminKey, requireIssuer } from "../config.js";
2
- import { buildIntegrationPlan, integrationFrameworks, isIntegrationFramework, } from "../integration.js";
3
- import { getResource } from "../rail.js";
1
+ import { requireIssuer } from "../config.js";
2
+ import { integrationFrameworks, isIntegrationFramework, } from "../integration.js";
3
+ import { currentWorkspacePath, managementRequest } from "../management.js";
4
4
  /**
5
5
  * CLI twin of `authflow_integration_plan`. The MCP tool is how an agent usually gets this; the
6
6
  * command exists so the two surfaces stay the same size.
@@ -12,14 +12,14 @@ export function planCommand(program) {
12
12
  .requiredOption("--slug <slug>", "Resource slug")
13
13
  .requiredOption("--framework <kind>", `Origin implementation (${integrationFrameworks.join(" | ")})`)
14
14
  .option("--issuer <url>", "Authflow issuer (default: AUTHFLOW_ISSUER)")
15
- .option("--admin-key <key>", "Admin API key (default: AUTHFLOW_ADMIN_API_KEY)")
15
+ .option("--workspace <id>", "Workspace selected by authflow login")
16
16
  .action(async (opts) => {
17
17
  if (!isIntegrationFramework(opts.framework)) {
18
18
  throw new Error(`--framework must be one of: ${integrationFrameworks.join(", ")}. Got '${opts.framework}'.`);
19
19
  }
20
- const auth = { issuer: requireIssuer(opts.issuer), adminKey: requireAdminKey(opts.adminKey) };
21
- const receipt = await getResource(auth, opts.slug);
22
- const plan = buildIntegrationPlan(opts.framework, receipt);
20
+ const issuer = requireIssuer(opts.issuer);
21
+ const workspace = await currentWorkspacePath(issuer, opts.workspace);
22
+ const plan = await managementRequest(issuer, `${workspace}/resources/${encodeURIComponent(opts.slug)}/integration-plan`, "GET", undefined, { framework: opts.framework });
23
23
  console.log(JSON.stringify(plan, null, 2));
24
24
  });
25
25
  }
@@ -1 +1 @@
1
- {"version":3,"file":"plan.js","sourceRoot":"","sources":["../../src/commands/plan.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,OAAgB;IAC1C,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,qEAAqE,CAAC;SAClF,cAAc,CAAC,eAAe,EAAE,eAAe,CAAC;SAChD,cAAc,CACb,oBAAoB,EACpB,0BAA0B,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAC/D;SACA,MAAM,CAAC,gBAAgB,EAAE,4CAA4C,CAAC;SACtE,MAAM,CAAC,mBAAmB,EAAE,iDAAiD,CAAC;SAC9E,MAAM,CAAC,KAAK,EAAE,IAA6E,EAAE,EAAE;QAC9F,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YAC5C,MAAM,IAAI,KAAK,CACb,+BAA+B,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,SAAS,IAAI,CAC5F,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,GAAG,EAAE,MAAM,EAAE,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC9F,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACnD,MAAM,IAAI,GAAG,oBAAoB,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC3D,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"plan.js","sourceRoot":"","sources":["../../src/commands/plan.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EACL,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE3E;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,OAAgB;IAC1C,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,qEAAqE,CAAC;SAClF,cAAc,CAAC,eAAe,EAAE,eAAe,CAAC;SAChD,cAAc,CACb,oBAAoB,EACpB,0BAA0B,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAC/D;SACA,MAAM,CAAC,gBAAgB,EAAE,4CAA4C,CAAC;SACtE,MAAM,CAAC,kBAAkB,EAAE,sCAAsC,CAAC;SAClE,MAAM,CAAC,KAAK,EAAE,IAA8E,EAAE,EAAE;QAC/F,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YAC5C,MAAM,IAAI,KAAK,CACb,+BAA+B,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,SAAS,IAAI,CAC5F,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1C,MAAM,SAAS,GAAG,MAAM,oBAAoB,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QACrE,MAAM,IAAI,GAAG,MAAM,iBAAiB,CAAC,MAAM,EAAE,GAAG,SAAS,cAAc,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;QAC1K,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -1,2 +1,3 @@
1
1
  import type { Command } from "commander";
2
+ /** Compatibility command: an email address is not proof of account ownership. */
2
3
  export declare function signupCommand(program: Command): void;
@@ -1,53 +1,7 @@
1
- import { requireIssuer } from "../config.js";
2
- import { signupTenant } from "../rail.js";
3
- import { writeAdminApiKey } from "../secrets.js";
1
+ /** Compatibility command: an email address is not proof of account ownership. */
4
2
  export function signupCommand(program) {
5
- program
6
- .command("signup")
7
- .description("Mint a per-tenant admin API key (shown once)")
8
- .requiredOption("--email <address>", "Email that owns the tenant")
9
- .option("--issuer <url>", "Authflow issuer (default: AUTHFLOW_ISSUER)")
10
- .option("--write-secrets", "Write the key to an env file (default: .env.local)", true)
11
- .option("--no-write-secrets", "Print the key only; do not write it to disk")
12
- .option("--secret-destination <path>", "Env-file path for --write-secrets")
13
- .addHelpText("after", [
14
- "",
15
- "The key is scoped to slugs you register with it. Paste it into Cursor as",
16
- "AUTHFLOW_ADMIN_API_KEY, then run `authflow mcp` or `authflow init`.",
17
- ].join("\n"))
18
- .action(async (opts) => {
19
- const issuer = requireIssuer(opts.issuer);
20
- const receipt = await signupTenant(issuer, opts.email);
21
- let storedAt;
22
- if (opts.writeSecrets !== false) {
23
- storedAt = await writeAdminApiKey({
24
- value: receipt.admin_api_key,
25
- destination: opts.secretDestination,
26
- });
27
- }
28
- const mcpConfig = {
29
- mcpServers: {
30
- authflow: {
31
- command: "npx",
32
- args: ["-y", "-p", "authflow-cli", "authflow", "mcp"],
33
- env: {
34
- AUTHFLOW_ISSUER: receipt.issuer,
35
- AUTHFLOW_ADMIN_API_KEY: storedAt ? `<from ${storedAt}>` : receipt.admin_api_key,
36
- },
37
- },
38
- },
39
- };
40
- process.stdout.write(JSON.stringify({
41
- ...receipt,
42
- admin_api_key: storedAt ? `<stored in ${storedAt}>` : receipt.admin_api_key,
43
- mcp_config: mcpConfig,
44
- next_steps: [
45
- storedAt
46
- ? `Load ${storedAt} (or copy the key into Cursor's MCP env) and run: npx -y -p authflow-cli authflow init --slug <your-slug>`
47
- : "Store the admin_api_key, then: npx -y -p authflow-cli authflow init --slug <your-slug>",
48
- "Or paste mcp_config into Cursor and let the agent finish onboarding.",
49
- ],
50
- }, null, 2) + "\n");
51
- });
3
+ program.command("signup").description("Moved: use verified browser sign-in with authflow login")
4
+ .option("--email <address>").option("--issuer <url>").option("--write-secrets").option("--no-write-secrets").option("--secret-destination <path>")
5
+ .action(() => { throw new Error("Email-only signup has been retired. Create a workspace in the Authflow portal, then run authflow login --issuer <issuer>. Existing tenant owners can claim their workspace in the portal with their current admin credential."); });
52
6
  }
53
7
  //# sourceMappingURL=signup.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"signup.js","sourceRoot":"","sources":["../../src/commands/signup.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AASjD,MAAM,UAAU,aAAa,CAAC,OAAgB;IAC5C,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,8CAA8C,CAAC;SAC3D,cAAc,CAAC,mBAAmB,EAAE,4BAA4B,CAAC;SACjE,MAAM,CAAC,gBAAgB,EAAE,4CAA4C,CAAC;SACtE,MAAM,CAAC,iBAAiB,EAAE,oDAAoD,EAAE,IAAI,CAAC;SACrF,MAAM,CAAC,oBAAoB,EAAE,6CAA6C,CAAC;SAC3E,MAAM,CAAC,6BAA6B,EAAE,mCAAmC,CAAC;SAC1E,WAAW,CACV,OAAO,EACP;QACE,EAAE;QACF,0EAA0E;QAC1E,qEAAqE;KACtE,CAAC,IAAI,CAAC,IAAI,CAAC,CACb;SACA,MAAM,CAAC,KAAK,EAAE,IAAmB,EAAE,EAAE;QACpC,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1C,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAEvD,IAAI,QAA4B,CAAC;QACjC,IAAI,IAAI,CAAC,YAAY,KAAK,KAAK,EAAE,CAAC;YAChC,QAAQ,GAAG,MAAM,gBAAgB,CAAC;gBAChC,KAAK,EAAE,OAAO,CAAC,aAAa;gBAC5B,WAAW,EAAE,IAAI,CAAC,iBAAiB;aACpC,CAAC,CAAC;QACL,CAAC;QAED,MAAM,SAAS,GAAG;YAChB,UAAU,EAAE;gBACV,QAAQ,EAAE;oBACR,OAAO,EAAE,KAAK;oBACd,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,cAAc,EAAE,UAAU,EAAE,KAAK,CAAC;oBACrD,GAAG,EAAE;wBACH,eAAe,EAAE,OAAO,CAAC,MAAM;wBAC/B,sBAAsB,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS,QAAQ,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa;qBAChF;iBACF;aACF;SACF,CAAC;QAEF,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,IAAI,CAAC,SAAS,CACZ;YACE,GAAG,OAAO;YACV,aAAa,EAAE,QAAQ,CAAC,CAAC,CAAC,cAAc,QAAQ,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa;YAC3E,UAAU,EAAE,SAAS;YACrB,UAAU,EAAE;gBACV,QAAQ;oBACN,CAAC,CAAC,QAAQ,QAAQ,2GAA2G;oBAC7H,CAAC,CAAC,wFAAwF;gBAC5F,sEAAsE;aACvE;SACF,EACD,IAAI,EACJ,CAAC,CACF,GAAG,IAAI,CACT,CAAC;IACJ,CAAC,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"signup.js","sourceRoot":"","sources":["../../src/commands/signup.ts"],"names":[],"mappings":"AAEA,iFAAiF;AACjF,MAAM,UAAU,aAAa,CAAC,OAAgB;IAC5C,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,yDAAyD,CAAC;SAC7F,MAAM,CAAC,mBAAmB,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,MAAM,CAAC,6BAA6B,CAAC;SACjJ,MAAM,CAAC,GAAG,EAAE,GAAG,MAAM,IAAI,KAAK,CAAC,+NAA+N,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACzQ,CAAC"}
package/dist/config.d.ts CHANGED
@@ -54,12 +54,16 @@ export type RegistrationReceipt = {
54
54
  origin_api_key?: string;
55
55
  gateway_egress_cidrs?: string[];
56
56
  status?: string;
57
+ access_mode?: "free" | "paid";
57
58
  metering_mode?: string;
59
+ metering_default_units?: number;
60
+ tool_units?: Record<string, number>;
58
61
  /**
59
62
  * What still blocks go-live: origin_base_uri, connected_account_id, stripe_onboarding_complete,
60
63
  * and custom_domain_dns while a custom host is set but not yet ready.
61
64
  */
62
65
  pending_requirements?: string[];
66
+ allowed_actions?: string[];
63
67
  last_probe_at_utc?: string | null;
64
68
  last_probe_passed?: boolean | null;
65
69
  };
package/dist/config.js CHANGED
@@ -9,7 +9,7 @@ export function requireIssuer(flag) {
9
9
  export function requireAdminKey(flag) {
10
10
  const key = (flag ?? process.env.AUTHFLOW_ADMIN_API_KEY ?? "").trim();
11
11
  if (!key) {
12
- throw new Error("Set AUTHFLOW_ADMIN_API_KEY or pass --admin-key.");
12
+ throw new Error("This legacy operator command requires AUTHFLOW_ADMIN_API_KEY or --admin-key. For creator onboarding, run authflow login and use authflow resource commands. Claim an existing workspace in the portal with its current tenant key.");
13
13
  }
14
14
  return key;
15
15
  }
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ export type LoginCredential = {
2
+ issuer: string;
3
+ client_id: string;
4
+ access_token: string;
5
+ refresh_token?: string;
6
+ expires_at: number;
7
+ workspace_id: string;
8
+ };
9
+ /** Credentials never enter the checkout, environment files, or tool results. */
10
+ export declare function credentialEntry(issuer: string, suffix?: string): Promise<import("@napi-rs/keyring").Entry>;
11
+ export declare function readCredential(issuer: string): Promise<LoginCredential | undefined>;
12
+ export declare function saveCredential(credential: LoginCredential): Promise<void>;
13
+ export declare function deleteCredential(issuer: string): Promise<void>;
14
+ /** Serialize refresh-token rotation across CLI/MCP processes. The lock contains no secrets. */
15
+ export declare function withCredentialLock<T>(issuer: string, action: () => Promise<T>): Promise<T>;
16
+ /** One storage boundary also lets protocol tests use an isolated in-memory credential store. */
17
+ export declare const credentialStore: {
18
+ read: typeof readCredential;
19
+ save: typeof saveCredential;
20
+ delete: typeof deleteCredential;
21
+ withLock: typeof withCredentialLock;
22
+ };
@@ -0,0 +1,206 @@
1
+ import { createHash, randomBytes } from "node:crypto";
2
+ import { mkdir, readFile, rmdir, stat, unlink, utimes, writeFile } from "node:fs/promises";
3
+ import { homedir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { setTimeout as delay } from "node:timers/promises";
6
+ /** Credentials never enter the checkout, environment files, or tool results. */
7
+ export async function credentialEntry(issuer, suffix = "") {
8
+ try {
9
+ const { Entry } = await import("@napi-rs/keyring");
10
+ return new Entry("authflow-cli", issuer + suffix, { linux: { store: "secret-service" } });
11
+ }
12
+ catch {
13
+ throw new Error("The operating system credential store is unavailable. Enable your desktop keyring and retry; Authflow does not fall back to plaintext credentials.");
14
+ }
15
+ }
16
+ export async function readCredential(issuer) {
17
+ const entry = await credentialEntry(issuer);
18
+ let value;
19
+ try {
20
+ value = entry.getPassword();
21
+ }
22
+ catch {
23
+ throw new Error("Unable to read the OS credential store. Unlock it and retry authflow login.");
24
+ }
25
+ if (!value)
26
+ return undefined;
27
+ const manifest = parseManifest(value);
28
+ const chunks = [];
29
+ for (let i = 0; i < manifest.count; i++) {
30
+ const chunk = (await credentialEntry(issuer, `:${manifest.generation}:${i}`)).getPassword();
31
+ if (chunk === null)
32
+ throw new Error("Stored Authflow login is incomplete; run authflow login again.");
33
+ chunks.push(chunk);
34
+ }
35
+ let parsed;
36
+ try {
37
+ parsed = JSON.parse(chunks.join(""));
38
+ }
39
+ catch {
40
+ throw new Error("Stored Authflow login is invalid; run authflow login again.");
41
+ }
42
+ if (!parsed || typeof parsed !== "object")
43
+ throw new Error("Stored Authflow login is invalid; run authflow login again.");
44
+ const credential = parsed;
45
+ if (credential.issuer !== issuer || typeof credential.client_id !== "string" || !credential.client_id
46
+ || typeof credential.access_token !== "string" || !credential.access_token || typeof credential.workspace_id !== "string" || !credential.workspace_id
47
+ || credential.refresh_token !== undefined && typeof credential.refresh_token !== "string" || !Number.isFinite(credential.expires_at)) {
48
+ throw new Error("Stored Authflow login is invalid; run authflow login again.");
49
+ }
50
+ return credential;
51
+ }
52
+ export async function saveCredential(credential) {
53
+ // Windows limits each credential blob. Publish one small manifest only after every
54
+ // protected chunk is written; interrupted writes leave the previous login readable.
55
+ const entry = await credentialEntry(credential.issuer);
56
+ const previous = entry.getPassword();
57
+ const serialized = JSON.stringify(credential);
58
+ const generation = randomBytes(16).toString("hex");
59
+ const count = Math.ceil(serialized.length / 1000);
60
+ if (count > 64)
61
+ throw new Error("The issuer returned an unexpectedly large login credential.");
62
+ let written = 0;
63
+ try {
64
+ for (; written < count; written++) {
65
+ (await credentialEntry(credential.issuer, `:${generation}:${written}`)).setPassword(serialized.slice(written * 1000, (written + 1) * 1000));
66
+ }
67
+ entry.setPassword(JSON.stringify({ generation, count }));
68
+ }
69
+ catch {
70
+ await removeChunks(credential.issuer, { generation, count: written });
71
+ throw new Error("Unable to save the login in your OS credential store. Unlock it and retry authflow login.");
72
+ }
73
+ if (previous) {
74
+ try {
75
+ await removeChunks(credential.issuer, parseManifest(previous));
76
+ }
77
+ catch { /* Replacing an invalid manifest still successfully repairs the login. */ }
78
+ }
79
+ }
80
+ export async function deleteCredential(issuer) {
81
+ const entry = await credentialEntry(issuer);
82
+ const previous = entry.getPassword();
83
+ entry.deletePassword();
84
+ if (previous) {
85
+ try {
86
+ await removeChunks(issuer, parseManifest(previous));
87
+ }
88
+ catch { /* An invalid old manifest cannot make removal of the login fail. */ }
89
+ }
90
+ }
91
+ function parseManifest(value) {
92
+ let parsed;
93
+ try {
94
+ parsed = JSON.parse(value);
95
+ }
96
+ catch {
97
+ throw new Error("Stored Authflow login is invalid; run authflow login again.");
98
+ }
99
+ if (!parsed || typeof parsed !== "object" || !/^[a-f0-9]{32}$/.test(parsed.generation) || !Number.isInteger(parsed.count) || parsed.count < 1 || parsed.count > 64) {
100
+ throw new Error("Stored Authflow login is invalid; run authflow login again.");
101
+ }
102
+ return parsed;
103
+ }
104
+ async function removeChunks(issuer, manifest) {
105
+ for (let i = 0; i < manifest.count; i++) {
106
+ try {
107
+ (await credentialEntry(issuer, `:${manifest.generation}:${i}`)).deletePassword();
108
+ }
109
+ catch { /* A revoked orphan remains OS-protected. */ }
110
+ }
111
+ }
112
+ /** Serialize refresh-token rotation across CLI/MCP processes. The lock contains no secrets. */
113
+ export async function withCredentialLock(issuer, action) {
114
+ const directory = join(homedir(), ".authflow", "locks");
115
+ await mkdir(directory, { recursive: true, mode: 0o700 });
116
+ const lock = join(directory, createHash("sha256").update(issuer).digest("hex"));
117
+ const ownerPath = join(lock, "owner.json");
118
+ const owner = { pid: process.pid, id: randomBytes(16).toString("hex") };
119
+ const deadline = Date.now() + 45_000;
120
+ while (true) {
121
+ try {
122
+ await mkdir(lock, { mode: 0o700 });
123
+ break;
124
+ }
125
+ catch (error) {
126
+ if (error.code !== "EEXIST")
127
+ throw error;
128
+ const info = await stat(lock).catch(() => undefined);
129
+ // A suspended process can miss its heartbeat while still holding a rotating refresh
130
+ // token. Never steal its lock merely because a timer elapsed.
131
+ if (info && Date.now() - info.mtimeMs > 60_000) {
132
+ await recoverAbandonedLock(lock, ownerPath);
133
+ }
134
+ if (Date.now() >= deadline)
135
+ throw new Error("Another Authflow login is busy. Retry shortly.");
136
+ await delay(200);
137
+ }
138
+ }
139
+ try {
140
+ await writeFile(ownerPath, JSON.stringify(owner), { mode: 0o600 });
141
+ }
142
+ catch (error) {
143
+ await rmdir(lock).catch(() => undefined);
144
+ throw error;
145
+ }
146
+ const heartbeat = setInterval(() => { const now = new Date(); void utimes(lock, now, now).catch(() => undefined); }, 10_000);
147
+ heartbeat.unref();
148
+ try {
149
+ return await action();
150
+ }
151
+ finally {
152
+ clearInterval(heartbeat);
153
+ if ((await lockOwner(ownerPath))?.id === owner.id) {
154
+ await unlink(ownerPath);
155
+ await rmdir(lock);
156
+ }
157
+ }
158
+ }
159
+ async function lockOwner(path) {
160
+ try {
161
+ const owner = JSON.parse(await readFile(path, "utf8"));
162
+ if (owner && typeof owner === "object" && "pid" in owner && "id" in owner
163
+ && Number.isInteger(owner.pid) && Number(owner.pid) > 0 && typeof owner.id === "string")
164
+ return owner;
165
+ }
166
+ catch { /* An interrupted acquisition can leave an empty legacy lock. */ }
167
+ return undefined;
168
+ }
169
+ function processIsAlive(pid) {
170
+ try {
171
+ process.kill(pid, 0);
172
+ return true;
173
+ }
174
+ catch (error) {
175
+ return error.code !== "ESRCH";
176
+ }
177
+ }
178
+ async function recoverAbandonedLock(lock, ownerPath) {
179
+ // Serialize stale cleanup. Recheck the owner after acquiring this marker: another
180
+ // waiter may already have recovered the directory and acquired a fresh login lock.
181
+ const recovery = join(lock, "recovering");
182
+ try {
183
+ await mkdir(recovery, { mode: 0o700 });
184
+ }
185
+ catch {
186
+ return;
187
+ }
188
+ let abandoned = false;
189
+ try {
190
+ const previous = await lockOwner(ownerPath);
191
+ if (previous && processIsAlive(previous.pid))
192
+ return;
193
+ abandoned = true;
194
+ await unlink(ownerPath).catch(() => undefined);
195
+ }
196
+ finally {
197
+ await rmdir(recovery).catch(() => undefined);
198
+ }
199
+ // A new owner writes owner.json before entering its action, so a delayed cleanup
200
+ // cannot delete an acquired lock: rmdir refuses any nonempty directory.
201
+ if (abandoned)
202
+ await rmdir(lock).catch(() => undefined);
203
+ }
204
+ /** One storage boundary also lets protocol tests use an isolated in-memory credential store. */
205
+ export const credentialStore = { read: readCredential, save: saveCredential, delete: deleteCredential, withLock: withCredentialLock };
206
+ //# sourceMappingURL=credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.js","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"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"}