@bkazemi/verily 0.2.0 → 0.4.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/README.md +30 -17
- package/dist/browser/badge.js +16 -5
- package/dist/browser/connect-dialog.d.ts +13 -2
- package/dist/browser/connect-dialog.js +19 -9
- package/dist/browser/evidence-dialog.d.ts +19 -1
- package/dist/browser/evidence-dialog.js +165 -18
- package/dist/browser/index.d.ts +10 -1
- package/dist/browser/index.js +58 -14
- package/dist/browser/logo.d.ts +2 -0
- package/dist/browser/logo.js +2 -0
- package/dist/browser/mark.d.ts +2 -0
- package/dist/browser/mark.js +6 -0
- package/dist/browser/provider-mark.js +5 -3
- package/dist/browser/signed.d.ts +4 -0
- package/dist/browser/signed.js +23 -6
- package/dist/core/index.d.ts +39 -6
- package/dist/core/index.js +23 -0
- package/dist/core/signed.d.ts +20 -5
- package/dist/core/signed.js +5 -2
- package/dist/server/domain.d.ts +51 -0
- package/dist/server/domain.js +285 -0
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +106 -42
- package/dist/server/link.js +1 -16
- package/dist/server/public-fetch.d.ts +10 -0
- package/dist/server/public-fetch.js +15 -0
- package/dist/server/service.d.ts +42 -3
- package/dist/server/service.js +156 -10
- package/dist/site/index.d.ts +2 -1
- package/dist/verily.js +213 -36
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/verily.js
CHANGED
|
@@ -9575,6 +9575,7 @@ var Verily = (() => {
|
|
|
9575
9575
|
__export(browser_exports, {
|
|
9576
9576
|
Refused: () => Refused,
|
|
9577
9577
|
attestationLabel: () => attestationLabel,
|
|
9578
|
+
externalId: () => externalId,
|
|
9578
9579
|
externalLink: () => externalLink,
|
|
9579
9580
|
externalName: () => externalName,
|
|
9580
9581
|
fresh: () => fresh,
|
|
@@ -9583,6 +9584,7 @@ var Verily = (() => {
|
|
|
9583
9584
|
isArtifactProvider: () => isArtifactProvider,
|
|
9584
9585
|
isCodeProvider: () => isCodeProvider,
|
|
9585
9586
|
isRedirectProvider: () => isRedirectProvider,
|
|
9587
|
+
lastProved: () => lastProved,
|
|
9586
9588
|
localSide: () => localSide,
|
|
9587
9589
|
presentConnections: () => presentConnections,
|
|
9588
9590
|
proofTitle: () => proofTitle,
|
|
@@ -9651,7 +9653,7 @@ var Verily = (() => {
|
|
|
9651
9653
|
});
|
|
9652
9654
|
await signatures2[0].verified;
|
|
9653
9655
|
const document2 = JSON.parse(data);
|
|
9654
|
-
return document2?.type === "verily-evidence" && document2.version === 1 && typeof document2.
|
|
9656
|
+
return document2?.type === "verily-evidence" && typeof document2.issuedAt === "number" && (document2.version === 1 || document2.version === 2 && document2.status === "retired" && typeof document2.retiredAt === "number") ? document2 : void 0;
|
|
9655
9657
|
} catch {
|
|
9656
9658
|
continue;
|
|
9657
9659
|
}
|
|
@@ -9677,6 +9679,7 @@ var Verily = (() => {
|
|
|
9677
9679
|
var freshnessMs = 7 * 864e5;
|
|
9678
9680
|
function status(connection, now, freshness = freshnessMs) {
|
|
9679
9681
|
if (connection.revokedAt !== void 0) return "revoked";
|
|
9682
|
+
if (connection.retiredAt !== void 0) return "retired";
|
|
9680
9683
|
if (now >= connection.expiresAt) return "expired";
|
|
9681
9684
|
const main = connection.attestations?.external[0];
|
|
9682
9685
|
if (main && !fresh(main, now, freshness)) return "unconfirmed";
|
|
@@ -9685,8 +9688,13 @@ var Verily = (() => {
|
|
|
9685
9688
|
function fresh(attestation, now, freshness = freshnessMs) {
|
|
9686
9689
|
return !attestation.artifactUrl || attestation.hosted === true || freshness === Infinity || now < attestation.confirmedAt + freshness;
|
|
9687
9690
|
}
|
|
9691
|
+
function lastProved(evidence) {
|
|
9692
|
+
const main = evidence.attestations.external[0];
|
|
9693
|
+
return main.artifactUrl ? main.confirmedAt : evidence.authenticatedAt;
|
|
9694
|
+
}
|
|
9688
9695
|
function statusLabel(evidence, now) {
|
|
9689
9696
|
if (evidence.status === "revoked") return "Revoked";
|
|
9697
|
+
if (evidence.status === "retired") return "Retired";
|
|
9690
9698
|
if (evidence.status === "expired" || evidence.expiresAt <= now) return "Expired";
|
|
9691
9699
|
return evidence.status === "unconfirmed" ? "Unconfirmed" : "Verified";
|
|
9692
9700
|
}
|
|
@@ -9708,10 +9716,15 @@ var Verily = (() => {
|
|
|
9708
9716
|
oauth: `Signed in with ${names.provider}`,
|
|
9709
9717
|
gist: `Published a proof on ${names.provider}`,
|
|
9710
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`,
|
|
9711
9721
|
signature: "Proved with a signature",
|
|
9712
9722
|
code: "Entered a code sent to this address"
|
|
9713
9723
|
}[method];
|
|
9714
9724
|
}
|
|
9725
|
+
function externalId(external) {
|
|
9726
|
+
return external.kind === "mailbox" || external.kind === "domain" ? void 0 : external.id;
|
|
9727
|
+
}
|
|
9715
9728
|
function externalLink(external) {
|
|
9716
9729
|
return external.kind === "mailbox" ? void 0 : external.profileUrl;
|
|
9717
9730
|
}
|
|
@@ -9782,6 +9795,11 @@ var Verily = (() => {
|
|
|
9782
9795
|
["circle", { cx: "8", cy: "8", r: "6.2" }],
|
|
9783
9796
|
["path", { d: "M8 4.6V8h2.6" }]
|
|
9784
9797
|
]);
|
|
9798
|
+
var boxMark = () => statusMark("box", [
|
|
9799
|
+
["path", { d: "M2.6 3.8h10.8v2.6H2.6z" }],
|
|
9800
|
+
["path", { d: "M3.7 6.4v5.8h8.6V6.4" }],
|
|
9801
|
+
["path", { d: "M6.6 9h2.8" }]
|
|
9802
|
+
]);
|
|
9785
9803
|
var dashMark = () => statusMark("dash", [["path", { d: "M4.4 8h7.2" }]]);
|
|
9786
9804
|
|
|
9787
9805
|
// src/browser/provider-mark.ts
|
|
@@ -9870,7 +9888,7 @@ var Verily = (() => {
|
|
|
9870
9888
|
openpgp: key,
|
|
9871
9889
|
email: envelope
|
|
9872
9890
|
};
|
|
9873
|
-
return marks2[provider]?.() ?? (method
|
|
9891
|
+
return marks2[provider]?.() ?? (["backlink", "dns", "wellknown"].includes(method ?? "") ? globe() : void 0);
|
|
9874
9892
|
}
|
|
9875
9893
|
|
|
9876
9894
|
// src/browser/badge.ts
|
|
@@ -9926,7 +9944,9 @@ var Verily = (() => {
|
|
|
9926
9944
|
.peek .via { display: block; margin-top: 6px; font-size: 11px; color: var(--verily-muted, #65726c); }
|
|
9927
9945
|
.provider { display: block; flex-shrink: 0; width: 14px; height: 14px; }
|
|
9928
9946
|
.expired .icon { color: #815a12; background: #fbefce; }
|
|
9929
|
-
.revoked .icon, .message .icon { color: #626d69; background: #edf0ee; }
|
|
9947
|
+
.revoked .icon, .retired .icon, .message .icon { color: #626d69; background: #edf0ee; }
|
|
9948
|
+
/* Nothing ran out and nothing wants attention: the holder chose this, so it is only quiet. */
|
|
9949
|
+
.retired .name { color: var(--verily-muted, #65726c); }
|
|
9930
9950
|
.message { color: var(--verily-muted, #65726c); }
|
|
9931
9951
|
.add { font-weight: 600; }
|
|
9932
9952
|
@media (prefers-reduced-motion: no-preference) {
|
|
@@ -10055,7 +10075,8 @@ var Verily = (() => {
|
|
|
10055
10075
|
} = {}) {
|
|
10056
10076
|
const provider = evidence.providerName;
|
|
10057
10077
|
const current = evidence.status === "verified" && evidence.expiresAt > Date.now();
|
|
10058
|
-
const
|
|
10078
|
+
const retired = evidence.status === "retired";
|
|
10079
|
+
const state = current ? "verified" : retired ? "retired" : evidence.status === "revoked" ? "revoked" : "expired";
|
|
10059
10080
|
const label = statusLabel(evidence, Date.now());
|
|
10060
10081
|
const key2 = renderKey(evidence, current, label, more, linked, rows, peek);
|
|
10061
10082
|
if (intact(element) && shown.get(element) === key2) return null;
|
|
@@ -10064,7 +10085,7 @@ var Verily = (() => {
|
|
|
10064
10085
|
const unnamed = Math.max(more - rows.length, 0);
|
|
10065
10086
|
const named = rows.map((row) => `, ${row.providerName} ${externalName(row.external)}`).join("");
|
|
10066
10087
|
const others = `${named}${unnamed ? ` and ${unnamed} more` : ""}`;
|
|
10067
|
-
paintMark(mark2, current ? "current" : "inactive");
|
|
10088
|
+
paintMark(mark2, current ? "current" : retired ? "pending" : "inactive");
|
|
10068
10089
|
if (linked) {
|
|
10069
10090
|
badge.href = evidence.evidenceUrl;
|
|
10070
10091
|
badge.rel = "noreferrer";
|
|
@@ -10101,7 +10122,7 @@ var Verily = (() => {
|
|
|
10101
10122
|
}
|
|
10102
10123
|
if (!current) {
|
|
10103
10124
|
const icon = span("icon", "");
|
|
10104
|
-
icon.append(state === "expired" ? clockMark() : dashMark());
|
|
10125
|
+
icon.append(retired ? boxMark() : state === "expired" ? clockMark() : dashMark());
|
|
10105
10126
|
icon.setAttribute("aria-hidden", "true");
|
|
10106
10127
|
badge.append(span("label", label), icon);
|
|
10107
10128
|
}
|
|
@@ -10232,6 +10253,7 @@ var Verily = (() => {
|
|
|
10232
10253
|
status: _status,
|
|
10233
10254
|
revokedAt: _revokedAt,
|
|
10234
10255
|
signedUrl: _signedUrl,
|
|
10256
|
+
mark: _mark,
|
|
10235
10257
|
links: _links,
|
|
10236
10258
|
type: _type,
|
|
10237
10259
|
version: _version,
|
|
@@ -10298,11 +10320,23 @@ ${claims(evidence)}`;
|
|
|
10298
10320
|
const document2 = await verifySigned(signed, keys);
|
|
10299
10321
|
if (!document2 || document2.id !== evidence.id || document2.verifierName !== evidence.verifierName || document2.evidenceUrl !== evidence.evidenceUrl || document2.siteName !== evidence.siteName || document2.local.reference !== evidence.local.reference || document2.provider !== evidence.provider || document2.external.id !== evidence.external.id)
|
|
10300
10322
|
return { state: "invalid" };
|
|
10301
|
-
|
|
10323
|
+
if (document2.version === 2 !== (evidence.status === "retired"))
|
|
10324
|
+
return { state: "unchecked", why: "unreadable" };
|
|
10325
|
+
const {
|
|
10326
|
+
type: _type,
|
|
10327
|
+
version: _version,
|
|
10328
|
+
issuedAt: _issuedAt,
|
|
10329
|
+
status: _status,
|
|
10330
|
+
retiredAt: _retiredAt,
|
|
10331
|
+
mark: _mark,
|
|
10332
|
+
...said
|
|
10333
|
+
} = document2;
|
|
10302
10334
|
const record2 = {
|
|
10303
10335
|
...said,
|
|
10304
10336
|
status: evidence.status,
|
|
10305
10337
|
...evidence.revokedAt === void 0 ? {} : { revokedAt: evidence.revokedAt },
|
|
10338
|
+
...document2.version === 2 ? { retiredAt: document2.retiredAt } : {},
|
|
10339
|
+
...evidence.mark === void 0 ? {} : { mark: evidence.mark },
|
|
10306
10340
|
signedUrl: evidence.signedUrl
|
|
10307
10341
|
};
|
|
10308
10342
|
return drawable(record2) ? { state: "valid", keyId: by2, record: record2 } : { state: "unchecked", why: "unreadable" };
|
|
@@ -10336,12 +10370,15 @@ ${claims(evidence)}`;
|
|
|
10336
10370
|
if (evidence.signedUrl === void 0) return evidence;
|
|
10337
10371
|
const key2 = shown2(evidence);
|
|
10338
10372
|
const signed = signedAs.get(key2);
|
|
10339
|
-
if (signed)
|
|
10373
|
+
if (signed) {
|
|
10374
|
+
const { mark: _mark, ...said } = signed;
|
|
10340
10375
|
return {
|
|
10341
|
-
...
|
|
10376
|
+
...said,
|
|
10342
10377
|
status: evidence.status,
|
|
10343
|
-
...evidence.revokedAt === void 0 ? {} : { revokedAt: evidence.revokedAt }
|
|
10378
|
+
...evidence.revokedAt === void 0 ? {} : { revokedAt: evidence.revokedAt },
|
|
10379
|
+
...evidence.mark === void 0 ? {} : { mark: evidence.mark }
|
|
10344
10380
|
};
|
|
10381
|
+
}
|
|
10345
10382
|
return evidence.status === "verified" && failures.has(key2) ? { ...evidence, status: "unconfirmed" } : evidence;
|
|
10346
10383
|
}
|
|
10347
10384
|
function watchSigned(records, changed) {
|
|
@@ -10379,6 +10416,7 @@ ${claims(evidence)}`;
|
|
|
10379
10416
|
var logo = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="${-pad} ${-26 - pad} ${2637 + 2 * pad} ${916 + 2 * pad}" class="logo" role="img" aria-label="Verily"><rect x="${-pad}" y="${-26 - pad}" width="${2637 + 2 * pad}" height="${916 + 2 * pad}" rx="166" fill="#0d1117"/>` + logoPaths.map(({ d: d2, fill }) => `<path d="${d2}" fill="${fill === "currentColor" ? "#ffffff" : fill}"/>`).join("") + "</svg>";
|
|
10380
10417
|
|
|
10381
10418
|
// src/browser/logo.ts
|
|
10419
|
+
var projectUrl = "https://github.com/bkazemi/verily";
|
|
10382
10420
|
function verilyLogo() {
|
|
10383
10421
|
const namespace2 = "http://www.w3.org/2000/svg";
|
|
10384
10422
|
const svg = document.createElementNS(namespace2, "svg");
|
|
@@ -10396,9 +10434,14 @@ ${claims(evidence)}`;
|
|
|
10396
10434
|
}
|
|
10397
10435
|
|
|
10398
10436
|
// src/version.ts
|
|
10399
|
-
var version = "v0.
|
|
10437
|
+
var version = "v0.4.0";
|
|
10400
10438
|
|
|
10401
10439
|
// src/browser/evidence-dialog.ts
|
|
10440
|
+
function stampLink() {
|
|
10441
|
+
const link = outward(node("a"), projectUrl);
|
|
10442
|
+
link.append(verilyLogo());
|
|
10443
|
+
return link;
|
|
10444
|
+
}
|
|
10402
10445
|
var openDialogs = /* @__PURE__ */ new WeakMap();
|
|
10403
10446
|
var styles2 = `
|
|
10404
10447
|
* { box-sizing: border-box; }
|
|
@@ -10431,6 +10474,14 @@ ${claims(evidence)}`;
|
|
|
10431
10474
|
.summary a, .method a, .additional a { font: inherit; }
|
|
10432
10475
|
.reference { margin-top: 2px; }
|
|
10433
10476
|
.method { margin-top: 8px; }
|
|
10477
|
+
/* In the corner the heading leaves empty, apart from everything that was checked. */
|
|
10478
|
+
.listing { position: absolute; top: 12px; right: 14px; padding: 1px 8px; border: 1px solid #e0e6df; border-radius: 999px; color: #6b786f; font-size: 11px; font-weight: 550; }
|
|
10479
|
+
.listing.preferred { border-color: #245f43; color: #245f43; }
|
|
10480
|
+
/* Quiet, as its pill is: the surface and the name step back, and the controls do not. */
|
|
10481
|
+
.account.retired { background: #f6f8f5; }
|
|
10482
|
+
.account.retired > a, .account.retired > strong { color: #6b786f; }
|
|
10483
|
+
.account.retired .mark { opacity: .45; }
|
|
10484
|
+
.group { margin: 20px 0 0; color: #6b786f; font-size: 11px; font-weight: 550; }
|
|
10434
10485
|
.additional { margin-top: 2px; padding-left: 12px; }
|
|
10435
10486
|
.joiner { display: block; width: 20px; height: 20px; margin: 8px auto -4px; color: #90a096; }
|
|
10436
10487
|
dl { margin: 16px 0 0; padding-top: 12px; border-top: 1px solid #e5e9e3; display: grid; grid-template-columns: auto 1fr; gap: 5px 16px; font-size: 11px; }
|
|
@@ -10443,9 +10494,10 @@ ${claims(evidence)}`;
|
|
|
10443
10494
|
.action:disabled { opacity: .6; cursor: progress; }
|
|
10444
10495
|
.action.danger:hover { border-color: #b3261e; background: #fdecea; color: #b3261e; }
|
|
10445
10496
|
.row { display: flex; justify-content: end; gap: 8px; margin-top: 16px; }
|
|
10446
|
-
.account .row { align-items: center; justify-content: start; margin-top: 12px; }
|
|
10497
|
+
.account .row { align-items: center; justify-content: start; flex-wrap: wrap; margin-top: 12px; }
|
|
10447
10498
|
.account .action { padding: 5px 10px; font-size: 12px; }
|
|
10448
|
-
footer { display: flex; align-items: center; justify-content: start; gap: 6px; margin
|
|
10499
|
+
footer { display: flex; align-items: center; justify-content: start; gap: 6px; margin: 20px 0 -8px; color: #9aa9a0; font-size: 11px; }
|
|
10500
|
+
footer a { display: flex; color: inherit; }
|
|
10449
10501
|
.logo { display: block; height: 13px; }
|
|
10450
10502
|
${markStyles}
|
|
10451
10503
|
`;
|
|
@@ -10510,6 +10562,7 @@ ${claims(evidence)}`;
|
|
|
10510
10562
|
card.append(...extra);
|
|
10511
10563
|
return card;
|
|
10512
10564
|
}
|
|
10565
|
+
var retiringNote = "Retiring keeps this record as history. It will no longer read as verified, and who can read it cannot be changed afterwards.";
|
|
10513
10566
|
var removable = (evidence) => evidence.links ?? (evidence.status === "revoked" ? [] : [evidence.id]);
|
|
10514
10567
|
function manageRow(evidence, manage) {
|
|
10515
10568
|
const row = node("div", "", "row");
|
|
@@ -10518,12 +10571,49 @@ ${claims(evidence)}`;
|
|
|
10518
10571
|
control.type = "button";
|
|
10519
10572
|
return control;
|
|
10520
10573
|
};
|
|
10574
|
+
const [named] = removable(evidence);
|
|
10575
|
+
const { mark: mark2 } = manage;
|
|
10576
|
+
const listable = mark2 !== void 0 && named !== void 0 && !["revoked", "retired"].includes(evidence.status);
|
|
10577
|
+
const list = (label, as2) => {
|
|
10578
|
+
const control = act(label);
|
|
10579
|
+
control.onclick = async () => {
|
|
10580
|
+
for (const other of row.children) other.disabled = true;
|
|
10581
|
+
try {
|
|
10582
|
+
await mark2(named, as2);
|
|
10583
|
+
} catch {
|
|
10584
|
+
offer("That did not go through.");
|
|
10585
|
+
}
|
|
10586
|
+
};
|
|
10587
|
+
return control;
|
|
10588
|
+
};
|
|
10521
10589
|
const offer = (note = "") => {
|
|
10522
10590
|
const renew = act("Renew");
|
|
10523
10591
|
const remove = act("Remove", true);
|
|
10524
|
-
renew.onclick = () => manage.
|
|
10592
|
+
renew.onclick = () => manage.renew && evidence.status !== "revoked" ? manage.renew(
|
|
10593
|
+
evidence.id,
|
|
10594
|
+
evidence.provider,
|
|
10595
|
+
evidence.status === "retired" ? evidence.attestations.external[0].method : void 0
|
|
10596
|
+
) : manage.connect(evidence.provider);
|
|
10525
10597
|
remove.onclick = confirm;
|
|
10526
|
-
|
|
10598
|
+
const listing = [];
|
|
10599
|
+
if (listable) {
|
|
10600
|
+
const retire = act("Retire");
|
|
10601
|
+
retire.onclick = retiring;
|
|
10602
|
+
listing.push(
|
|
10603
|
+
...evidence.mark === "preferred" ? [] : [list("Mark as preferred", "preferred")],
|
|
10604
|
+
...evidence.mark === "unused" ? [] : [list("Mark as unused", "unused")],
|
|
10605
|
+
...evidence.mark === void 0 ? [] : [list("Mark as current", "current")],
|
|
10606
|
+
retire
|
|
10607
|
+
);
|
|
10608
|
+
}
|
|
10609
|
+
row.replaceChildren(renew, ...listing, remove, ...note ? [node("span", note, "muted")] : []);
|
|
10610
|
+
};
|
|
10611
|
+
const retiring = () => {
|
|
10612
|
+
const cancel = act("Cancel");
|
|
10613
|
+
const sure = list("Retire", "retired");
|
|
10614
|
+
cancel.onclick = () => offer();
|
|
10615
|
+
row.replaceChildren(node("span", retiringNote, "muted"), cancel, sure);
|
|
10616
|
+
cancel.focus();
|
|
10527
10617
|
};
|
|
10528
10618
|
const confirm = () => {
|
|
10529
10619
|
const cancel = act("Cancel");
|
|
@@ -10626,11 +10716,15 @@ ${claims(evidence)}`;
|
|
|
10626
10716
|
} else attribution.append(document.createTextNode(evidence.verifierName));
|
|
10627
10717
|
if (evidence.signedUrl) attribution.append(signedMark(evidence, later));
|
|
10628
10718
|
copy.append(node("div", status2, "state"), attribution);
|
|
10629
|
-
|
|
10719
|
+
const retired = evidence.status === "retired";
|
|
10720
|
+
summary.append(verificationMark(current ? "current" : retired ? "pending" : "inactive"), copy);
|
|
10630
10721
|
const dates = node("dl");
|
|
10631
10722
|
const dateRows = [["Approved", evidence.approvedAt]];
|
|
10632
10723
|
if (evidence.status === "revoked") {
|
|
10633
10724
|
if (evidence.revokedAt !== void 0) dateRows.push(["Revoked on", evidence.revokedAt]);
|
|
10725
|
+
} else if (retired) {
|
|
10726
|
+
dateRows.push(["Last verified", lastProved(evidence)]);
|
|
10727
|
+
if (evidence.retiredAt !== void 0) dateRows.push(["Retired", evidence.retiredAt]);
|
|
10634
10728
|
} else {
|
|
10635
10729
|
dateRows.push([
|
|
10636
10730
|
evidence.expiresAt > Date.now() ? "Valid until" : "Expired on",
|
|
@@ -10638,7 +10732,7 @@ ${claims(evidence)}`;
|
|
|
10638
10732
|
]);
|
|
10639
10733
|
}
|
|
10640
10734
|
const main = evidence.attestations.external[0];
|
|
10641
|
-
if (main.artifactUrl) dateRows.push(["Last checked", main.confirmedAt]);
|
|
10735
|
+
if (main.artifactUrl && !retired) dateRows.push(["Last checked", main.confirmedAt]);
|
|
10642
10736
|
for (const [label, time] of dateRows) {
|
|
10643
10737
|
dates.append(node("dt", label), node("dd", moment(time)));
|
|
10644
10738
|
}
|
|
@@ -10649,27 +10743,30 @@ ${claims(evidence)}`;
|
|
|
10649
10743
|
// would print it twice here, since this heading writes it either way.
|
|
10650
10744
|
logo2 ? [logo2, document.createTextNode(provider)] : [document.createTextNode(provider)],
|
|
10651
10745
|
externalName(evidence.external),
|
|
10652
|
-
// A mailbox's address is its name already, so there is no second identifier.
|
|
10653
|
-
evidence.external
|
|
10746
|
+
// A mailbox's address or a domain is its name already, so there is no second identifier.
|
|
10747
|
+
externalId(evidence.external),
|
|
10654
10748
|
externalLink(evidence.external),
|
|
10655
10749
|
// Status first, then how it was shown, then when. The proof explains the state
|
|
10656
10750
|
// above it, so it cannot sit before that state has been given.
|
|
10657
10751
|
summary,
|
|
10658
10752
|
...attestationNote(main, names),
|
|
10659
10753
|
...evidence.attestations.external.slice(1).flatMap((a2) => attestationNote(a2, names, true)),
|
|
10754
|
+
...evidence.status === "revoked" || retired ? [] : evidence.mark === "preferred" ? [node("div", "Preferred", "listing preferred")] : evidence.mark === "unused" ? [node("div", "No longer used", "listing")] : [],
|
|
10660
10755
|
dates,
|
|
10661
10756
|
...manage && removable(evidence).length ? [manageRow(evidence, manage)] : []
|
|
10662
10757
|
);
|
|
10758
|
+
const surface = retired ? "account retired" : "account";
|
|
10759
|
+
card.className = surface;
|
|
10663
10760
|
if (evidence.signedUrl) {
|
|
10664
10761
|
const veiled = [...card.children];
|
|
10665
10762
|
const checking = node("div", "", "checking");
|
|
10666
10763
|
checking.setAttribute("role", "status");
|
|
10667
10764
|
checking.append(node("span", "", "spinner"), document.createTextNode("Checking signature\u2026"));
|
|
10668
|
-
card.className =
|
|
10765
|
+
card.className = `${surface} veiled`;
|
|
10669
10766
|
for (const part of veiled) part.inert = true;
|
|
10670
10767
|
card.append(checking);
|
|
10671
10768
|
void signatures(evidence).then(() => {
|
|
10672
|
-
card.className =
|
|
10769
|
+
card.className = surface;
|
|
10673
10770
|
for (const part of veiled) part.inert = false;
|
|
10674
10771
|
checking.remove();
|
|
10675
10772
|
});
|
|
@@ -10700,11 +10797,16 @@ ${claims(evidence)}`;
|
|
|
10700
10797
|
provider: first.providerName
|
|
10701
10798
|
})
|
|
10702
10799
|
);
|
|
10800
|
+
const retired = records.filter((record2) => record2.status === "retired");
|
|
10703
10801
|
content.replaceChildren(
|
|
10704
10802
|
localCard,
|
|
10705
10803
|
linkMark(),
|
|
10706
|
-
...records.map((record2) => externalCard(record2, manage, later)),
|
|
10804
|
+
...records.filter((record2) => record2.status !== "retired").map((record2) => externalCard(record2, manage, later)),
|
|
10707
10805
|
...manage ? [addRow(manage)] : [],
|
|
10806
|
+
...retired.length ? [
|
|
10807
|
+
node("h3", "Retired accounts", "group"),
|
|
10808
|
+
...retired.map((record2) => externalCard(record2, manage, later))
|
|
10809
|
+
] : [],
|
|
10708
10810
|
// Nothing below the cards may name a provider. Approval, method and dates belong to
|
|
10709
10811
|
// the card they came from, and a second provider on this subject gets its own card.
|
|
10710
10812
|
node(
|
|
@@ -10736,11 +10838,30 @@ ${claims(evidence)}`;
|
|
|
10736
10838
|
close.type = "button";
|
|
10737
10839
|
close.setAttribute("aria-label", "Close verification details");
|
|
10738
10840
|
content.setAttribute("aria-live", "polite");
|
|
10739
|
-
stamp.append(
|
|
10841
|
+
stamp.append(stampLink(), node("span", version));
|
|
10740
10842
|
header.append(heading, close);
|
|
10741
10843
|
dialog.append(header, content, stamp);
|
|
10742
10844
|
const removed = /* @__PURE__ */ new Map();
|
|
10845
|
+
const listed = [];
|
|
10846
|
+
const listing = (record2) => JSON.stringify([record2.status, record2.mark, record2.retiredAt, record2.approvedAt]);
|
|
10847
|
+
const listings = (given) => new Map([given].flat().map((record2) => [record2.id, listing(record2)]));
|
|
10743
10848
|
let held;
|
|
10849
|
+
const relisted = (evidence) => {
|
|
10850
|
+
let record2 = evidence;
|
|
10851
|
+
for (const { ids, as: as2, at: at2 } of listed) {
|
|
10852
|
+
if (["revoked", "retired"].includes(record2.status)) break;
|
|
10853
|
+
if (!ids.includes(record2.id)) {
|
|
10854
|
+
if (as2 === "preferred" && record2.mark === "preferred")
|
|
10855
|
+
record2 = { ...record2, mark: void 0 };
|
|
10856
|
+
continue;
|
|
10857
|
+
}
|
|
10858
|
+
record2 = as2 === "retired" ? (
|
|
10859
|
+
// Its signed form is another document now, to be read with the records to come.
|
|
10860
|
+
{ ...record2, status: "retired", retiredAt: at2, mark: void 0, signedUrl: void 0 }
|
|
10861
|
+
) : { ...record2, mark: as2 === "current" ? void 0 : as2 };
|
|
10862
|
+
}
|
|
10863
|
+
return record2;
|
|
10864
|
+
};
|
|
10744
10865
|
const actions = manage && {
|
|
10745
10866
|
// The other dialog opens over this one before this one goes, so the page behind is
|
|
10746
10867
|
// never uncovered between the two.
|
|
@@ -10748,11 +10869,32 @@ ${claims(evidence)}`;
|
|
|
10748
10869
|
manage.connect(provider);
|
|
10749
10870
|
dialog.close();
|
|
10750
10871
|
},
|
|
10872
|
+
...manage.renew ? {
|
|
10873
|
+
renew(id, provider, method) {
|
|
10874
|
+
manage.renew(id, provider, method);
|
|
10875
|
+
dialog.close();
|
|
10876
|
+
}
|
|
10877
|
+
} : {},
|
|
10751
10878
|
async remove(ids) {
|
|
10752
10879
|
await manage.remove(ids);
|
|
10753
10880
|
for (const id of ids) removed.set(id, Date.now());
|
|
10754
10881
|
if (held && dialog.open) draw(held);
|
|
10755
|
-
}
|
|
10882
|
+
},
|
|
10883
|
+
...manage.mark ? {
|
|
10884
|
+
async mark(id, as2) {
|
|
10885
|
+
await manage.mark(id, as2);
|
|
10886
|
+
const account = arrange2([held ?? []].flat()).find(
|
|
10887
|
+
(card) => removable(card).includes(id)
|
|
10888
|
+
);
|
|
10889
|
+
listed.push({
|
|
10890
|
+
ids: account ? removable(account) : [id],
|
|
10891
|
+
as: as2,
|
|
10892
|
+
at: Date.now(),
|
|
10893
|
+
before: listings(held ?? [])
|
|
10894
|
+
});
|
|
10895
|
+
if (held && dialog.open) draw(held);
|
|
10896
|
+
}
|
|
10897
|
+
} : {}
|
|
10756
10898
|
};
|
|
10757
10899
|
root.append(dialog);
|
|
10758
10900
|
document.body.append(host);
|
|
@@ -10763,9 +10905,13 @@ ${claims(evidence)}`;
|
|
|
10763
10905
|
const retries = /* @__PURE__ */ new Set();
|
|
10764
10906
|
const draw = (given) => {
|
|
10765
10907
|
held = given;
|
|
10908
|
+
const now = listings(given);
|
|
10909
|
+
for (const change of [...listed])
|
|
10910
|
+
if (change.ids.some((id) => now.get(id) !== change.before.get(id)))
|
|
10911
|
+
listed.splice(listed.indexOf(change), 1);
|
|
10766
10912
|
const records = arrange2(
|
|
10767
10913
|
[given].flat().map(
|
|
10768
|
-
(e2) => removed.has(e2.id) && e2.status !== "revoked" ? { ...e2, status: "revoked", revokedAt: removed.get(e2.id) } : standing(e2)
|
|
10914
|
+
(e2) => removed.has(e2.id) && e2.status !== "revoked" ? { ...e2, status: "revoked", revokedAt: removed.get(e2.id) } : relisted(standing(e2))
|
|
10769
10915
|
)
|
|
10770
10916
|
);
|
|
10771
10917
|
const key2 = JSON.stringify(records.map((e2) => [e2, statusLabel(e2, Date.now())]));
|
|
@@ -10906,7 +11052,7 @@ ${claims(evidence)}`;
|
|
|
10906
11052
|
return element;
|
|
10907
11053
|
}
|
|
10908
11054
|
var openDialogs2 = /* @__PURE__ */ new WeakMap();
|
|
10909
|
-
function openConnectDialog(opener, api, back, provider) {
|
|
11055
|
+
function openConnectDialog(opener, api, back, provider, renew) {
|
|
10910
11056
|
const existing = openDialogs2.get(opener);
|
|
10911
11057
|
if (existing?.open) {
|
|
10912
11058
|
existing.focus();
|
|
@@ -10928,7 +11074,7 @@ ${claims(evidence)}`;
|
|
|
10928
11074
|
close.type = "button";
|
|
10929
11075
|
close.setAttribute("aria-label", "Close");
|
|
10930
11076
|
content.setAttribute("aria-live", "polite");
|
|
10931
|
-
stamp.append(
|
|
11077
|
+
stamp.append(stampLink(), node("span", version));
|
|
10932
11078
|
header.append(heading, close);
|
|
10933
11079
|
dialog.append(header, content, stamp);
|
|
10934
11080
|
root.append(dialog);
|
|
@@ -11006,7 +11152,11 @@ ${claims(evidence)}`;
|
|
|
11006
11152
|
return;
|
|
11007
11153
|
}
|
|
11008
11154
|
if (!current(asked)) return;
|
|
11009
|
-
const
|
|
11155
|
+
const renewing = methods.methods.filter(
|
|
11156
|
+
(m2) => m2.provider === provider && (renew?.method === void 0 || m2.method === renew.method)
|
|
11157
|
+
);
|
|
11158
|
+
if (renew && !renewing.length) renew = void 0;
|
|
11159
|
+
const all = renew ? renewing : methods.methods;
|
|
11010
11160
|
if (group !== void 0 && !all.some((m2) => m2.provider === group)) group = void 0;
|
|
11011
11161
|
const count = (provider2) => all.filter((m2) => m2.provider === provider2).length;
|
|
11012
11162
|
const list = node("div", "", "choices");
|
|
@@ -11035,7 +11185,7 @@ ${claims(evidence)}`;
|
|
|
11035
11185
|
return;
|
|
11036
11186
|
}
|
|
11037
11187
|
}
|
|
11038
|
-
void busy(control, () => api.start(choice.provider, choice.method), show);
|
|
11188
|
+
void busy(control, () => api.start(choice.provider, choice.method, renew?.id), show);
|
|
11039
11189
|
};
|
|
11040
11190
|
list.append(control);
|
|
11041
11191
|
}
|
|
@@ -11049,7 +11199,7 @@ ${claims(evidence)}`;
|
|
|
11049
11199
|
),
|
|
11050
11200
|
list
|
|
11051
11201
|
];
|
|
11052
|
-
if (group !== void 0) {
|
|
11202
|
+
if (group !== void 0 && !renew) {
|
|
11053
11203
|
const back2 = button("\u2039 All options");
|
|
11054
11204
|
back2.onclick = () => {
|
|
11055
11205
|
group = void 0;
|
|
@@ -11209,7 +11359,7 @@ ${claims(evidence)}`;
|
|
|
11209
11359
|
const external = accountCard(
|
|
11210
11360
|
logo2 ? [logo2, document.createTextNode(flow.provider.name)] : [document.createTextNode(flow.provider.name)],
|
|
11211
11361
|
externalName(flow.external),
|
|
11212
|
-
flow.external
|
|
11362
|
+
externalId(flow.external),
|
|
11213
11363
|
externalLink(flow.external)
|
|
11214
11364
|
);
|
|
11215
11365
|
const parts = [subjectCard(flow.local), linkMark(), external];
|
|
@@ -11399,7 +11549,11 @@ ${claims(evidence)}`;
|
|
|
11399
11549
|
// Every record the card speaks for, so its signature mark answers for all of them.
|
|
11400
11550
|
sources: verified.length ? verified : [base]
|
|
11401
11551
|
};
|
|
11402
|
-
}).sort((a2, b2) => a2.connectedAt - b2.connectedAt);
|
|
11552
|
+
}).sort((a2, b2) => place2(a2) - place2(b2) || a2.connectedAt - b2.connectedAt);
|
|
11553
|
+
}
|
|
11554
|
+
function place2(account) {
|
|
11555
|
+
if (account.status === "retired") return 3;
|
|
11556
|
+
return account.mark === "preferred" ? 0 : account.mark === "unused" ? 2 : 1;
|
|
11403
11557
|
}
|
|
11404
11558
|
function presentGroup(element, records, load2) {
|
|
11405
11559
|
const ordered = accounts(records.map(standing));
|
|
@@ -11506,7 +11660,12 @@ ${claims(evidence)}`;
|
|
|
11506
11660
|
if (typeof data.local.profileUrl === "string") safeUrl(data.local.profileUrl);
|
|
11507
11661
|
return data;
|
|
11508
11662
|
},
|
|
11509
|
-
start: async (provider, method) => flowView(
|
|
11663
|
+
start: async (provider, method, renew) => flowView(
|
|
11664
|
+
await ask(
|
|
11665
|
+
"/sessions",
|
|
11666
|
+
renew ? { kind: "renew", connectionId: renew, provider, method } : { kind: "connect", provider, method }
|
|
11667
|
+
)
|
|
11668
|
+
),
|
|
11510
11669
|
read: async (id) => flowView(await ask(`/flows/${encodeURIComponent(id)}?format=json`, void 0, id)),
|
|
11511
11670
|
submit: async (id, artifact) => flowView(await ask(`/flows/${encodeURIComponent(id)}/submit`, { artifact }, id)),
|
|
11512
11671
|
async approve(id, visibility, cancel) {
|
|
@@ -11550,11 +11709,11 @@ ${claims(evidence)}`;
|
|
|
11550
11709
|
* Opens the connect dialog over the current page. Resolves when it closes, with how
|
|
11551
11710
|
* the last attempt in it ended. Call from a click: a sign-in method opens a window.
|
|
11552
11711
|
*/
|
|
11553
|
-
openConnect(opener = document.body, back, provider) {
|
|
11712
|
+
openConnect(opener = document.body, back, provider, renew) {
|
|
11554
11713
|
if (remote && !handoffUrl)
|
|
11555
11714
|
throw new Error("A backend on another origin requires a handoff URL");
|
|
11556
11715
|
session = void 0;
|
|
11557
|
-
return openConnectDialog(opener, flows, back, provider);
|
|
11716
|
+
return openConnectDialog(opener, flows, back, provider, renew);
|
|
11558
11717
|
},
|
|
11559
11718
|
/**
|
|
11560
11719
|
* Draws the pill that opens the connect dialog. The host receives a `verily-result`
|
|
@@ -11682,6 +11841,14 @@ ${claims(evidence)}`;
|
|
|
11682
11841
|
if (remote) session = void 0;
|
|
11683
11842
|
return ask(`/connections/${encodeURIComponent(id)}/disconnect`, {});
|
|
11684
11843
|
},
|
|
11844
|
+
/**
|
|
11845
|
+
* Says how the holder would have an account listed, or retires it. Names one record
|
|
11846
|
+
* and acts on the account: every record of it the holder has.
|
|
11847
|
+
*/
|
|
11848
|
+
mark(id, as2) {
|
|
11849
|
+
if (remote) session = void 0;
|
|
11850
|
+
return ask(`/connections/${encodeURIComponent(id)}/mark`, { as: as2 });
|
|
11851
|
+
},
|
|
11685
11852
|
issueShare: (id) => request(`/connections/${encodeURIComponent(id)}/share`, {}),
|
|
11686
11853
|
revokeShare: (id) => request(`/connections/${encodeURIComponent(id)}/share-revoke`, {})
|
|
11687
11854
|
};
|
|
@@ -11753,7 +11920,8 @@ ${claims(evidence)}`;
|
|
|
11753
11920
|
(k2) => typeof value.external[k2] === "string"
|
|
11754
11921
|
) && (value.local.profileUrl === void 0 || typeof value.local.profileUrl === "string") && // A signed record lives beside the record it was made from and nowhere else, since the
|
|
11755
11922
|
// keys it is checked against are read from where the record lives.
|
|
11756
|
-
(value.signedUrl === void 0 || value.signedUrl === `${value.evidenceUrl}?format=signed`) && validAttestations(value.attestations) && (value.local.kind === void 0 || typeof value.local.kind === "string") && (value.external.kind === void 0 || ["account", "key", "page", "mailbox"].includes(String(value.external.kind))) && (value.revokedAt === void 0 || typeof value.revokedAt === "number" && Number.isFinite(value.revokedAt)) && ["verified", "unconfirmed", "expired", "revoked"].includes(String(value.status)) &&
|
|
11923
|
+
(value.signedUrl === void 0 || value.signedUrl === `${value.evidenceUrl}?format=signed`) && validAttestations(value.attestations) && (value.local.kind === void 0 || typeof value.local.kind === "string") && (value.external.kind === void 0 || ["account", "key", "page", "mailbox", "domain"].includes(String(value.external.kind))) && (value.revokedAt === void 0 || typeof value.revokedAt === "number" && Number.isFinite(value.revokedAt)) && ["verified", "unconfirmed", "expired", "retired", "revoked"].includes(String(value.status)) && // A retired record stands on its dates, so one that does not say when is not one.
|
|
11924
|
+
(value.status === "retired" ? typeof value.retiredAt === "number" && Number.isFinite(value.retiredAt) : value.retiredAt === void 0) && (value.mark === void 0 || ["preferred", "unused"].includes(String(value.mark))) && ["public", "unlisted"].includes(String(value.visibility)) && (value.connectedAt === void 0 || typeof value.connectedAt === "number" && Number.isFinite(value.connectedAt)) && ["authenticatedAt", "approvedAt", "expiresAt"].every(
|
|
11757
11925
|
(k2) => typeof value[k2] === "number" && Number.isFinite(value[k2])
|
|
11758
11926
|
);
|
|
11759
11927
|
}
|
|
@@ -11862,6 +12030,11 @@ ${claims(evidence)}`;
|
|
|
11862
12030
|
if (result.outcome === "complete") changed(result);
|
|
11863
12031
|
});
|
|
11864
12032
|
},
|
|
12033
|
+
renew: (id, provider, method) => {
|
|
12034
|
+
void client.openConnect(this, () => details(this), provider, { id, method }).then((result) => {
|
|
12035
|
+
if (result.outcome === "complete") changed(result);
|
|
12036
|
+
});
|
|
12037
|
+
},
|
|
11865
12038
|
// One at a time, each told as it goes: if a later one fails, the host still
|
|
11866
12039
|
// hears of those that went and reads its records again.
|
|
11867
12040
|
remove: async (ids2) => {
|
|
@@ -11869,6 +12042,10 @@ ${claims(evidence)}`;
|
|
|
11869
12042
|
await client.disconnect(id);
|
|
11870
12043
|
changed({ outcome: "removed", connectionId: id });
|
|
11871
12044
|
}
|
|
12045
|
+
},
|
|
12046
|
+
mark: async (id, as2) => {
|
|
12047
|
+
await client.mark(id, as2);
|
|
12048
|
+
changed({ outcome: "marked", connectionId: id, as: as2 });
|
|
11872
12049
|
}
|
|
11873
12050
|
});
|
|
11874
12051
|
} else managers.delete(this);
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED