@bkazemi/verily 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/verily.js CHANGED
@@ -9575,6 +9575,8 @@ var Verily = (() => {
9575
9575
  __export(browser_exports, {
9576
9576
  Refused: () => Refused,
9577
9577
  attestationLabel: () => attestationLabel,
9578
+ dialogPath: () => dialogPath,
9579
+ dialogRoute: () => dialogRoute,
9578
9580
  externalId: () => externalId,
9579
9581
  externalLink: () => externalLink,
9580
9582
  externalName: () => externalName,
@@ -9589,6 +9591,9 @@ var Verily = (() => {
9589
9591
  presentConnections: () => presentConnections,
9590
9592
  proofTitle: () => proofTitle,
9591
9593
  providerMethod: () => providerMethod,
9594
+ routeOf: () => routeOf,
9595
+ routePath: () => routePath,
9596
+ routes: () => routes,
9592
9597
  signedBy: () => signedBy,
9593
9598
  status: () => status,
9594
9599
  statusLabel: () => statusLabel,
@@ -9661,6 +9666,50 @@ var Verily = (() => {
9661
9666
  return void 0;
9662
9667
  }
9663
9668
 
9669
+ // src/core/routes.ts
9670
+ var routes = {
9671
+ methods: { method: "GET", path: "/methods" },
9672
+ start: { method: "POST", path: "/sessions" },
9673
+ flow: { method: "GET", path: "/flows/:id", format: "json" },
9674
+ submit: { method: "POST", path: "/flows/:id/submit" },
9675
+ approve: { method: "POST", path: "/flows/:id/approve" },
9676
+ disconnect: { method: "POST", path: "/connections/:id/disconnect", manages: true },
9677
+ mark: { method: "POST", path: "/connections/:id/mark", manages: true },
9678
+ share: { method: "POST", path: "/connections/:id/share", manages: true, dialog: false },
9679
+ shareRevoke: {
9680
+ method: "POST",
9681
+ path: "/connections/:id/share-revoke",
9682
+ manages: true,
9683
+ dialog: false
9684
+ }
9685
+ };
9686
+ var names = Object.keys(routes);
9687
+ function matches(route, path) {
9688
+ const want = route.path.split("/");
9689
+ const got = path.split("/");
9690
+ return want.length === got.length && want.every((part, at2) => part === ":id" ? got[at2] !== "" : part === got[at2]);
9691
+ }
9692
+ function routePath(name, id) {
9693
+ const route = routes[name];
9694
+ const path = route.path.replace(":id", encodeURIComponent(id ?? ""));
9695
+ return route.format ? `${path}?format=${route.format}` : path;
9696
+ }
9697
+ function routeOf(method, path) {
9698
+ return names.find((name) => routes[name].method === method && matches(routes[name], path));
9699
+ }
9700
+ function dialogRoute(method, path, query) {
9701
+ const name = routeOf(method, path);
9702
+ const route = name && routes[name];
9703
+ if (!route || route.dialog === false) return void 0;
9704
+ return !route.format || query.get("format") === route.format ? name : void 0;
9705
+ }
9706
+ function dialogPath(path) {
9707
+ return names.some((name) => {
9708
+ const route = routes[name];
9709
+ return route.dialog !== false && matches(route, path);
9710
+ });
9711
+ }
9712
+
9664
9713
  // src/core/index.ts
9665
9714
  var Refused = class extends Error {
9666
9715
  };
@@ -9710,14 +9759,16 @@ var Verily = (() => {
9710
9759
  function externalName(external) {
9711
9760
  return external.kind === void 0 || external.kind === "account" ? `@${external.handle.replace(/^@/, "")}` : external.handle;
9712
9761
  }
9713
- function attestationLabel(method, names) {
9762
+ function attestationLabel(method, names2, proof = {}) {
9763
+ const dnssec = proof.dnssec ? ", validated by DNSSEC" : "";
9714
9764
  return {
9715
- declared: `Stated by ${names.site}`,
9716
- oauth: `Signed in with ${names.provider}`,
9717
- gist: `Published a proof on ${names.provider}`,
9718
- backlink: `Linked back to ${names.site}`,
9719
- dns: `Named ${names.site} in a DNS record`,
9720
- wellknown: `Named ${names.site} in a file it serves`,
9765
+ // A site's word carries a proof only where its own DNS was read naming this verifier.
9766
+ declared: proof.artifactUrl ? `Stated by ${names2.site}, whose DNS names this verifier${dnssec}` : `Stated by ${names2.site}`,
9767
+ oauth: `Signed in with ${names2.provider}`,
9768
+ gist: `Published a proof on ${names2.provider}`,
9769
+ backlink: `Linked back to ${names2.site}`,
9770
+ dns: `Published a proof in its DNS${dnssec}`,
9771
+ wellknown: "Published a proof in a file it serves",
9721
9772
  signature: "Proved with a signature",
9722
9773
  code: "Entered a code sent to this address"
9723
9774
  }[method];
@@ -10434,7 +10485,7 @@ ${claims(evidence)}`;
10434
10485
  }
10435
10486
 
10436
10487
  // src/version.ts
10437
- var version = "v0.4.0";
10488
+ var version = "v0.5.0";
10438
10489
 
10439
10490
  // src/browser/evidence-dialog.ts
10440
10491
  function stampLink() {
@@ -10535,8 +10586,8 @@ ${claims(evidence)}`;
10535
10586
  }
10536
10587
  return svg;
10537
10588
  }
10538
- function attestationNote(attestation, names, additional = false) {
10539
- const label = attestationLabel(attestation.method, names);
10589
+ function attestationNote(attestation, names2, additional = false) {
10590
+ const label = attestationLabel(attestation.method, names2, attestation);
10540
10591
  if (!label) return [];
10541
10592
  const note = node("div", additional ? "+ " : "", `muted ${additional ? "additional" : "method"}`);
10542
10593
  if (!attestation.artifactUrl) {
@@ -10736,7 +10787,7 @@ ${claims(evidence)}`;
10736
10787
  for (const [label, time] of dateRows) {
10737
10788
  dates.append(node("dt", label), node("dd", moment(time)));
10738
10789
  }
10739
- const names = { site: evidence.siteName, provider };
10790
+ const names2 = { site: evidence.siteName, provider };
10740
10791
  const logo2 = providerMark(evidence.provider, evidence.attestations.external[0].method);
10741
10792
  const card = accountCard(
10742
10793
  // The mark and the name, or just the name. A mark that falls back to writing the name
@@ -10749,8 +10800,8 @@ ${claims(evidence)}`;
10749
10800
  // Status first, then how it was shown, then when. The proof explains the state
10750
10801
  // above it, so it cannot sit before that state has been given.
10751
10802
  summary,
10752
- ...attestationNote(main, names),
10753
- ...evidence.attestations.external.slice(1).flatMap((a2) => attestationNote(a2, names, true)),
10803
+ ...attestationNote(main, names2),
10804
+ ...evidence.attestations.external.slice(1).flatMap((a2) => attestationNote(a2, names2, true)),
10754
10805
  ...evidence.status === "revoked" || retired ? [] : evidence.mark === "preferred" ? [node("div", "Preferred", "listing preferred")] : evidence.mark === "unused" ? [node("div", "No longer used", "listing")] : [],
10755
10806
  dates,
10756
10807
  ...manage && removable(evidence).length ? [manageRow(evidence, manage)] : []
@@ -11594,7 +11645,7 @@ ${claims(evidence)}`;
11594
11645
  function init({ backendUrl, handoffUrl }) {
11595
11646
  const base = new URL(backendUrl, location.href);
11596
11647
  if (!["https:", "http:"].includes(base.protocol)) throw new Error("Invalid backend URL");
11597
- base.pathname = base.pathname.replace(/\/$/, "");
11648
+ const root = base.href.replace(/\/$/, "");
11598
11649
  const remote = base.origin !== location.origin;
11599
11650
  const bindings = /* @__PURE__ */ new Map();
11600
11651
  let session;
@@ -11607,7 +11658,7 @@ ${claims(evidence)}`;
11607
11658
  const vouched = handed.ok ? await handed.json() : void 0;
11608
11659
  if (!record(vouched) || typeof vouched.token !== "string")
11609
11660
  throw new Error("Verily request unavailable");
11610
- const traded = await fetch(`${base.href}/site/session`, {
11661
+ const traded = await fetch(`${root}/site/session`, {
11611
11662
  method: "POST",
11612
11663
  credentials: "omit",
11613
11664
  cache: "no-store",
@@ -11622,11 +11673,12 @@ ${claims(evidence)}`;
11622
11673
  async function ask(path, data, flow) {
11623
11674
  if (!remote) return request(path, data);
11624
11675
  const binding = flow && bindings.get(flow);
11625
- const response = await fetch(`${base.href}${path}`, {
11676
+ const response = await fetch(`${root}${path}`, {
11626
11677
  credentials: "omit",
11627
11678
  cache: "no-store",
11628
11679
  method: data ? "POST" : "GET",
11629
11680
  headers: {
11681
+ Accept: "application/json",
11630
11682
  Authorization: `Bearer ${await (session ??= openSession())}`,
11631
11683
  ...binding ? { "X-Verily-Flow": binding } : {},
11632
11684
  ...data ? { "Content-Type": "application/json" } : {}
@@ -11640,21 +11692,23 @@ ${claims(evidence)}`;
11640
11692
  return answer;
11641
11693
  }
11642
11694
  async function request(path, data) {
11643
- const response = await fetch(`${base.href}${path}`, {
11695
+ const response = await fetch(`${root}${path}`, {
11644
11696
  credentials: "same-origin",
11645
11697
  cache: "no-store",
11646
- ...data ? {
11647
- method: "POST",
11648
- headers: { "Content-Type": "application/json" },
11649
- body: JSON.stringify(data)
11650
- } : {}
11698
+ // Says what is wanted back, whatever is sent. A header any page may send to another
11699
+ // origin without asking first, so a badge on a static site reads as it did.
11700
+ headers: {
11701
+ Accept: "application/json",
11702
+ ...data ? { "Content-Type": "application/json" } : {}
11703
+ },
11704
+ ...data ? { method: "POST", body: JSON.stringify(data) } : {}
11651
11705
  });
11652
11706
  if (!response.ok) throw new Error("Verily request unavailable");
11653
11707
  return response.json();
11654
11708
  }
11655
11709
  const flows = {
11656
11710
  async methods() {
11657
- const data = await ask("/methods");
11711
+ const data = await ask(routePath("methods"));
11658
11712
  if (!record(data) || !record(data.local) || !Array.isArray(data.methods))
11659
11713
  throw new Error("Invalid methods response");
11660
11714
  if (typeof data.local.profileUrl === "string") safeUrl(data.local.profileUrl);
@@ -11662,15 +11716,15 @@ ${claims(evidence)}`;
11662
11716
  },
11663
11717
  start: async (provider, method, renew) => flowView(
11664
11718
  await ask(
11665
- "/sessions",
11719
+ routePath("start"),
11666
11720
  renew ? { kind: "renew", connectionId: renew, provider, method } : { kind: "connect", provider, method }
11667
11721
  )
11668
11722
  ),
11669
- read: async (id) => flowView(await ask(`/flows/${encodeURIComponent(id)}?format=json`, void 0, id)),
11670
- submit: async (id, artifact) => flowView(await ask(`/flows/${encodeURIComponent(id)}/submit`, { artifact }, id)),
11723
+ read: async (id) => flowView(await ask(routePath("flow", id), void 0, id)),
11724
+ submit: async (id, artifact) => flowView(await ask(routePath("submit", id), { artifact }, id)),
11671
11725
  async approve(id, visibility, cancel) {
11672
11726
  const data = await ask(
11673
- `/flows/${encodeURIComponent(id)}/approve`,
11727
+ routePath("approve", id),
11674
11728
  { action: cancel ? "cancel" : "approve", visibility },
11675
11729
  id
11676
11730
  );
@@ -11700,7 +11754,7 @@ ${claims(evidence)}`;
11700
11754
  );
11701
11755
  };
11702
11756
  window.addEventListener("message", receive);
11703
- popup.location.href = `${base.href}/site/enter`;
11757
+ popup.location.href = `${root}/site/enter`;
11704
11758
  }
11705
11759
  } : {}
11706
11760
  };
@@ -11724,7 +11778,7 @@ ${claims(evidence)}`;
11724
11778
  pill.setAttribute("aria-haspopup", "dialog");
11725
11779
  pill.onclick = async () => {
11726
11780
  if (typeof HTMLDialogElement === "undefined" && !remote) {
11727
- location.href = `${base.href}/verify`;
11781
+ location.href = `${root}/verify`;
11728
11782
  return;
11729
11783
  }
11730
11784
  const result = await client.openConnect(element);
@@ -11839,7 +11893,7 @@ ${claims(evidence)}`;
11839
11893
  },
11840
11894
  disconnect(id) {
11841
11895
  if (remote) session = void 0;
11842
- return ask(`/connections/${encodeURIComponent(id)}/disconnect`, {});
11896
+ return ask(routePath("disconnect", id), {});
11843
11897
  },
11844
11898
  /**
11845
11899
  * Says how the holder would have an account listed, or retires it. Names one record
@@ -11847,10 +11901,10 @@ ${claims(evidence)}`;
11847
11901
  */
11848
11902
  mark(id, as2) {
11849
11903
  if (remote) session = void 0;
11850
- return ask(`/connections/${encodeURIComponent(id)}/mark`, { as: as2 });
11904
+ return ask(routePath("mark", id), { as: as2 });
11851
11905
  },
11852
- issueShare: (id) => request(`/connections/${encodeURIComponent(id)}/share`, {}),
11853
- revokeShare: (id) => request(`/connections/${encodeURIComponent(id)}/share-revoke`, {})
11906
+ issueShare: (id) => request(routePath("share", id), {}),
11907
+ revokeShare: (id) => request(routePath("shareRevoke", id), {})
11854
11908
  };
11855
11909
  return client;
11856
11910
  }
@@ -11899,7 +11953,7 @@ ${claims(evidence)}`;
11899
11953
  }
11900
11954
  function validAttestation(attestation) {
11901
11955
  if (!record(attestation)) return false;
11902
- return ["backend", "provider"].includes(String(attestation.by)) && typeof attestation.method === "string" && typeof attestation.confirmedAt === "number" && Number.isFinite(attestation.confirmedAt) && (attestation.expect === void 0 || typeof attestation.expect === "string") && // Rendered as a link later, so only http(s) may ever reach an href.
11956
+ return ["backend", "provider"].includes(String(attestation.by)) && typeof attestation.method === "string" && typeof attestation.confirmedAt === "number" && Number.isFinite(attestation.confirmedAt) && (attestation.expect === void 0 || typeof attestation.expect === "string") && (attestation.dnssec === void 0 || typeof attestation.dnssec === "boolean") && // Rendered as a link later, so only http(s) may ever reach an href.
11903
11957
  (attestation.artifactUrl === void 0 || httpUrl2(attestation.artifactUrl));
11904
11958
  }
11905
11959
  function httpUrl2(value) {
package/dist/version.d.ts CHANGED
@@ -7,4 +7,4 @@
7
7
  * output stays what tsc emitted and nothing has to be substituted into it. A version bump
8
8
  * changes this line with package.json.
9
9
  */
10
- export declare const version = "v0.4.0";
10
+ export declare const version = "v0.5.0";
package/dist/version.js CHANGED
@@ -7,4 +7,4 @@
7
7
  * output stays what tsc emitted and nothing has to be substituted into it. A version bump
8
8
  * changes this line with package.json.
9
9
  */
10
- export const version = 'v0.4.0';
10
+ export const version = 'v0.5.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bkazemi/verily",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Self-hosted account-to-account verification for Node.js",
5
5
  "type": "module",
6
6
  "license": "MIT",