@pidgeon-ai/cli 1.36.1 → 1.38.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/{chunk-W5VS5RM7.js → chunk-UBA2RP6N.js} +257 -1
- package/dist/{chunk-W5VS5RM7.js.map → chunk-UBA2RP6N.js.map} +1 -1
- package/dist/{chunk-FA77SSPH.js → chunk-ZDJG3Z7B.js} +305 -17
- package/dist/chunk-ZDJG3Z7B.js.map +1 -0
- package/dist/cli.js +2 -2
- package/dist/commands.gen.js +1 -1
- package/dist/index.js +2 -2
- package/package.json +2 -2
- package/dist/chunk-FA77SSPH.js.map +0 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
COMMANDS,
|
|
4
4
|
__export
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-UBA2RP6N.js";
|
|
6
6
|
|
|
7
7
|
// ../sdk/dist/index.js
|
|
8
8
|
var dist_exports = {};
|
|
@@ -67,6 +67,14 @@ __export(dist_exports, {
|
|
|
67
67
|
eventsSocket: () => eventsSocket,
|
|
68
68
|
eventsStream: () => eventsStream,
|
|
69
69
|
exportMail: () => exportMail,
|
|
70
|
+
grantsCreate: () => grantsCreate,
|
|
71
|
+
grantsGet: () => grantsGet,
|
|
72
|
+
grantsList: () => grantsList,
|
|
73
|
+
grantsRevoke: () => grantsRevoke,
|
|
74
|
+
grantsStatus: () => grantsStatus,
|
|
75
|
+
grantsTemplatesCreate: () => grantsTemplatesCreate,
|
|
76
|
+
grantsTemplatesDelete: () => grantsTemplatesDelete,
|
|
77
|
+
grantsTemplatesList: () => grantsTemplatesList,
|
|
70
78
|
identitiesAccessCreate: () => identitiesAccessCreate,
|
|
71
79
|
identitiesAccessDelete: () => identitiesAccessDelete,
|
|
72
80
|
identitiesAccessGet: () => identitiesAccessGet,
|
|
@@ -1025,6 +1033,10 @@ var logMonitorsDelete = (options) => (options.client ?? client).delete({
|
|
|
1025
1033
|
url: "/log/monitors/{id}",
|
|
1026
1034
|
...options
|
|
1027
1035
|
});
|
|
1036
|
+
var grantsStatus = (options) => (options.client ?? client).get({
|
|
1037
|
+
url: "/grants/{id}/status",
|
|
1038
|
+
...options
|
|
1039
|
+
});
|
|
1028
1040
|
var agentConnect = (options) => (options.client ?? client).post({
|
|
1029
1041
|
url: "/agent/connect",
|
|
1030
1042
|
...options,
|
|
@@ -1201,6 +1213,49 @@ var labelsUpdate = (options) => (options.client ?? client).patch({
|
|
|
1201
1213
|
...options.headers
|
|
1202
1214
|
}
|
|
1203
1215
|
});
|
|
1216
|
+
var grantsTemplatesList = (options) => (options?.client ?? client).get({
|
|
1217
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1218
|
+
url: "/grant-templates",
|
|
1219
|
+
...options
|
|
1220
|
+
});
|
|
1221
|
+
var grantsTemplatesCreate = (options) => (options.client ?? client).post({
|
|
1222
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1223
|
+
url: "/grant-templates",
|
|
1224
|
+
...options,
|
|
1225
|
+
headers: {
|
|
1226
|
+
"Content-Type": "application/json",
|
|
1227
|
+
...options.headers
|
|
1228
|
+
}
|
|
1229
|
+
});
|
|
1230
|
+
var grantsTemplatesDelete = (options) => (options.client ?? client).delete({
|
|
1231
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1232
|
+
url: "/grant-templates/{id}",
|
|
1233
|
+
...options
|
|
1234
|
+
});
|
|
1235
|
+
var grantsList = (options) => (options.client ?? client).get({
|
|
1236
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1237
|
+
url: "/grants",
|
|
1238
|
+
...options
|
|
1239
|
+
});
|
|
1240
|
+
var grantsCreate = (options) => (options.client ?? client).post({
|
|
1241
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1242
|
+
url: "/grants",
|
|
1243
|
+
...options,
|
|
1244
|
+
headers: {
|
|
1245
|
+
"Content-Type": "application/json",
|
|
1246
|
+
...options.headers
|
|
1247
|
+
}
|
|
1248
|
+
});
|
|
1249
|
+
var grantsRevoke = (options) => (options.client ?? client).delete({
|
|
1250
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1251
|
+
url: "/grants/{id}",
|
|
1252
|
+
...options
|
|
1253
|
+
});
|
|
1254
|
+
var grantsGet = (options) => (options.client ?? client).get({
|
|
1255
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
1256
|
+
url: "/grants/{id}",
|
|
1257
|
+
...options
|
|
1258
|
+
});
|
|
1204
1259
|
var contactsList = (options) => (options?.client ?? client).get({
|
|
1205
1260
|
security: [{ scheme: "bearer", type: "http" }],
|
|
1206
1261
|
url: "/contacts",
|
|
@@ -1972,7 +2027,7 @@ function sleep(ms, signal) {
|
|
|
1972
2027
|
});
|
|
1973
2028
|
}
|
|
1974
2029
|
|
|
1975
|
-
// ../id/dist/chunk-
|
|
2030
|
+
// ../id/dist/chunk-C5J6V6N2.js
|
|
1976
2031
|
import { createHash } from "crypto";
|
|
1977
2032
|
import { chmod, mkdir, readFile, readdir, writeFile } from "fs/promises";
|
|
1978
2033
|
import { homedir } from "os";
|
|
@@ -2414,7 +2469,8 @@ async function signRequest(identity, input) {
|
|
|
2414
2469
|
}
|
|
2415
2470
|
const added = {
|
|
2416
2471
|
"signature-agent": quote(`https://post.${identity.domain}`),
|
|
2417
|
-
...agent ? { from: agent } : {}
|
|
2472
|
+
...agent ? { from: agent } : {},
|
|
2473
|
+
...input.grants?.length ? { "post-grant": input.grants.map((jws) => jws.replace(/\s+/g, "")).join(", ") } : {}
|
|
2418
2474
|
};
|
|
2419
2475
|
const body = input.body === void 0 || input.body === null ? null : bytesOf(input.body);
|
|
2420
2476
|
if (body && body.length > 0) added["content-digest"] = contentDigest(body);
|
|
@@ -2425,6 +2481,7 @@ async function signRequest(identity, input) {
|
|
|
2425
2481
|
...url.search ? [["@query", url.search]] : [],
|
|
2426
2482
|
["signature-agent", added["signature-agent"]],
|
|
2427
2483
|
...added.from ? [["from", added.from]] : [],
|
|
2484
|
+
...added["post-grant"] ? [["post-grant", added["post-grant"]]] : [],
|
|
2428
2485
|
...added["content-digest"] ? [["content-digest", added["content-digest"]]] : []
|
|
2429
2486
|
];
|
|
2430
2487
|
const params = `(${values.map(([name]) => quote(name)).join(" ")});created=${created};expires=${expires};keyid=${quote(identity.kid)};alg="ed25519";nonce=${quote(randomBytes(32).toString("base64"))};tag=${quote(input.tag ?? TAG)}`;
|
|
@@ -2468,15 +2525,15 @@ var IdClient = class {
|
|
|
2468
2525
|
await signRequest(this.identity, { method, url, headers, body: text, tag: ISSUANCE_TAG })
|
|
2469
2526
|
);
|
|
2470
2527
|
const response = await this.fetcher(url, { method, headers, body: text ?? void 0 });
|
|
2471
|
-
const
|
|
2472
|
-
if (!response.ok || !
|
|
2528
|
+
const json2 = await response.json().catch(() => null);
|
|
2529
|
+
if (!response.ok || !json2 || json2.data === void 0) {
|
|
2473
2530
|
throw new IdApiError(
|
|
2474
2531
|
response.status,
|
|
2475
|
-
|
|
2476
|
-
|
|
2532
|
+
json2?.error?.code,
|
|
2533
|
+
json2?.error?.message ?? `Pidgeon answered ${response.status}.`
|
|
2477
2534
|
);
|
|
2478
2535
|
}
|
|
2479
|
-
return
|
|
2536
|
+
return json2.data;
|
|
2480
2537
|
}
|
|
2481
2538
|
/** Claim the domain with this key. Idempotent: a second call returns the same records. */
|
|
2482
2539
|
claim() {
|
|
@@ -2498,6 +2555,20 @@ var IdClient = class {
|
|
|
2498
2555
|
revoke(name) {
|
|
2499
2556
|
return this.call("DELETE", `/agents/${encodeURIComponent(name)}`);
|
|
2500
2557
|
}
|
|
2558
|
+
/**
|
|
2559
|
+
* The domain grants one of its own agents, at once: what it may do, for
|
|
2560
|
+
* which customer, account or order, where, until when (at most 90 days).
|
|
2561
|
+
*/
|
|
2562
|
+
grant(input) {
|
|
2563
|
+
return this.call("POST", "/grants", input);
|
|
2564
|
+
}
|
|
2565
|
+
/** Every token Sign in with Pidgeon issued `name`, taken back; its card and grants stand. */
|
|
2566
|
+
revokeSignIns(name) {
|
|
2567
|
+
return this.call("DELETE", `/agents/${encodeURIComponent(name)}/sign-ins`);
|
|
2568
|
+
}
|
|
2569
|
+
revokeGrant(id) {
|
|
2570
|
+
return this.call("DELETE", `/grants/${encodeURIComponent(id)}`);
|
|
2571
|
+
}
|
|
2501
2572
|
/**
|
|
2502
2573
|
* Publish `next` as the domain's key, signed by the current one. `proof`
|
|
2503
2574
|
* is `next`'s own signature over the rotation, so nobody can rotate a
|
|
@@ -2517,6 +2588,136 @@ ${domain}
|
|
|
2517
2588
|
${from}
|
|
2518
2589
|
${to}`;
|
|
2519
2590
|
}
|
|
2591
|
+
var TOKEN_EXCHANGE = "urn:ietf:params:oauth:grant-type:token-exchange";
|
|
2592
|
+
var JWT_BEARER = "urn:ietf:params:oauth:grant-type:jwt-bearer";
|
|
2593
|
+
var TOKEN_TYPE_JWT = "urn:ietf:params:oauth:token-type:jwt";
|
|
2594
|
+
var SignInError = class extends Error {
|
|
2595
|
+
constructor(step, status, code, message) {
|
|
2596
|
+
super(message);
|
|
2597
|
+
this.step = step;
|
|
2598
|
+
this.status = status;
|
|
2599
|
+
this.code = code;
|
|
2600
|
+
}
|
|
2601
|
+
step;
|
|
2602
|
+
status;
|
|
2603
|
+
code;
|
|
2604
|
+
};
|
|
2605
|
+
async function json(response) {
|
|
2606
|
+
return await response.json().catch(() => null) ?? {};
|
|
2607
|
+
}
|
|
2608
|
+
function form(values) {
|
|
2609
|
+
return new URLSearchParams(values).toString();
|
|
2610
|
+
}
|
|
2611
|
+
async function siteMetadata(site, fetcher = fetch) {
|
|
2612
|
+
const response = await fetcher(site, { headers: { accept: "application/json" } });
|
|
2613
|
+
const body = await json(response);
|
|
2614
|
+
if (!response.ok || typeof body.issuer !== "string" || typeof body.client_id !== "string") {
|
|
2615
|
+
throw new SignInError(
|
|
2616
|
+
"site",
|
|
2617
|
+
response.status,
|
|
2618
|
+
void 0,
|
|
2619
|
+
`${site} does not offer Sign in with Pidgeon.`
|
|
2620
|
+
);
|
|
2621
|
+
}
|
|
2622
|
+
return { issuer: body.issuer, client_id: body.client_id, token_endpoint: site };
|
|
2623
|
+
}
|
|
2624
|
+
async function fetchCard(agent, fetcher = fetch, postHost = (domain) => `https://post.${domain}`) {
|
|
2625
|
+
const domain = agent.split("@")[1] ?? "";
|
|
2626
|
+
const response = await fetcher(
|
|
2627
|
+
`${postHost(domain)}/.well-known/post/card?address=${encodeURIComponent(agent)}`
|
|
2628
|
+
);
|
|
2629
|
+
const body = await json(response);
|
|
2630
|
+
if (!response.ok || typeof body.jws !== "string") {
|
|
2631
|
+
throw new SignInError(
|
|
2632
|
+
"card",
|
|
2633
|
+
response.status,
|
|
2634
|
+
void 0,
|
|
2635
|
+
`${agent} has no card to sign in with.`
|
|
2636
|
+
);
|
|
2637
|
+
}
|
|
2638
|
+
return body.jws;
|
|
2639
|
+
}
|
|
2640
|
+
function signInWithPidgeon(identity, input) {
|
|
2641
|
+
return signIn(
|
|
2642
|
+
identity,
|
|
2643
|
+
input,
|
|
2644
|
+
async ({ tokenEndpoint, exchange, headers, agent }) => signRequest(identity, {
|
|
2645
|
+
method: "POST",
|
|
2646
|
+
url: tokenEndpoint,
|
|
2647
|
+
headers,
|
|
2648
|
+
body: exchange,
|
|
2649
|
+
agent,
|
|
2650
|
+
grants: input.grant ? [input.grant] : void 0
|
|
2651
|
+
})
|
|
2652
|
+
);
|
|
2653
|
+
}
|
|
2654
|
+
async function signIn(identity, input, authenticate) {
|
|
2655
|
+
const fetcher = input.fetch ?? fetch;
|
|
2656
|
+
const agent = input.agent.trim().toLowerCase();
|
|
2657
|
+
const site = await siteMetadata(input.site, fetcher);
|
|
2658
|
+
const card = input.card ?? await fetchCard(agent, fetcher, input.postHost);
|
|
2659
|
+
const discovery = await json(
|
|
2660
|
+
await fetcher(`${site.issuer.replace(/\/$/, "")}/.well-known/openid-configuration`)
|
|
2661
|
+
);
|
|
2662
|
+
const tokenEndpoint = discovery.token_endpoint;
|
|
2663
|
+
if (typeof tokenEndpoint !== "string") {
|
|
2664
|
+
throw new SignInError("pidgeon", 0, void 0, `${site.issuer} has no token endpoint.`);
|
|
2665
|
+
}
|
|
2666
|
+
const exchange = form({
|
|
2667
|
+
grant_type: TOKEN_EXCHANGE,
|
|
2668
|
+
subject_token: card,
|
|
2669
|
+
subject_token_type: TOKEN_TYPE_JWT,
|
|
2670
|
+
audience: site.client_id,
|
|
2671
|
+
...input.delegation ? { requested_token_type: TOKEN_TYPE_JWT } : {}
|
|
2672
|
+
});
|
|
2673
|
+
const headers = { "content-type": "application/x-www-form-urlencoded" };
|
|
2674
|
+
const issued = await fetcher(tokenEndpoint, {
|
|
2675
|
+
method: "POST",
|
|
2676
|
+
headers: {
|
|
2677
|
+
...headers,
|
|
2678
|
+
...await authenticate({ tokenEndpoint, exchange, headers, agent, site })
|
|
2679
|
+
},
|
|
2680
|
+
body: exchange
|
|
2681
|
+
});
|
|
2682
|
+
const tokens = await json(issued);
|
|
2683
|
+
if (!issued.ok || typeof tokens.id_token !== "string") {
|
|
2684
|
+
throw new SignInError(
|
|
2685
|
+
"pidgeon",
|
|
2686
|
+
issued.status,
|
|
2687
|
+
tokens.error,
|
|
2688
|
+
tokens.error_description ?? `Pidgeon answered ${issued.status}.`
|
|
2689
|
+
);
|
|
2690
|
+
}
|
|
2691
|
+
const bearer = form({ grant_type: JWT_BEARER, assertion: tokens.id_token });
|
|
2692
|
+
const answered = await fetcher(site.token_endpoint, {
|
|
2693
|
+
method: "POST",
|
|
2694
|
+
headers: {
|
|
2695
|
+
...headers,
|
|
2696
|
+
...await signRequest(identity, {
|
|
2697
|
+
method: "POST",
|
|
2698
|
+
url: site.token_endpoint,
|
|
2699
|
+
headers,
|
|
2700
|
+
body: bearer,
|
|
2701
|
+
agent
|
|
2702
|
+
})
|
|
2703
|
+
},
|
|
2704
|
+
body: bearer
|
|
2705
|
+
});
|
|
2706
|
+
const session = await json(answered);
|
|
2707
|
+
if (!answered.ok) {
|
|
2708
|
+
throw new SignInError(
|
|
2709
|
+
"site",
|
|
2710
|
+
answered.status,
|
|
2711
|
+
session.error,
|
|
2712
|
+
session.error_description ?? `The site answered ${answered.status}.`
|
|
2713
|
+
);
|
|
2714
|
+
}
|
|
2715
|
+
return {
|
|
2716
|
+
site: session,
|
|
2717
|
+
idToken: tokens.id_token,
|
|
2718
|
+
accessToken: tokens.access_token
|
|
2719
|
+
};
|
|
2720
|
+
}
|
|
2520
2721
|
var UsageError = class extends Error {
|
|
2521
2722
|
};
|
|
2522
2723
|
var HELP = `pidgeon id \u2014 a signed identity for your agents, on your own domain. No account.
|
|
@@ -2527,6 +2728,13 @@ var HELP = `pidgeon id \u2014 a signed identity for your agents, on your own dom
|
|
|
2527
2728
|
list Agents on the domain
|
|
2528
2729
|
revoke <name> Withdraw an agent's card now
|
|
2529
2730
|
rotate Replace the domain's key; the old one verifies for another day
|
|
2731
|
+
grant <name> Grant <name> what it may do, as the domain
|
|
2732
|
+
--scope bookings.change --label "manage bookings"
|
|
2733
|
+
--subject customer:42 --audience delta.com --days 30
|
|
2734
|
+
--grantor maria@example.com ask a person instead
|
|
2735
|
+
revoke-grant <id> Take a grant back now
|
|
2736
|
+
revoke-sign-ins <name> End every token <name> signed in with; its card and grants stand
|
|
2737
|
+
sign-in <site> Sign in to a site as an agent --as <name> --grant <jws>
|
|
2530
2738
|
|
|
2531
2739
|
--domain <domain> Which domain, when this machine holds more than one
|
|
2532
2740
|
--json Print the API's answer as JSON
|
|
@@ -2569,7 +2777,7 @@ async function runId(argv, env = process.env, options = {}) {
|
|
|
2569
2777
|
const [command, ...rest] = positional;
|
|
2570
2778
|
if (!command || flags.has("help") || command === "help") return HELP;
|
|
2571
2779
|
const dir = identityDir(env);
|
|
2572
|
-
const
|
|
2780
|
+
const json2 = flags.has("json");
|
|
2573
2781
|
const say = options.stderr ?? (() => {
|
|
2574
2782
|
});
|
|
2575
2783
|
const sleep2 = options.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
@@ -2600,7 +2808,7 @@ async function runId(argv, env = process.env, options = {}) {
|
|
|
2600
2808
|
made = true;
|
|
2601
2809
|
}
|
|
2602
2810
|
let state = await client2(identity).claim();
|
|
2603
|
-
if (
|
|
2811
|
+
if (json2 && (state.status === "verified" || flags.has("no-wait")))
|
|
2604
2812
|
return JSON.stringify(state, null, 2);
|
|
2605
2813
|
const lines = [
|
|
2606
2814
|
made ? `Made a signing key for ${domain} on this machine (${identity.kid}).` : `Using the key for ${domain} on this machine.`
|
|
@@ -2629,13 +2837,13 @@ Or add them by hand:` : "Add these records at your DNS provider:",
|
|
|
2629
2837
|
}
|
|
2630
2838
|
lines.length = 0;
|
|
2631
2839
|
}
|
|
2632
|
-
if (
|
|
2840
|
+
if (json2) return JSON.stringify(state, null, 2);
|
|
2633
2841
|
return [...lines, `${domain} is proved. Next: pidgeon id issue support-agent`].join("\n").trim();
|
|
2634
2842
|
}
|
|
2635
2843
|
case "check": {
|
|
2636
2844
|
const identity = rest[0] ? await loadIdentity(rest[0], { dir, env }) : await which();
|
|
2637
2845
|
const state = await client2(identity).check();
|
|
2638
|
-
if (
|
|
2846
|
+
if (json2) return JSON.stringify(state, null, 2);
|
|
2639
2847
|
return [
|
|
2640
2848
|
`${state.domain}: ${state.status === "verified" ? "proved" : state.status}`,
|
|
2641
2849
|
...describeRecords(state)
|
|
@@ -2655,7 +2863,7 @@ Or add them by hand:` : "Add these records at your DNS provider:",
|
|
|
2655
2863
|
...kind ? { kind } : {},
|
|
2656
2864
|
...typeof onBehalfOf === "string" ? { on_behalf_of: onBehalfOf } : {}
|
|
2657
2865
|
});
|
|
2658
|
-
if (
|
|
2866
|
+
if (json2) return JSON.stringify(card, null, 2);
|
|
2659
2867
|
return [
|
|
2660
2868
|
`${card.card.address} has a card: ${card.url}`,
|
|
2661
2869
|
`Found from the address at https://post.${identity.domain}/.well-known/post/card?address=${card.card.address}`,
|
|
@@ -2664,7 +2872,7 @@ Or add them by hand:` : "Add these records at your DNS provider:",
|
|
|
2664
2872
|
}
|
|
2665
2873
|
case "list": {
|
|
2666
2874
|
const agents = await client2(await which()).list();
|
|
2667
|
-
if (
|
|
2875
|
+
if (json2) return JSON.stringify(agents, null, 2);
|
|
2668
2876
|
if (agents.length === 0)
|
|
2669
2877
|
return "No agents yet. `pidgeon id issue <name>` gives one a card.";
|
|
2670
2878
|
return agents.map((agent) => `${agent.address} ${agent.kind} ${agent.card_url}`).join("\n");
|
|
@@ -2673,7 +2881,7 @@ Or add them by hand:` : "Add these records at your DNS provider:",
|
|
|
2673
2881
|
const name = rest[0]?.trim().toLowerCase();
|
|
2674
2882
|
if (!name) throw new UsageError("Name the agent: `pidgeon id revoke support-agent`.");
|
|
2675
2883
|
const revoked = await client2(await which()).revoke(name);
|
|
2676
|
-
if (
|
|
2884
|
+
if (json2) return JSON.stringify(revoked, null, 2);
|
|
2677
2885
|
return `${revoked.address} has no card from now on. Copies already fetched lapse within a day.`;
|
|
2678
2886
|
}
|
|
2679
2887
|
case "rotate": {
|
|
@@ -2682,9 +2890,89 @@ Or add them by hand:` : "Add these records at your DNS provider:",
|
|
|
2682
2890
|
const state = await client2(current).rotate(next);
|
|
2683
2891
|
next.previous = { kid: current.kid, publicKey: current.publicKey };
|
|
2684
2892
|
await saveIdentity(next, dir);
|
|
2685
|
-
if (
|
|
2893
|
+
if (json2) return JSON.stringify(state, null, 2);
|
|
2686
2894
|
return `${current.domain} signs with ${next.kid} now. ${current.kid} still verifies for a day.`;
|
|
2687
2895
|
}
|
|
2896
|
+
case "grant": {
|
|
2897
|
+
const name = rest[0]?.trim().toLowerCase();
|
|
2898
|
+
const scope = flags.get("scope");
|
|
2899
|
+
const label = flags.get("label");
|
|
2900
|
+
const subject = flags.get("subject");
|
|
2901
|
+
if (!name || typeof scope !== "string" || typeof label !== "string") {
|
|
2902
|
+
throw new UsageError(
|
|
2903
|
+
'Name the agent and the scope: `pidgeon id grant support-agent --scope bookings.change --label "manage bookings" --subject customer:42`.'
|
|
2904
|
+
);
|
|
2905
|
+
}
|
|
2906
|
+
const [type, ...idParts] = typeof subject === "string" ? subject.split(":") : [];
|
|
2907
|
+
if (!type || idParts.length === 0 || !["customer", "account", "order"].includes(type)) {
|
|
2908
|
+
throw new UsageError("--subject is customer:<id>, account:<id> or order:<id>.");
|
|
2909
|
+
}
|
|
2910
|
+
const days = flags.get("days");
|
|
2911
|
+
const audience = flags.get("audience");
|
|
2912
|
+
const grantor = flags.get("grantor");
|
|
2913
|
+
const grant = await client2(await which()).grant({
|
|
2914
|
+
agent: name,
|
|
2915
|
+
scope: { name: scope, label },
|
|
2916
|
+
subject: { type, id: idParts.join(":") },
|
|
2917
|
+
...typeof audience === "string" ? { audience } : {},
|
|
2918
|
+
...typeof grantor === "string" ? { grantor: { email: grantor } } : {},
|
|
2919
|
+
...typeof days === "string" ? { expires_at: new Date(Date.now() + Number(days) * 864e5).toISOString() } : {}
|
|
2920
|
+
});
|
|
2921
|
+
if (json2) return JSON.stringify(grant, null, 2);
|
|
2922
|
+
if (grant.consent_url) {
|
|
2923
|
+
return [
|
|
2924
|
+
`Asked ${typeof grantor === "string" ? grantor : "them"} to let ${grant.agent} ${grant.scope.label} for ${grant.subject.type} ${grant.subject.id}.`,
|
|
2925
|
+
`Send them this link; nothing is allowed until they answer it: ${grant.consent_url}`,
|
|
2926
|
+
`Grant ${grant.id}. \`pidgeon id revoke-grant ${grant.id}\` withdraws the request.`
|
|
2927
|
+
].join("\n");
|
|
2928
|
+
}
|
|
2929
|
+
return [
|
|
2930
|
+
`${grant.agent} may ${grant.scope.label} for ${grant.subject.type} ${grant.subject.id}${grant.audience ? ` at ${grant.audience}` : ""}, until ${grant.expires_at}.`,
|
|
2931
|
+
`Grant ${grant.id}. The agent carries it as Post-Grant; --json prints the JWS.`
|
|
2932
|
+
].join("\n");
|
|
2933
|
+
}
|
|
2934
|
+
case "revoke-grant": {
|
|
2935
|
+
const grantId = rest[0]?.trim();
|
|
2936
|
+
if (!grantId) throw new UsageError("Name the grant: `pidgeon id revoke-grant <id>`.");
|
|
2937
|
+
const revoked = await client2(await which()).revokeGrant(grantId);
|
|
2938
|
+
if (json2) return JSON.stringify(revoked, null, 2);
|
|
2939
|
+
return `Grant ${revoked.id} is revoked. The next check of it fails.`;
|
|
2940
|
+
}
|
|
2941
|
+
case "revoke-sign-ins": {
|
|
2942
|
+
const name = rest[0]?.trim().toLowerCase();
|
|
2943
|
+
if (!name)
|
|
2944
|
+
throw new UsageError("Name the agent: `pidgeon id revoke-sign-ins support-agent`.");
|
|
2945
|
+
const done = await client2(await which()).revokeSignIns(name);
|
|
2946
|
+
if (json2) return JSON.stringify(done, null, 2);
|
|
2947
|
+
return `${done.address}: ${done.revoked} token${done.revoked === 1 ? "" : "s"} taken back. Its card and grants stand.`;
|
|
2948
|
+
}
|
|
2949
|
+
case "sign-in": {
|
|
2950
|
+
const site = rest[0];
|
|
2951
|
+
const name = flags.get("as");
|
|
2952
|
+
if (!site || typeof name !== "string") {
|
|
2953
|
+
throw new UsageError(
|
|
2954
|
+
"Name the site and the agent: `pidgeon id sign-in https://site.example/api/auth/pidgeon/token --as support-agent`."
|
|
2955
|
+
);
|
|
2956
|
+
}
|
|
2957
|
+
const identity = await which();
|
|
2958
|
+
const card = await client2(identity).issue({ name: name.trim().toLowerCase() });
|
|
2959
|
+
const grant = flags.get("grant");
|
|
2960
|
+
try {
|
|
2961
|
+
const signedIn = await signInWithPidgeon(identity, {
|
|
2962
|
+
agent: card.card.address,
|
|
2963
|
+
site,
|
|
2964
|
+
card: card.jws,
|
|
2965
|
+
...typeof grant === "string" ? { grant } : {},
|
|
2966
|
+
...options.fetch ? { fetch: options.fetch } : {}
|
|
2967
|
+
});
|
|
2968
|
+
if (json2) return JSON.stringify(signedIn.site, null, 2);
|
|
2969
|
+
return `Signed in to ${new URL(site).host} as ${card.card.address}.
|
|
2970
|
+
${JSON.stringify(signedIn.site, null, 2)}`;
|
|
2971
|
+
} catch (error) {
|
|
2972
|
+
if (error instanceof SignInError) throw new Error(`${error.step}: ${error.message}`);
|
|
2973
|
+
throw error;
|
|
2974
|
+
}
|
|
2975
|
+
}
|
|
2688
2976
|
default:
|
|
2689
2977
|
throw new UsageError(`No such command "${command}".
|
|
2690
2978
|
|
|
@@ -2890,4 +3178,4 @@ export {
|
|
|
2890
3178
|
find,
|
|
2891
3179
|
run
|
|
2892
3180
|
};
|
|
2893
|
-
//# sourceMappingURL=chunk-
|
|
3181
|
+
//# sourceMappingURL=chunk-ZDJG3Z7B.js.map
|