@permission-slip/cli 0.1.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.
Files changed (65) hide show
  1. package/dist/api/client.d.ts +91 -0
  2. package/dist/api/client.d.ts.map +1 -0
  3. package/dist/api/client.js +190 -0
  4. package/dist/api/client.js.map +1 -0
  5. package/dist/auth/keys.d.ts +41 -0
  6. package/dist/auth/keys.d.ts.map +1 -0
  7. package/dist/auth/keys.js +133 -0
  8. package/dist/auth/keys.js.map +1 -0
  9. package/dist/auth/signing.d.ts +27 -0
  10. package/dist/auth/signing.d.ts.map +1 -0
  11. package/dist/auth/signing.js +61 -0
  12. package/dist/auth/signing.js.map +1 -0
  13. package/dist/commands/capabilities.d.ts +8 -0
  14. package/dist/commands/capabilities.d.ts.map +1 -0
  15. package/dist/commands/capabilities.js +30 -0
  16. package/dist/commands/capabilities.js.map +1 -0
  17. package/dist/commands/config.d.ts +8 -0
  18. package/dist/commands/config.d.ts.map +1 -0
  19. package/dist/commands/config.js +38 -0
  20. package/dist/commands/config.js.map +1 -0
  21. package/dist/commands/connectors.d.ts +9 -0
  22. package/dist/commands/connectors.d.ts.map +1 -0
  23. package/dist/commands/connectors.js +34 -0
  24. package/dist/commands/connectors.js.map +1 -0
  25. package/dist/commands/execute.d.ts +17 -0
  26. package/dist/commands/execute.d.ts.map +1 -0
  27. package/dist/commands/execute.js +58 -0
  28. package/dist/commands/execute.js.map +1 -0
  29. package/dist/commands/register.d.ts +14 -0
  30. package/dist/commands/register.d.ts.map +1 -0
  31. package/dist/commands/register.js +65 -0
  32. package/dist/commands/register.js.map +1 -0
  33. package/dist/commands/request.d.ts +9 -0
  34. package/dist/commands/request.d.ts.map +1 -0
  35. package/dist/commands/request.js +54 -0
  36. package/dist/commands/request.js.map +1 -0
  37. package/dist/commands/status.d.ts +9 -0
  38. package/dist/commands/status.d.ts.map +1 -0
  39. package/dist/commands/status.js +44 -0
  40. package/dist/commands/status.js.map +1 -0
  41. package/dist/commands/verify.d.ts +9 -0
  42. package/dist/commands/verify.d.ts.map +1 -0
  43. package/dist/commands/verify.js +61 -0
  44. package/dist/commands/verify.js.map +1 -0
  45. package/dist/commands/whoami.d.ts +8 -0
  46. package/dist/commands/whoami.d.ts.map +1 -0
  47. package/dist/commands/whoami.js +65 -0
  48. package/dist/commands/whoami.js.map +1 -0
  49. package/dist/config/store.d.ts +30 -0
  50. package/dist/config/store.d.ts.map +1 -0
  51. package/dist/config/store.js +73 -0
  52. package/dist/config/store.js.map +1 -0
  53. package/dist/index.d.ts +22 -0
  54. package/dist/index.d.ts.map +1 -0
  55. package/dist/index.js +51 -0
  56. package/dist/index.js.map +1 -0
  57. package/dist/output.d.ts +9 -0
  58. package/dist/output.d.ts.map +1 -0
  59. package/dist/output.js +16 -0
  60. package/dist/output.js.map +1 -0
  61. package/dist/util/shell.d.ts +12 -0
  62. package/dist/util/shell.d.ts.map +1 -0
  63. package/dist/util/shell.js +14 -0
  64. package/dist/util/shell.js.map +1 -0
  65. package/package.json +54 -0
