modelos-secure 0.1.1 → 0.1.2

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 @@
1
+ export { t as loginCommand } from "./login-JPkrnvZC.js";
@@ -426,13 +426,27 @@ function refusalKind(answer) {
426
426
  if (!json && status < 500 && (status < 300 || page)) return "not-the-app";
427
427
  return null;
428
428
  }
429
+ /**
430
+ * IAP's own words for a refusal, when it gave them as plain text, such as "Invalid bearer token.
431
+ * Audience doesn't match the allowlisted oauth clients for this application." A page gives none.
432
+ */
433
+ function iapReason(headers, text) {
434
+ if ((headers.get("content-type") ?? "").includes("html")) return void 0;
435
+ const line = text.trim().split("\n")[0]?.trim() ?? "";
436
+ if (!(headers.get("x-goog-iap-generated-response") === "true" || line.startsWith("Invalid IAP credentials")) || !line || line.startsWith("<")) return void 0;
437
+ const words = line.replace(/^Invalid IAP credentials:\s*/i, "").slice(0, 240).trim();
438
+ if (!words) return void 0;
439
+ return /[.!?]$/.test(words) ? words : `${words}.`;
440
+ }
429
441
  /** What happened, why, and what to do, in the voice of the CLI's other failures. */
430
- function refusalMessage(kind, credential, url, ci = Boolean(process.env.CI)) {
442
+ function refusalMessage(kind, credential, url, ci = Boolean(process.env.CI), detail = {}) {
431
443
  if (kind === "not-the-app") return `${url} answered, but it is not ModelOS Secure. Check the address against the login command on the tokens page.`;
432
444
  if (kind === "no-sign-in") return ci ? "This address needs a Google sign-in, and none was found. In CI, set MODELOS_SECURE_CLIENT_ID with gcloud signed in as a service account, or set MODELOS_SECURE_IAP_TOKEN." : "This address needs a Google sign-in, and this machine has none yet. Run modelos-secure login with the command from the tokens page.";
433
445
  if (kind === "not-allowed") return credential.email ? `You are signed in to Google as ${credential.email}, but that account is not allowed through to ModelOS Secure. Ask whoever runs ModelOS Secure to give it access.` : "This Google account is not allowed through to ModelOS Secure. Ask whoever runs ModelOS Secure to give it access.";
434
- if (credential.source === "env") return "Google refused the token in MODELOS_SECURE_IAP_TOKEN: it has expired, or it was made for another client ID. Make a new one for the client ID on the tokens page.";
435
- if (credential.source === "gcloud") return "Google refused the identity token from gcloud: it was made for another client ID, or the account is not a service account. Check MODELOS_SECURE_CLIENT_ID against the tokens page.";
446
+ const said = detail.reason ? `It said: ${detail.reason}` : detail.redirected ? "It sent the request to its sign-in page instead." : "";
447
+ if (credential.source === "env") return `Google refused the token in MODELOS_SECURE_IAP_TOKEN: it has expired, or it was made for another client ID. Make a new one for the client ID on the tokens page.${said ? ` ${said}` : ""}`;
448
+ if (credential.source === "gcloud") return `Google refused the identity token from gcloud: it was made for another client ID, or the account is not a service account. Check MODELOS_SECURE_CLIENT_ID against the tokens page.${said ? ` ${said}` : ""}`;
449
+ if (said) return `Google did not let your sign-in through to ModelOS Secure. ${said} Run modelos-secure login again. If it says the same, send this message to whoever runs ModelOS Secure.`;
436
450
  return "Google refused your sign-in: it has expired or was revoked. Run modelos-secure login again.";
437
451
  }
438
452
  // src/api.ts
@@ -528,8 +542,8 @@ function apiClient(connection, options = {}) {
528
542
  const sent = await credential();
529
543
  const url = `${connection.url}/api/v1${path}`;
530
544
  const headers = {
531
- authorization: `Bearer ${connection.token}`,
532
- ...sent.token ? { "proxy-authorization": `Bearer ${sent.token}` } : {},
545
+ authorization: `Bearer ${sent.token ?? connection.token}`,
546
+ "x-modelos-secure-token": connection.token,
533
547
  ...body ? { "content-type": body.type } : {}
534
548
  };
535
549
  const response = await (connection.tlsName ? fetchCheckingName(connection.tlsName)(url, {
@@ -560,7 +574,10 @@ function apiClient(connection, options = {}) {
560
574
  body: parsed,
561
575
  sent: Boolean(sent.token)
562
576
  });
563
- if (kind) throw new IapRefusal(kind, response.status, refusalMessage(kind, sent, connection.url));
577
+ if (kind) throw new IapRefusal(kind, response.status, refusalMessage(kind, sent, connection.url, void 0, {
578
+ reason: iapReason(response.headers, text),
579
+ redirected: response.status >= 300 && response.status < 400
580
+ }));
564
581
  if (!response.ok) {
565
582
  const error = typeof parsed === "object" && parsed !== null ? parsed.error : void 0;
566
583
  throw new ApiError(typeof error === "string" ? error : `The server answered ${response.status.toString()}.`, response.status);
package/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { _ as step, a as apiClient, c as Interrupted, d as blue, f as bold, g as say, h as red, i as IapRefusal, l as ask, m as grey, o as atAddress, p as dash, r as ApiError$1, s as readConnection, t as loginCommand, u as askText } from "./assets/login-WwE-Gunj.js";
2
+ import { _ as step, a as apiClient, c as Interrupted, d as blue, f as bold, g as say, h as red, i as IapRefusal, l as ask, m as grey, o as atAddress, p as dash, r as ApiError$1, s as readConnection, t as loginCommand, u as askText } from "./assets/login-JPkrnvZC.js";
3
3
  import { createRequire } from "node:module";
4
4
  import { existsSync } from "node:fs";
5
5
  import { fileURLToPath } from "node:url";
@@ -19485,7 +19485,7 @@ async function scanCommand(dir, options) {
19485
19485
  label: "Enter a token now",
19486
19486
  recommended: true,
19487
19487
  apply: async () => {
19488
- const { loginCommand } = await import("./assets/login-BcHFyX6z.js");
19488
+ const { loginCommand } = await import("./assets/login-BoqCvsTW.js");
19489
19489
  await loginCommand();
19490
19490
  const fresh = await readConnection();
19491
19491
  api = fresh ? apiClient(fresh) : null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "modelos-secure",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Tests AI systems for Security, Safety and Quality. One command connects a system from its code.",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {
@@ -1 +0,0 @@
1
- export { t as loginCommand } from "./login-WwE-Gunj.js";