@@ -0,0 +1,38 @@
1
+ /**
2
+ * permission-slip config [--server <url>]
3
+ *
4
+ * Shows all saved registrations or the registration for a specific server.
5
+ */
6
+ import { loadRegistrations, findRegistration, CONFIG_DIR, REGISTRATIONS_FILE, PRIVATE_KEY_FILE, PUBLIC_KEY_FILE, } from "../config/store.js";
7
+ import { keyPairExists } from "../auth/keys.js";
8
+ import { output } from "../output.js";
9
+ export function configCommand(program) {
10
+ program
11
+ .command("config")
12
+ .description("Show saved configuration and registrations")
13
+ .option("--server <url>", "Show registration for a specific server only")
14
+ .option("--pretty", "Pretty-printed JSON (default is compact JSON)")
15
+ .action((opts) => {
16
+ const outputOpts = { pretty: opts.pretty ?? false };
17
+ try {
18
+ const data = {
19
+ config_dir: CONFIG_DIR,
20
+ registrations_file: REGISTRATIONS_FILE,
21
+ key: {
22
+ private_key_file: PRIVATE_KEY_FILE,
23
+ public_key_file: PUBLIC_KEY_FILE,
24
+ exists: keyPairExists(),
25
+ },
26
+ registrations: opts.server
27
+ ? (findRegistration(opts.server) ? [findRegistration(opts.server)] : [])
28
+ : loadRegistrations(),
29
+ };
30
+ output(data, outputOpts);
31
+ }
32
+ catch (err) {
33
+ output({ error: err instanceof Error ? err.message : String(err) }, outputOpts);
34
+ process.exit(1);
35
+ }
36
+ });
37
+ }
38
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACV,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,GAChB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,MAAM,EAAsB,MAAM,cAAc,CAAC;AAE1D,MAAM,UAAU,aAAa,CAAC,OAAgB;IAC5C,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,4CAA4C,CAAC;SACzD,MAAM,CAAC,gBAAgB,EAAE,8CAA8C,CAAC;SACxE,MAAM,CAAC,UAAU,EAAE,+CAA+C,CAAC;SACnE,MAAM,CAAC,CAAC,IAA2C,EAAE,EAAE;QACtD,MAAM,UAAU,GAAkB,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK,EAAE,CAAC;QACnE,IAAI,CAAC;YACH,MAAM,IAAI,GAAG;gBACX,UAAU,EAAE,UAAU;gBACtB,kBAAkB,EAAE,kBAAkB;gBACtC,GAAG,EAAE;oBACH,gBAAgB,EAAE,gBAAgB;oBAClC,eAAe,EAAE,eAAe;oBAChC,MAAM,EAAE,aAAa,EAAE;iBACxB;gBACD,aAAa,EAAE,IAAI,CAAC,MAAM;oBACxB,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;oBACxE,CAAC,CAAC,iBAAiB,EAAE;aACxB,CAAC;YACF,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAC3B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;YAChF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * permission-slip connectors [--server <url>] [--id <connector_id>]
3
+ *
4
+ * Lists available connectors (public endpoint, no auth required).
5
+ * With --id, shows details for a specific connector.
6
+ */
7
+ import type { Command } from "commander";
8
+ export declare function connectorsCommand(program: Command): void;
9
+ //# sourceMappingURL=connectors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connectors.d.ts","sourceRoot":"","sources":["../../src/commands/connectors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIzC,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA+BxD"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * permission-slip connectors [--server <url>] [--id <connector_id>]
3
+ *
4
+ * Lists available connectors (public endpoint, no auth required).
5
+ * With --id, shows details for a specific connector.
6
+ */
7
+ import { ApiClient } from "../api/client.js";
8
+ import { output } from "../output.js";
9
+ export function connectorsCommand(program) {
10
+ program
11
+ .command("connectors")
12
+ .description("List available connectors (public — no registration required)")
13
+ .option("--server <url>", "Permission Slip server URL", "https://app.permissionslip.dev")
14
+ .option("--id <connector_id>", "Get details for a specific connector")
15
+ .option("--pretty", "Pretty-printed JSON (default is compact JSON)")
16
+ .action(async (opts) => {
17
+ const outputOpts = { pretty: opts.pretty ?? false };
18
+ try {
19
+ const client = new ApiClient({
20
+ serverUrl: opts.server,
21
+ agentId: 0, // unused for public endpoints
22
+ });
23
+ const result = opts.id
24
+ ? await client.connector(opts.id)
25
+ : await client.connectors();
26
+ output(result, outputOpts);
27
+ }
28
+ catch (err) {
29
+ output({ error: err instanceof Error ? err.message : String(err) }, outputOpts);
30
+ process.exit(1);
31
+ }
32
+ });
33
+ }
34
+ //# sourceMappingURL=connectors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connectors.js","sourceRoot":"","sources":["../../src/commands/connectors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAsB,MAAM,cAAc,CAAC;AAE1D,MAAM,UAAU,iBAAiB,CAAC,OAAgB;IAChD,OAAO;SACJ,OAAO,CAAC,YAAY,CAAC;SACrB,WAAW,CAAC,+DAA+D,CAAC;SAC5E,MAAM,CACL,gBAAgB,EAChB,4BAA4B,EAC5B,gCAAgC,CACjC;SACA,MAAM,CAAC,qBAAqB,EAAE,sCAAsC,CAAC;SACrE,MAAM,CAAC,UAAU,EAAE,+CAA+C,CAAC;SACnE,MAAM,CAAC,KAAK,EAAE,IAId,EAAE,EAAE;QACH,MAAM,UAAU,GAAkB,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK,EAAE,CAAC;QACnE,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;gBAC3B,SAAS,EAAE,IAAI,CAAC,MAAM;gBACtB,OAAO,EAAE,CAAC,EAAE,8BAA8B;aAC3C,CAAC,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE;gBACpB,CAAC,CAAC,MAAM,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;gBACjC,CAAC,CAAC,MAAM,MAAM,CAAC,UAAU,EAAE,CAAC;YAC9B,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAC7B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;YAChF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * permission-slip execute --token <token> [--action <id>] [--params '{}'] [--server <url>]
3
+ * or
4
+ * permission-slip execute --configuration <id> [--params '{}'] [--server <url>]
5
+ *
6
+ * Executes an approved action using either:
7
+ * - A one-off execution token (obtained after the user approves a request)
8
+ * - A standing approval configuration (--configuration)
9
+ *
10
+ * NOTE: The /approvals/{id}/verify endpoint (which trades an approval ID for
11
+ * a token) is currently "Planned" server-side. Until it is implemented, agents
12
+ * must obtain the token out-of-band (the user shares it after approving on the
13
+ * dashboard) and pass it directly with --token.
14
+ */
15
+ import type { Command } from "commander";
16
+ export declare function executeCommand(program: Command): void;
17
+ //# sourceMappingURL=execute.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../src/commands/execute.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKzC,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAuDrD"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * permission-slip execute --token <token> [--action <id>] [--params '{}'] [--server <url>]
3
+ * or
4
+ * permission-slip execute --configuration <id> [--params '{}'] [--server <url>]
5
+ *
6
+ * Executes an approved action using either:
7
+ * - A one-off execution token (obtained after the user approves a request)
8
+ * - A standing approval configuration (--configuration)
9
+ *
10
+ * NOTE: The /approvals/{id}/verify endpoint (which trades an approval ID for
11
+ * a token) is currently "Planned" server-side. Until it is implemented, agents
12
+ * must obtain the token out-of-band (the user shares it after approving on the
13
+ * dashboard) and pass it directly with --token.
14
+ */
15
+ import { ApiClient } from "../api/client.js";
16
+ import { resolveAgentId } from "./status.js";
17
+ import { output } from "../output.js";
18
+ export function executeCommand(program) {
19
+ program
20
+ .command("execute")
21
+ .description("Execute an approved action")
22
+ .option("--token <token>", "Execution token (shared by the user after approving on the dashboard)")
23
+ .option("--configuration <id>", "Standing approval configuration ID")
24
+ .option("--action <action_id>", "Action type (required with --token)")
25
+ .option("--params <json>", "Action parameters as JSON string", "{}")
26
+ .option("--server <url>", "Permission Slip server URL", "https://app.permissionslip.dev")
27
+ .option("--agent-id <id>", "Agent ID (auto-detected from saved registration)")
28
+ .option("--pretty", "Pretty-printed JSON (default is compact JSON)")
29
+ .action(async (opts) => {
30
+ const outputOpts = { pretty: opts.pretty ?? false };
31
+ try {
32
+ if (!opts.token && !opts.configuration) {
33
+ throw new Error("Provide either --token <token> (one-off approval) or --configuration <id> (standing approval).");
34
+ }
35
+ if (opts.token && !opts.action) {
36
+ throw new Error("--action <action_id> is required when using --token.");
37
+ }
38
+ let params;
39
+ try {
40
+ params = JSON.parse(opts.params);
41
+ }
42
+ catch {
43
+ throw new Error(`--params must be valid JSON. Got: ${opts.params}`);
44
+ }
45
+ const agentId = resolveAgentId(opts.server, opts.agentId);
46
+ const client = new ApiClient({ serverUrl: opts.server, agentId });
47
+ const result = opts.token
48
+ ? await client.execute({ token: opts.token }, opts.action, params)
49
+ : await client.execute({ configuration_id: opts.configuration }, undefined, params);
50
+ output(result, outputOpts);
51
+ }
52
+ catch (err) {
53
+ output({ error: err instanceof Error ? err.message : String(err) }, outputOpts);
54
+ process.exit(1);
55
+ }
56
+ });
57
+ }
58
+ //# sourceMappingURL=execute.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execute.js","sourceRoot":"","sources":["../../src/commands/execute.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAsB,MAAM,cAAc,CAAC;AAE1D,MAAM,UAAU,cAAc,CAAC,OAAgB;IAC7C,OAAO;SACJ,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,4BAA4B,CAAC;SACzC,MAAM,CAAC,iBAAiB,EAAE,uEAAuE,CAAC;SAClG,MAAM,CAAC,sBAAsB,EAAE,oCAAoC,CAAC;SACpE,MAAM,CAAC,sBAAsB,EAAE,qCAAqC,CAAC;SACrE,MAAM,CAAC,iBAAiB,EAAE,kCAAkC,EAAE,IAAI,CAAC;SACnE,MAAM,CACL,gBAAgB,EAChB,4BAA4B,EAC5B,gCAAgC,CACjC;SACA,MAAM,CAAC,iBAAiB,EAAE,kDAAkD,CAAC;SAC7E,MAAM,CAAC,UAAU,EAAE,+CAA+C,CAAC;SACnE,MAAM,CAAC,KAAK,EAAE,IAQd,EAAE,EAAE;QACH,MAAM,UAAU,GAAkB,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK,EAAE,CAAC;QACnE,IAAI,CAAC;YACH,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;gBACvC,MAAM,IAAI,KAAK,CACb,gGAAgG,CACjG,CAAC;YACJ,CAAC;YACD,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;gBAC/B,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;YAC1E,CAAC;YAED,IAAI,MAAe,CAAC;YACpB,IAAI,CAAC;gBACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACnC,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,IAAI,KAAK,CAAC,qCAAqC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;YACtE,CAAC;YAED,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YAC1D,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;YAElE,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK;gBAChC,CAAC,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC;gBAClE,CAAC,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,gBAAgB,EAAE,IAAI,CAAC,aAAc,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;YAEvF,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAC7B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;YAChF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * permission-slip register --invite-code <code> [--server <url>] [--name <name>]
3
+ *
4
+ * Generates (or reuses) an Ed25519 key pair, then registers with the server
5
+ * using the provided invite code. Saves the result to
6
+ * ~/.permission-slip/registrations.json.
7
+ *
8
+ * After registration the server requires a verification step — the user will
9
+ * see a confirmation code on their dashboard and must relay it to the agent
10
+ * (via `permission-slip verify --code <code>`).
11
+ */
12
+ import type { Command } from "commander";
13
+ export declare function registerCommand(program: Command): void;
14
+ //# sourceMappingURL=register.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/commands/register.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQzC,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAuEtD"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * permission-slip register --invite-code <code> [--server <url>] [--name <name>]
3
+ *
4
+ * Generates (or reuses) an Ed25519 key pair, then registers with the server
5
+ * using the provided invite code. Saves the result to
6
+ * ~/.permission-slip/registrations.json.
7
+ *
8
+ * After registration the server requires a verification step — the user will
9
+ * see a confirmation code on their dashboard and must relay it to the agent
10
+ * (via `permission-slip verify --code <code>`).
11
+ */
12
+ import { generateKeyPair, keyPairExists, displayPath } from "../auth/keys.js";
13
+ import { ApiClient } from "../api/client.js";
14
+ import { REGISTRATION_AGENT_ID } from "../auth/signing.js";
15
+ import { saveRegistration } from "../config/store.js";
16
+ import { output } from "../output.js";
17
+ import { shellQuote } from "../util/shell.js";
18
+ export function registerCommand(program) {
19
+ program
20
+ .command("register")
21
+ .description("Generate keys and register with a Permission Slip server")
22
+ .requiredOption("--invite-code <code>", "Invite code from the dashboard")
23
+ .option("--server <url>", "Permission Slip server URL (default: https://app.permissionslip.dev)", "https://app.permissionslip.dev")
24
+ .option("--name <name>", "Agent name shown in the dashboard", "Agent")
25
+ .option("--version <version>", "Agent version metadata", "1.0.0")
26
+ .option("--pretty", "Pretty-printed JSON (default is compact JSON)")
27
+ .action(async (opts) => {
28
+ const outputOpts = { pretty: opts.pretty ?? false };
29
+ try {
30
+ // Key generation
31
+ const hadKey = keyPairExists();
32
+ const kp = generateKeyPair(false);
33
+ if (!hadKey && outputOpts.pretty) {
34
+ console.error(`Generated new Ed25519 key pair at ${displayPath(kp.privateKeyFile)}`);
35
+ }
36
+ else if (hadKey && outputOpts.pretty) {
37
+ console.error(`Reusing existing key pair at ${displayPath(kp.privateKeyFile)}`);
38
+ }
39
+ // Register
40
+ const client = new ApiClient({
41
+ serverUrl: opts.server,
42
+ agentId: REGISTRATION_AGENT_ID,
43
+ });
44
+ const result = await client.register(opts.inviteCode, kp.publicKey, opts.name, opts.version);
45
+ // Save a partial registration (will be completed after verify)
46
+ saveRegistration({
47
+ server: opts.server,
48
+ agent_id: result.agent_id,
49
+ registered_at: new Date().toISOString(),
50
+ });
51
+ output({
52
+ agent_id: result.agent_id,
53
+ expires_at: result.expires_at,
54
+ verification_required: result.verification_required,
55
+ key_file: displayPath(kp.privateKeyFile),
56
+ next_step: `Run: permission-slip verify --code <confirmation_code> --server ${shellQuote(opts.server)}`,
57
+ }, outputOpts);
58
+ }
59
+ catch (err) {
60
+ output({ error: err instanceof Error ? err.message : String(err) }, outputOpts);
61
+ process.exit(1);
62
+ }
63
+ });
64
+ }
65
+ //# sourceMappingURL=register.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.js","sourceRoot":"","sources":["../../src/commands/register.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * permission-slip request --action <action_id> [--params '{}'] [--server <url>]
3
+ *
4
+ * Requests one-off approval for an action. Returns the approval ID and URL.
5
+ * The user must approve on the dashboard and share a confirmation code.
6
+ */
7
+ import type { Command } from "commander";
8
+ export declare function requestCommand(program: Command): void;
9
+ //# sourceMappingURL=request.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/commands/request.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMzC,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA6DrD"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * permission-slip request --action <action_id> [--params '{}'] [--server <url>]
3
+ *
4
+ * Requests one-off approval for an action. Returns the approval ID and URL.
5
+ * The user must approve on the dashboard and share a confirmation code.
6
+ */
7
+ import { ApiClient } from "../api/client.js";
8
+ import { resolveAgentId } from "./status.js";
9
+ import { output } from "../output.js";
10
+ import { shellQuote } from "../util/shell.js";
11
+ export function requestCommand(program) {
12
+ program
13
+ .command("request")
14
+ .description("Request approval for an action")
15
+ .requiredOption("--action <action_id>", "Action type (e.g. email.send)")
16
+ .option("--params <json>", "Action parameters as JSON string", "{}")
17
+ .option("--description <text>", "Human-readable description of the action")
18
+ .option("--risk-level <level>", "Risk level: low, medium, high")
19
+ .option("--server <url>", "Permission Slip server URL", "https://app.permissionslip.dev")
20
+ .option("--agent-id <id>", "Agent ID (auto-detected from saved registration)")
21
+ .option("--pretty", "Pretty-printed JSON (default is compact JSON)")
22
+ .action(async (opts) => {
23
+ const outputOpts = { pretty: opts.pretty ?? false };
24
+ try {
25
+ let params;
26
+ try {
27
+ params = JSON.parse(opts.params);
28
+ }
29
+ catch {
30
+ throw new Error(`--params must be valid JSON. Got: ${opts.params}`);
31
+ }
32
+ const agentId = resolveAgentId(opts.server, opts.agentId);
33
+ const client = new ApiClient({ serverUrl: opts.server, agentId });
34
+ const context = opts.description || opts.riskLevel
35
+ ? {
36
+ description: opts.description,
37
+ risk_level: opts.riskLevel,
38
+ }
39
+ : undefined;
40
+ const result = await client.requestApproval(opts.action, params, context);
41
+ output({
42
+ ...result,
43
+ next_step: "Wait for the user to approve on the dashboard. Once they share the execution token with you, run: " +
44
+ `permission-slip execute --token <token> --action ${shellQuote(opts.action)} --params ${shellQuote(opts.params)}` +
45
+ (opts.server !== "https://app.permissionslip.dev" ? ` --server ${shellQuote(opts.server)}` : ""),
46
+ }, outputOpts);
47
+ }
48
+ catch (err) {
49
+ output({ error: err instanceof Error ? err.message : String(err) }, outputOpts);
50
+ process.exit(1);
51
+ }
52
+ });
53
+ }
54
+ //# sourceMappingURL=request.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request.js","sourceRoot":"","sources":["../../src/commands/request.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAsB,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,MAAM,UAAU,cAAc,CAAC,OAAgB;IAC7C,OAAO;SACJ,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,gCAAgC,CAAC;SAC7C,cAAc,CAAC,sBAAsB,EAAE,+BAA+B,CAAC;SACvE,MAAM,CAAC,iBAAiB,EAAE,kCAAkC,EAAE,IAAI,CAAC;SACnE,MAAM,CAAC,sBAAsB,EAAE,0CAA0C,CAAC;SAC1E,MAAM,CAAC,sBAAsB,EAAE,+BAA+B,CAAC;SAC/D,MAAM,CACL,gBAAgB,EAChB,4BAA4B,EAC5B,gCAAgC,CACjC;SACA,MAAM,CAAC,iBAAiB,EAAE,kDAAkD,CAAC;SAC7E,MAAM,CAAC,UAAU,EAAE,+CAA+C,CAAC;SACnE,MAAM,CAAC,KAAK,EAAE,IAQd,EAAE,EAAE;QACH,MAAM,UAAU,GAAkB,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK,EAAE,CAAC;QACnE,IAAI,CAAC;YACH,IAAI,MAAe,CAAC;YACpB,IAAI,CAAC;gBACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACnC,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,IAAI,KAAK,CAAC,qCAAqC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;YACtE,CAAC;YAED,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YAC1D,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;YAElE,MAAM,OAAO,GACX,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,SAAS;gBAChC,CAAC,CAAC;oBACE,WAAW,EAAE,IAAI,CAAC,WAAW;oBAC7B,UAAU,EAAE,IAAI,CAAC,SAAS;iBAC3B;gBACH,CAAC,CAAC,SAAS,CAAC;YAEhB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;YAE1E,MAAM,CACJ;gBACE,GAAG,MAAM;gBACT,SAAS,EACP,oGAAoG;oBACpG,oDAAoD,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;oBACjH,CAAC,IAAI,CAAC,MAAM,KAAK,gCAAgC,CAAC,CAAC,CAAC,aAAa,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACnG,EACD,UAAU,CACX,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;YAChF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * permission-slip status [--server <url>]
3
+ *
4
+ * Shows the current registration state for the agent on the given server.
5
+ */
6
+ import type { Command } from "commander";
7
+ export declare function statusCommand(program: Command): void;
8
+ export declare function resolveAgentId(server: string, agentIdFlag?: string): number;
9
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKzC,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA2BpD;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAc3E"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * permission-slip status [--server <url>]
3
+ *
4
+ * Shows the current registration state for the agent on the given server.
5
+ */
6
+ import { ApiClient } from "../api/client.js";
7
+ import { findRegistration } from "../config/store.js";
8
+ import { output } from "../output.js";
9
+ export function statusCommand(program) {
10
+ program
11
+ .command("status")
12
+ .description("Show current registration state")
13
+ .option("--server <url>", "Permission Slip server URL", "https://app.permissionslip.dev")
14
+ .option("--agent-id <id>", "Agent ID (auto-detected from saved registration)")
15
+ .option("--pretty", "Pretty-printed JSON (default is compact JSON)")
16
+ .action(async (opts) => {
17
+ const outputOpts = { pretty: opts.pretty ?? false };
18
+ try {
19
+ const agentId = resolveAgentId(opts.server, opts.agentId);
20
+ const client = new ApiClient({ serverUrl: opts.server, agentId });
21
+ const result = await client.status();
22
+ output(result, outputOpts);
23
+ }
24
+ catch (err) {
25
+ output({ error: err instanceof Error ? err.message : String(err) }, outputOpts);
26
+ process.exit(1);
27
+ }
28
+ });
29
+ }
30
+ export function resolveAgentId(server, agentIdFlag) {
31
+ if (agentIdFlag) {
32
+ const id = parseInt(agentIdFlag, 10);
33
+ if (isNaN(id))
34
+ throw new Error(`Invalid agent ID: ${agentIdFlag}`);
35
+ return id;
36
+ }
37
+ const reg = findRegistration(server);
38
+ if (!reg) {
39
+ throw new Error(`No registration found for ${server}. ` +
40
+ "Run 'permission-slip register --invite-code <code>' first.");
41
+ }
42
+ return reg.agent_id;
43
+ }
44
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,MAAM,EAAsB,MAAM,cAAc,CAAC;AAE1D,MAAM,UAAU,aAAa,CAAC,OAAgB;IAC5C,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,iCAAiC,CAAC;SAC9C,MAAM,CACL,gBAAgB,EAChB,4BAA4B,EAC5B,gCAAgC,CACjC;SACA,MAAM,CAAC,iBAAiB,EAAE,kDAAkD,CAAC;SAC7E,MAAM,CAAC,UAAU,EAAE,+CAA+C,CAAC;SACnE,MAAM,CAAC,KAAK,EAAE,IAId,EAAE,EAAE;QACH,MAAM,UAAU,GAAkB,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK,EAAE,CAAC;QACnE,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YAC1D,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;YAClE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC;YACrC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAC7B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;YAChF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAc,EAAE,WAAoB;IACjE,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,EAAE,GAAG,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QACrC,IAAI,KAAK,CAAC,EAAE,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,WAAW,EAAE,CAAC,CAAC;QACnE,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,GAAG,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACrC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CACb,6BAA6B,MAAM,IAAI;YACvC,4DAA4D,CAC7D,CAAC;IACJ,CAAC;IACD,OAAO,GAAG,CAAC,QAAQ,CAAC;AACtB,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * permission-slip verify --code <confirmation_code> [--server <url>]
3
+ *
4
+ * Completes the registration flow by submitting the confirmation code
5
+ * that the user sees on their dashboard after reviewing the pending agent.
6
+ */
7
+ import type { Command } from "commander";
8
+ export declare function verifyCommand(program: Command): void;
9
+ //# sourceMappingURL=verify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/commands/verify.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMzC,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAgEpD"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * permission-slip verify --code <confirmation_code> [--server <url>]
3
+ *
4
+ * Completes the registration flow by submitting the confirmation code
5
+ * that the user sees on their dashboard after reviewing the pending agent.
6
+ */
7
+ import { ApiClient } from "../api/client.js";
8
+ import { findRegistration, saveRegistration } from "../config/store.js";
9
+ import { output } from "../output.js";
10
+ import { shellQuote } from "../util/shell.js";
11
+ export function verifyCommand(program) {
12
+ program
13
+ .command("verify")
14
+ .description("Complete registration with the confirmation code from the dashboard")
15
+ .requiredOption("--code <confirmation_code>", "Confirmation code from the dashboard")
16
+ .option("--server <url>", "Permission Slip server URL", "https://app.permissionslip.dev")
17
+ .option("--agent-id <id>", "Agent ID (auto-detected from saved registration)")
18
+ .option("--pretty", "Pretty-printed JSON (default is compact JSON)")
19
+ .action(async (opts) => {
20
+ const outputOpts = { pretty: opts.pretty ?? false };
21
+ try {
22
+ let agentId;
23
+ if (opts.agentId) {
24
+ agentId = parseInt(opts.agentId, 10);
25
+ if (isNaN(agentId)) {
26
+ throw new Error(`Invalid agent ID: ${opts.agentId}`);
27
+ }
28
+ }
29
+ else {
30
+ const reg = findRegistration(opts.server);
31
+ if (!reg) {
32
+ throw new Error(`No registration found for ${opts.server}. ` +
33
+ "Run 'permission-slip register --invite-code <code>' first, " +
34
+ "or pass --agent-id explicitly.");
35
+ }
36
+ agentId = reg.agent_id;
37
+ }
38
+ const client = new ApiClient({ serverUrl: opts.server, agentId });
39
+ const result = await client.verify(agentId, opts.code);
40
+ // Update the registration with the confirmed timestamp
41
+ saveRegistration({
42
+ server: opts.server,
43
+ agent_id: agentId,
44
+ registered_at: result.registered_at,
45
+ });
46
+ output({
47
+ status: result.status,
48
+ agent_id: agentId,
49
+ registered_at: result.registered_at,
50
+ next_step: opts.server === "https://app.permissionslip.dev"
51
+ ? "Run: permission-slip capabilities"
52
+ : `Run: permission-slip capabilities --server ${shellQuote(opts.server)}`,
53
+ }, outputOpts);
54
+ }
55
+ catch (err) {
56
+ output({ error: err instanceof Error ? err.message : String(err) }, outputOpts);
57
+ process.exit(1);
58
+ }
59
+ });
60
+ }
61
+ //# sourceMappingURL=verify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/commands/verify.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,EAAE,MAAM,EAAsB,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,MAAM,UAAU,aAAa,CAAC,OAAgB;IAC5C,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,qEAAqE,CAAC;SAClF,cAAc,CAAC,4BAA4B,EAAE,sCAAsC,CAAC;SACpF,MAAM,CACL,gBAAgB,EAChB,4BAA4B,EAC5B,gCAAgC,CACjC;SACA,MAAM,CAAC,iBAAiB,EAAE,kDAAkD,CAAC;SAC7E,MAAM,CAAC,UAAU,EAAE,+CAA+C,CAAC;SACnE,MAAM,CAAC,KAAK,EAAE,IAKd,EAAE,EAAE;QACH,MAAM,UAAU,GAAkB,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK,EAAE,CAAC;QACnE,IAAI,CAAC;YACH,IAAI,OAAe,CAAC;YACpB,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBACjB,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;gBACrC,IAAI,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;oBACnB,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;gBACvD,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,MAAM,GAAG,GAAG,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBAC1C,IAAI,CAAC,GAAG,EAAE,CAAC;oBACT,MAAM,IAAI,KAAK,CACb,6BAA6B,IAAI,CAAC,MAAM,IAAI;wBAC5C,6DAA6D;wBAC7D,gCAAgC,CACjC,CAAC;gBACJ,CAAC;gBACD,OAAO,GAAG,GAAG,CAAC,QAAQ,CAAC;YACzB,CAAC;YAED,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;YAClE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;YAEvD,uDAAuD;YACvD,gBAAgB,CAAC;gBACf,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,QAAQ,EAAE,OAAO;gBACjB,aAAa,EAAE,MAAM,CAAC,aAAa;aACpC,CAAC,CAAC;YAEH,MAAM,CACJ;gBACE,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,QAAQ,EAAE,OAAO;gBACjB,aAAa,EAAE,MAAM,CAAC,aAAa;gBACnC,SAAS,EAAE,IAAI,CAAC,MAAM,KAAK,gCAAgC;oBACzD,CAAC,CAAC,mCAAmC;oBACrC,CAAC,CAAC,8CAA8C,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;aAC5E,EACD,UAAU,CACX,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;YAChF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * permission-slip whoami [--server <url>]
3
+ *
4
+ * Shows agent identity: local registration info and live status from the server.
5
+ */
6
+ import type { Command } from "commander";
7
+ export declare function whoamiCommand(program: Command): void;
8
+ //# sourceMappingURL=whoami.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whoami.d.ts","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMzC,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAgEpD"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * permission-slip whoami [--server <url>]
3
+ *
4
+ * Shows agent identity: local registration info and live status from the server.
5
+ */
6
+ import { ApiClient } from "../api/client.js";
7
+ import { loadRegistrations, findRegistration } from "../config/store.js";
8
+ import { keyPairExists, readPublicKey } from "../auth/keys.js";
9
+ import { output } from "../output.js";
10
+ export function whoamiCommand(program) {
11
+ program
12
+ .command("whoami")
13
+ .description("Show agent identity and registration info")
14
+ .option("--server <url>", "Permission Slip server URL", "https://app.permissionslip.dev")
15
+ .option("--agent-id <id>", "Agent ID (auto-detected from saved registration)")
16
+ .option("--pretty", "Pretty-printed JSON (default is compact JSON)")
17
+ .action(async (opts) => {
18
+ const outputOpts = { pretty: opts.pretty ?? false };
19
+ try {
20
+ const hasKey = keyPairExists();
21
+ let publicKey = null;
22
+ if (hasKey) {
23
+ try {
24
+ publicKey = readPublicKey();
25
+ }
26
+ catch {
27
+ // ignore
28
+ }
29
+ }
30
+ const registrations = loadRegistrations();
31
+ const reg = findRegistration(opts.server);
32
+ let agentId;
33
+ if (opts.agentId) {
34
+ agentId = parseInt(opts.agentId, 10);
35
+ }
36
+ else if (reg) {
37
+ agentId = reg.agent_id;
38
+ }
39
+ let liveStatus = null;
40
+ if (agentId !== undefined) {
41
+ try {
42
+ const client = new ApiClient({ serverUrl: opts.server, agentId });
43
+ liveStatus = await client.status();
44
+ }
45
+ catch {
46
+ liveStatus = null;
47
+ }
48
+ }
49
+ output({
50
+ key: { exists: hasKey, public_key: publicKey },
51
+ registrations,
52
+ current_server: {
53
+ server: opts.server,
54
+ registration: reg ?? null,
55
+ live_status: liveStatus,
56
+ },
57
+ }, outputOpts);
58
+ }
59
+ catch (err) {
60
+ output({ error: err instanceof Error ? err.message : String(err) }, outputOpts);
61
+ process.exit(1);
62
+ }
63
+ });
64
+ }
65
+ //# sourceMappingURL=whoami.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whoami.js","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAsB,MAAM,cAAc,CAAC;AAE1D,MAAM,UAAU,aAAa,CAAC,OAAgB;IAC5C,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,2CAA2C,CAAC;SACxD,MAAM,CACL,gBAAgB,EAChB,4BAA4B,EAC5B,gCAAgC,CACjC;SACA,MAAM,CAAC,iBAAiB,EAAE,kDAAkD,CAAC;SAC7E,MAAM,CAAC,UAAU,EAAE,+CAA+C,CAAC;SACnE,MAAM,CAAC,KAAK,EAAE,IAId,EAAE,EAAE;QACH,MAAM,UAAU,GAAkB,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK,EAAE,CAAC;QACnE,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;YAC/B,IAAI,SAAS,GAAkB,IAAI,CAAC;YACpC,IAAI,MAAM,EAAE,CAAC;gBACX,IAAI,CAAC;oBACH,SAAS,GAAG,aAAa,EAAE,CAAC;gBAC9B,CAAC;gBAAC,MAAM,CAAC;oBACP,SAAS;gBACX,CAAC;YACH,CAAC;YAED,MAAM,aAAa,GAAG,iBAAiB,EAAE,CAAC;YAC1C,MAAM,GAAG,GAAG,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC1C,IAAI,OAA2B,CAAC;YAChC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBACjB,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YACvC,CAAC;iBAAM,IAAI,GAAG,EAAE,CAAC;gBACf,OAAO,GAAG,GAAG,CAAC,QAAQ,CAAC;YACzB,CAAC;YAED,IAAI,UAAU,GAAY,IAAI,CAAC;YAC/B,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBAC1B,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;oBAClE,UAAU,GAAG,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC;gBACrC,CAAC;gBAAC,MAAM,CAAC;oBACP,UAAU,GAAG,IAAI,CAAC;gBACpB,CAAC;YACH,CAAC;YAED,MAAM,CACJ;gBACE,GAAG,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE;gBAC9C,aAAa;gBACb,cAAc,EAAE;oBACd,MAAM,EAAE,IAAI,CAAC,MAAM;oBACnB,YAAY,EAAE,GAAG,IAAI,IAAI;oBACzB,WAAW,EAAE,UAAU;iBACxB;aACF,EACD,UAAU,CACX,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;YAChF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Manages ~/.permission-slip/ — config directory and registrations file.
3
+ *
4
+ * Registrations are stored as:
5
+ * ~/.permission-slip/registrations.json
6
+ *
7
+ * Key files are stored as:
8
+ * ~/.ssh/permission_slip_agent (private key, OpenSSH format)
9
+ * ~/.ssh/permission_slip_agent.pub (public key)
10
+ */
11
+ export interface Registration {
12
+ server: string;
13
+ agent_id: number;
14
+ registered_at: string;
15
+ }
16
+ export declare const CONFIG_DIR: string;
17
+ export declare const REGISTRATIONS_FILE: string;
18
+ export declare const SSH_DIR: string;
19
+ export declare const PRIVATE_KEY_FILE: string;
20
+ export declare const PUBLIC_KEY_FILE: string;
21
+ export declare function ensureConfigDir(): void;
22
+ export declare function loadRegistrations(): Registration[];
23
+ export declare function saveRegistration(reg: Registration): void;
24
+ /**
25
+ * Find a registration for the given server. If multiple registrations exist
26
+ * for the same server (different agent IDs), returns the most recently
27
+ * registered one.
28
+ */
29
+ export declare function findRegistration(server: string): Registration | undefined;
30
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/config/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;CACvB;AAOD,eAAO,MAAM,UAAU,QAEsB,CAAC;AAC9C,eAAO,MAAM,kBAAkB,QAA8C,CAAC;AAC9E,eAAO,MAAM,OAAO,QACmD,CAAC;AACxE,eAAO,MAAM,gBAAgB,QAEgB,CAAC;AAC9C,eAAO,MAAM,eAAe,QAEqB,CAAC;AAElD,wBAAgB,eAAe,IAAI,IAAI,CAItC;AAED,wBAAgB,iBAAiB,IAAI,YAAY,EAAE,CAWlD;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,CAmBxD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CASzE"}