@did-btcr2/cli 0.10.2 → 0.11.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 (89) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/cjs/index.js +889 -43
  3. package/dist/esm/src/cli.js +30 -12
  4. package/dist/esm/src/cli.js.map +1 -1
  5. package/dist/esm/src/commands/completion.js +36 -0
  6. package/dist/esm/src/commands/completion.js.map +1 -0
  7. package/dist/esm/src/commands/config.js +69 -0
  8. package/dist/esm/src/commands/config.js.map +1 -0
  9. package/dist/esm/src/commands/deactivate.js +21 -8
  10. package/dist/esm/src/commands/deactivate.js.map +1 -1
  11. package/dist/esm/src/commands/index.js +4 -0
  12. package/dist/esm/src/commands/index.js.map +1 -1
  13. package/dist/esm/src/commands/key.js +175 -0
  14. package/dist/esm/src/commands/key.js.map +1 -0
  15. package/dist/esm/src/commands/profile.js +63 -0
  16. package/dist/esm/src/commands/profile.js.map +1 -0
  17. package/dist/esm/src/commands/update.js +19 -9
  18. package/dist/esm/src/commands/update.js.map +1 -1
  19. package/dist/esm/src/config.js +100 -13
  20. package/dist/esm/src/config.js.map +1 -1
  21. package/dist/esm/src/keystore/atomic.js +64 -0
  22. package/dist/esm/src/keystore/atomic.js.map +1 -0
  23. package/dist/esm/src/keystore/envelope.js +123 -0
  24. package/dist/esm/src/keystore/envelope.js.map +1 -0
  25. package/dist/esm/src/keystore/error.js +16 -0
  26. package/dist/esm/src/keystore/error.js.map +1 -0
  27. package/dist/esm/src/keystore/file-backed-key-manager.js +78 -0
  28. package/dist/esm/src/keystore/file-backed-key-manager.js.map +1 -0
  29. package/dist/esm/src/keystore/file-key-store.js +184 -0
  30. package/dist/esm/src/keystore/file-key-store.js.map +1 -0
  31. package/dist/esm/src/keystore/passphrase.js +87 -0
  32. package/dist/esm/src/keystore/passphrase.js.map +1 -0
  33. package/dist/esm/src/keystore/paths.js +20 -0
  34. package/dist/esm/src/keystore/paths.js.map +1 -0
  35. package/dist/esm/src/keystore/resolve-key-ref.js +47 -0
  36. package/dist/esm/src/keystore/resolve-key-ref.js.map +1 -0
  37. package/dist/types/src/cli.d.ts +6 -2
  38. package/dist/types/src/cli.d.ts.map +1 -1
  39. package/dist/types/src/commands/completion.d.ts +5 -0
  40. package/dist/types/src/commands/completion.d.ts.map +1 -0
  41. package/dist/types/src/commands/config.d.ts +5 -0
  42. package/dist/types/src/commands/config.d.ts.map +1 -0
  43. package/dist/types/src/commands/deactivate.d.ts.map +1 -1
  44. package/dist/types/src/commands/index.d.ts +4 -0
  45. package/dist/types/src/commands/index.d.ts.map +1 -1
  46. package/dist/types/src/commands/key.d.ts +10 -0
  47. package/dist/types/src/commands/key.d.ts.map +1 -0
  48. package/dist/types/src/commands/profile.d.ts +5 -0
  49. package/dist/types/src/commands/profile.d.ts.map +1 -0
  50. package/dist/types/src/commands/update.d.ts.map +1 -1
  51. package/dist/types/src/config.d.ts +50 -7
  52. package/dist/types/src/config.d.ts.map +1 -1
  53. package/dist/types/src/keystore/atomic.d.ts +19 -0
  54. package/dist/types/src/keystore/atomic.d.ts.map +1 -0
  55. package/dist/types/src/keystore/envelope.d.ts +64 -0
  56. package/dist/types/src/keystore/envelope.d.ts.map +1 -0
  57. package/dist/types/src/keystore/error.d.ts +14 -0
  58. package/dist/types/src/keystore/error.d.ts.map +1 -0
  59. package/dist/types/src/keystore/file-backed-key-manager.d.ts +41 -0
  60. package/dist/types/src/keystore/file-backed-key-manager.d.ts.map +1 -0
  61. package/dist/types/src/keystore/file-key-store.d.ts +52 -0
  62. package/dist/types/src/keystore/file-key-store.d.ts.map +1 -0
  63. package/dist/types/src/keystore/passphrase.d.ts +20 -0
  64. package/dist/types/src/keystore/passphrase.d.ts.map +1 -0
  65. package/dist/types/src/keystore/paths.d.ts +13 -0
  66. package/dist/types/src/keystore/paths.d.ts.map +1 -0
  67. package/dist/types/src/keystore/resolve-key-ref.d.ts +19 -0
  68. package/dist/types/src/keystore/resolve-key-ref.d.ts.map +1 -0
  69. package/dist/types/src/types.d.ts +91 -0
  70. package/dist/types/src/types.d.ts.map +1 -1
  71. package/package.json +9 -4
  72. package/src/cli.ts +36 -11
  73. package/src/commands/completion.ts +40 -0
  74. package/src/commands/config.ts +84 -0
  75. package/src/commands/deactivate.ts +25 -12
  76. package/src/commands/index.ts +4 -0
  77. package/src/commands/key.ts +193 -0
  78. package/src/commands/profile.ts +65 -0
  79. package/src/commands/update.ts +23 -13
  80. package/src/config.ts +144 -22
  81. package/src/keystore/atomic.ts +73 -0
  82. package/src/keystore/envelope.ts +172 -0
  83. package/src/keystore/error.ts +16 -0
  84. package/src/keystore/file-backed-key-manager.ts +99 -0
  85. package/src/keystore/file-key-store.ts +242 -0
  86. package/src/keystore/passphrase.ts +99 -0
  87. package/src/keystore/paths.ts +20 -0
  88. package/src/keystore/resolve-key-ref.ts +62 -0
  89. package/src/types.ts +30 -11
@@ -1,7 +1,7 @@
1
+ import { DidMethodError } from '@did-btcr2/common';
1
2
  import { Command, CommanderError } from 'commander';
2
- import { registerCreateCommand, registerDeactivateCommand, registerResolveCommand, registerUpdateCommand, } from './commands/index.js';
3
- import { defaultApiFactory } from './config.js';
4
- import { CLIError } from './error.js';
3
+ import { registerCompletionCommand, registerConfigCommand, registerCreateCommand, registerDeactivateCommand, registerKeyCommand, registerProfileCommand, registerResolveCommand, registerUpdateCommand, } from './commands/index.js';
4
+ import { defaultApiFactory, keystoreApiFactory } from './config.js';
5
5
  import { VERSION } from './version.js';
6
6
  /**
7
7
  * CLI tool for the did:btcr2 method.
@@ -16,9 +16,13 @@ export class DidBtcr2Cli {
16
16
  * {@link defaultApiFactory} which uses public endpoints (mempool.space)
17
17
  * for known networks and localhost Polar for regtest.
18
18
  *
19
- * @param factory - Optional API factory. Defaults to {@link defaultApiFactory}.
19
+ * @param factory - Optional API factory for keystore-free commands (create,
20
+ * resolve). Defaults to {@link defaultApiFactory}.
21
+ * @param keystoreFactory - Optional keystore-aware API factory for commands
22
+ * that need a signing identity (key, update, deactivate). Defaults to
23
+ * {@link keystoreApiFactory}.
20
24
  */
21
- constructor(factory = defaultApiFactory) {
25
+ constructor(factory = defaultApiFactory, keystoreFactory = keystoreApiFactory) {
22
26
  this.program = new Command('btcr2')
23
27
  .version(`btcr2 ${VERSION}`, '-v, --version', 'Output the current version')
24
28
  .description('CLI tool for the did:btcr2 method')
@@ -31,12 +35,19 @@ export class DidBtcr2Cli {
31
35
  .option('--btc-rpc-url <url>', 'Override Bitcoin Core RPC endpoint')
32
36
  .option('--btc-rpc-user <user>', 'Bitcoin Core RPC username')
33
37
  .option('--btc-rpc-pass <pass>', 'Bitcoin Core RPC password')
34
- .option('--cas-gateway <url>', 'IPFS HTTP gateway for CAS reads');
38
+ .option('--cas-gateway <url>', 'IPFS HTTP gateway for CAS reads')
39
+ .option('--keystore <path>', 'Path to the keystore file (default: $XDG_DATA_HOME/btcr2/keystore.json)')
40
+ .option('--passphrase-file <path>', 'Read the keystore passphrase from a file (unattended use)')
41
+ .option('--signing-key <ref>', 'Key for update/deactivate signing: a URN, fingerprint prefix, or name');
35
42
  const globals = () => this.program.opts();
36
43
  registerCreateCommand(this.program, factory, globals);
37
44
  registerResolveCommand(this.program, factory, globals);
38
- registerUpdateCommand(this.program, factory, globals);
39
- registerDeactivateCommand(this.program, factory, globals);
45
+ registerUpdateCommand(this.program, keystoreFactory, globals);
46
+ registerDeactivateCommand(this.program, keystoreFactory, globals);
47
+ registerKeyCommand(this.program, keystoreFactory, globals);
48
+ registerConfigCommand(this.program, globals);
49
+ registerProfileCommand(this.program, globals);
50
+ registerCompletionCommand(this.program, globals);
40
51
  }
41
52
  /**
42
53
  * Runs the CLI with the provided argv or process.argv.
@@ -51,7 +62,7 @@ export class DidBtcr2Cli {
51
62
  this.program.outputHelp();
52
63
  }
53
64
  catch (error) {
54
- handleError(error);
65
+ handleError(error, Boolean(this.program.opts().verbose));
55
66
  }
56
67
  }
57
68
  }
@@ -69,16 +80,23 @@ function normalizeArgv(argv) {
69
80
  }
70
81
  /**
71
82
  * Handles errors thrown during CLI execution.
83
+ *
84
+ * Known method errors ({@link DidMethodError} and its subclasses, including
85
+ * {@link CLIError} and the keystore errors) print only their message, never the
86
+ * stack or the structured `data` payload, so internal shapes are not leaked.
87
+ * The full error object and stack are shown only under `--verbose`.
88
+ *
72
89
  * @param {unknown} error - The error to handle.
90
+ * @param {boolean} verbose - Whether to print the full error object and stack.
73
91
  * @returns {void}
74
92
  */
75
- function handleError(error) {
93
+ function handleError(error, verbose) {
76
94
  if (error instanceof CommanderError &&
77
95
  (error.code === 'commander.helpDisplayed' || error.code === 'commander.help')) {
78
96
  return;
79
97
  }
80
- if (error instanceof CLIError) {
81
- console.error(error.message);
98
+ if (error instanceof DidMethodError) {
99
+ console.error(verbose ? error : error.message);
82
100
  process.exitCode ??= 1;
83
101
  return;
84
102
  }
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import { CLIError } from '../error.js';
2
+ const COMMANDS = 'create resolve read update deactivate delete key config profile completion';
3
+ /** Registers the `completion` command, which prints a shell completion script to stdout. */
4
+ export function registerCompletionCommand(program, _globals) {
5
+ program
6
+ .command('completion [shell]')
7
+ .description('Print a shell completion script (bash, zsh, or fish) to stdout.')
8
+ .action((shell = 'bash') => {
9
+ console.log(completionScript(shell));
10
+ });
11
+ }
12
+ /** Returns a completion script for the given shell. */
13
+ function completionScript(shell) {
14
+ switch (shell) {
15
+ case 'bash':
16
+ return [
17
+ '# btcr2 bash completion. Install with: eval "$(btcr2 completion bash)"',
18
+ '_btcr2() { COMPREPLY=( $(compgen -W "' + COMMANDS + '" -- "${COMP_WORDS[COMP_CWORD]}") ); }',
19
+ 'complete -F _btcr2 btcr2',
20
+ ].join('\n');
21
+ case 'zsh':
22
+ return [
23
+ '# btcr2 zsh completion. Install with: eval "$(btcr2 completion zsh)"',
24
+ '_btcr2() { compadd ' + COMMANDS + ' }',
25
+ 'compdef _btcr2 btcr2',
26
+ ].join('\n');
27
+ case 'fish':
28
+ return [
29
+ '# btcr2 fish completion. Save to ~/.config/fish/completions/btcr2.fish',
30
+ 'complete -c btcr2 -f -a "' + COMMANDS + '"',
31
+ ].join('\n');
32
+ default:
33
+ throw new CLIError(`Unsupported shell "${shell}". Use bash, zsh, or fish.`, 'INVALID_ARGUMENT_ERROR', { shell });
34
+ }
35
+ }
36
+ //# sourceMappingURL=completion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completion.js","sourceRoot":"","sources":["../../../../src/commands/completion.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGvC,MAAM,QAAQ,GAAG,4EAA4E,CAAC;AAE9F,4FAA4F;AAC5F,MAAM,UAAU,yBAAyB,CAAC,OAAgB,EAAE,QAA6B;IACvF,OAAO;SACJ,OAAO,CAAC,oBAAoB,CAAC;SAC7B,WAAW,CAAC,iEAAiE,CAAC;SAC9E,MAAM,CAAC,CAAC,KAAK,GAAG,MAAM,EAAE,EAAE;QACzB,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;AACP,CAAC;AAED,uDAAuD;AACvD,SAAS,gBAAgB,CAAC,KAAa;IACrC,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,MAAM;YACT,OAAO;gBACL,wEAAwE;gBACxE,uCAAuC,GAAG,QAAQ,GAAG,wCAAwC;gBAC7F,0BAA0B;aAC3B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACf,KAAK,KAAK;YACR,OAAO;gBACL,sEAAsE;gBACtE,qBAAqB,GAAG,QAAQ,GAAG,IAAI;gBACvC,sBAAsB;aACvB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACf,KAAK,MAAM;YACT,OAAO;gBACL,wEAAwE;gBACxE,2BAA2B,GAAG,QAAQ,GAAG,GAAG;aAC7C,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACf;YACE,MAAM,IAAI,QAAQ,CAAC,sBAAsB,KAAK,4BAA4B,EAAE,wBAAwB,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IACrH,CAAC;AACH,CAAC"}
@@ -0,0 +1,69 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { dirname } from 'node:path';
3
+ import { CONFIG_SCHEMA_VERSION, defaultConfigPath, getConfigPath, readConfigFile, setConfigPath, unsetConfigPath, writeConfigFile, } from '../config.js';
4
+ import { CLIError } from '../error.js';
5
+ import { ensureDir, writeFileAtomic } from '../keystore/atomic.js';
6
+ import { formatResult } from '../output.js';
7
+ import { SUPPORTED_NETWORKS } from '../types.js';
8
+ /** Registers the `config` command group for reading and writing CLI configuration. */
9
+ export function registerConfigCommand(program, globals) {
10
+ const config = program.command('config').description('Read and write CLI configuration.');
11
+ const path = () => globals().config ?? defaultConfigPath();
12
+ const print = (result) => console.log(formatResult(result, globals()));
13
+ config
14
+ .command('init')
15
+ .description('Create a default config file with one profile per network.')
16
+ .option('--force', 'Overwrite an existing config file.', false)
17
+ .action((options) => {
18
+ const p = path();
19
+ if (existsSync(p) && !options.force) {
20
+ throw new CLIError(`Config already exists at ${p}. Use --force to overwrite.`, 'INVALID_ARGUMENT_ERROR', { path: p });
21
+ }
22
+ const scaffold = {
23
+ schemaVersion: CONFIG_SCHEMA_VERSION,
24
+ defaults: { output: 'text' },
25
+ profiles: Object.fromEntries(SUPPORTED_NETWORKS.map(n => [n, {}])),
26
+ };
27
+ ensureDir(dirname(p), 0o700);
28
+ writeFileAtomic(p, `${JSON.stringify(scaffold, null, 2)}\n`, 0o600);
29
+ print({ action: 'config-init', data: { path: p } });
30
+ });
31
+ config
32
+ .command('get [path]')
33
+ .description('Print a value at a dotted path, or the whole config.')
34
+ .action((dotted) => {
35
+ const file = (readConfigFile(path()) ?? {});
36
+ print({ action: 'config-get', data: (dotted ? getConfigPath(file, dotted) : file) ?? null });
37
+ });
38
+ config
39
+ .command('set <path> <value>')
40
+ .description('Set a value at a dotted path. The value is parsed as JSON when valid, else stored as a string.')
41
+ .action((dotted, value) => {
42
+ writeConfigFile(path(), raw => setConfigPath(raw, dotted, parseValue(value)));
43
+ print({ action: 'config-set', data: { path: dotted } });
44
+ });
45
+ config
46
+ .command('unset <path>')
47
+ .description('Delete a value at a dotted path.')
48
+ .action((dotted) => {
49
+ writeConfigFile(path(), raw => unsetConfigPath(raw, dotted));
50
+ print({ action: 'config-unset', data: { path: dotted } });
51
+ });
52
+ config
53
+ .command('list')
54
+ .alias('ls')
55
+ .description('Print the entire config file.')
56
+ .action(() => {
57
+ print({ action: 'config-list', data: readConfigFile(path()) ?? {} });
58
+ });
59
+ }
60
+ /** Parses a value as JSON when valid, otherwise treats it as a plain string. */
61
+ function parseValue(value) {
62
+ try {
63
+ return JSON.parse(value);
64
+ }
65
+ catch {
66
+ return value;
67
+ }
68
+ }
69
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../../src/commands/config.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,8 @@
1
+ import { KeyManagerSigner } from '@did-btcr2/key-manager';
1
2
  import { deriveNetwork } from '../config.js';
2
3
  import { CLIError } from '../error.js';
4
+ import { resolveKeyRef } from '../keystore/resolve-key-ref.js';
5
+ import { formatResult } from '../output.js';
3
6
  /** The JSON Patch that marks a DID document as permanently deactivated. */
4
7
  const DEACTIVATION_PATCH = [{ op: 'add', path: '/deactivated', value: true }];
5
8
  export function registerDeactivateCommand(program, factory, globals) {
@@ -12,6 +15,9 @@ export function registerDeactivateCommand(program, factory, globals) {
12
15
  .requiredOption('-m, --verification-method-id <id>', 'DID document verification method ID used to sign the deactivation')
13
16
  .requiredOption('-b, --beacon-id <json>', 'Beacon ID as a JSON string', parseJsonArg('--beacon-id'))
14
17
  .action(async (options) => {
18
+ if (!/^\d+$/.test(options.sourceVersionId)) {
19
+ throw new CLIError('--source-version-id must be a non-negative integer.', 'INVALID_ARGUMENT_ERROR', { value: options.sourceVersionId });
20
+ }
15
21
  const parsed = {
16
22
  sourceDocument: options.sourceDocument,
17
23
  patches: DEACTIVATION_PATCH,
@@ -23,14 +29,21 @@ export function registerDeactivateCommand(program, factory, globals) {
23
29
  if (!did) {
24
30
  throw new CLIError('Source document must contain an "id" field.', 'INVALID_ARGUMENT_ERROR', options);
25
31
  }
26
- // CLI signing is not yet wired up; deactivate uses the same update path
27
- // and inherits the same gap. Drive the SDK directly with a `Signer` for now.
28
- // Variables above are kept so command parsing + validation still works.
29
- void deriveNetwork(did);
30
- void factory;
31
- void globals;
32
- void parsed;
33
- throw new CLIError('CLI signing is not yet implemented. Use @did-btcr2/api with a Signer directly.', 'NOT_IMPLEMENTED_ERROR', { command: 'deactivate' });
32
+ // Deactivation is an update that applies the deactivation patch. The core
33
+ // method has no separate deactivate path, so this routes through update.
34
+ const network = deriveNetwork(did);
35
+ const api = factory(network, globals());
36
+ const keyId = resolveKeyRef(api.kms.kms, globals().signingKey);
37
+ const signer = new KeyManagerSigner(api.kms.kms, keyId);
38
+ const data = await api.btcr2.update({
39
+ sourceDocument: parsed.sourceDocument,
40
+ patches: parsed.patches,
41
+ sourceVersionId: parsed.sourceVersionId,
42
+ verificationMethodId: parsed.verificationMethodId,
43
+ beaconId: parsed.beaconId,
44
+ signer,
45
+ });
46
+ console.log(formatResult({ action: 'deactivate', data }, globals()));
34
47
  });
35
48
  }
36
49
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"deactivate.js","sourceRoot":"","sources":["../../../../src/commands/deactivate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAmB,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGvC,2EAA2E;AAC3E,MAAM,kBAAkB,GAAG,CAAC,EAAE,EAAE,EAAE,KAAc,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAEvF,MAAM,UAAU,yBAAyB,CACvC,OAAiB,EACjB,OAAoB,EACpB,OAA6B;IAE7B,OAAO;SACJ,OAAO,CAAC,YAAY,CAAC;SACrB,KAAK,CAAC,QAAQ,CAAC;SACf,WAAW,CAAC,wEAAwE,CAAC;SACrF,cAAc,CACb,8BAA8B,EAC9B,qCAAqC,EACrC,YAAY,CAAC,mBAAmB,CAAC,CAClC;SACA,cAAc,CACb,8BAA8B,EAC9B,wCAAwC,CACzC;SACA,cAAc,CACb,mCAAmC,EACnC,mEAAmE,CACpE;SACA,cAAc,CACb,wBAAwB,EACxB,4BAA4B,EAC5B,YAAY,CAAC,aAAa,CAAC,CAC5B;SACA,MAAM,CAAC,KAAK,EAAE,OAKd,EAAE,EAAE;QACH,MAAM,MAAM,GAAyB;YACnC,cAAc,EAAS,OAAO,CAAC,cAAwD;YACvF,OAAO,EAAgB,kBAAkB;YACzC,eAAe,EAAQ,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC;YACtD,oBAAoB,EAAG,OAAO,CAAC,oBAAoB;YACnD,QAAQ,EAAe,OAAO,CAAC,QAA4C;SAC5E,CAAC;QACF,MAAM,GAAG,GAAG,MAAM,CAAC,cAAc,EAAE,EAAE,CAAC;QACtC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,QAAQ,CAChB,6CAA6C,EAC7C,wBAAwB,EACxB,OAAO,CACR,CAAC;QACJ,CAAC;QACD,wEAAwE;QACxE,6EAA6E;QAC7E,wEAAwE;QACxE,KAAK,aAAa,CAAC,GAAG,CAAC,CAAC;QACxB,KAAK,OAAO,CAAC;QACb,KAAK,OAAO,CAAC;QACb,KAAK,MAAM,CAAC;QACZ,MAAM,IAAI,QAAQ,CAChB,gFAAgF,EAChF,uBAAuB,EACvB,EAAE,OAAO,EAAE,YAAY,EAAE,CAC1B,CAAC;IACJ,CAAC,CAAC,CAAC;AACP,CAAC;AAED;;;GAGG;AACH,SAAS,YAAY,CAAC,QAAgB;IACpC,OAAO,CAAC,KAAa,EAAW,EAAE;QAChC,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,QAAQ,CAChB,oBAAoB,QAAQ,gCAAgC,EAC5D,wBAAwB,EACxB,EAAE,QAAQ,EAAE,KAAK,EAAE,CACpB,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"deactivate.js","sourceRoot":"","sources":["../../../../src/commands/deactivate.ts"],"names":[],"mappings":"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"}
@@ -2,4 +2,8 @@ export { registerCreateCommand } from './create.js';
2
2
  export { registerResolveCommand } from './resolve.js';
3
3
  export { registerUpdateCommand } from './update.js';
4
4
  export { registerDeactivateCommand } from './deactivate.js';
5
+ export { registerKeyCommand } from './key.js';
6
+ export { registerConfigCommand } from './config.js';
7
+ export { registerProfileCommand } from './profile.js';
8
+ export { registerCompletionCommand } from './completion.js';
5
9
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,175 @@
1
+ import { SchnorrKeyPair } from '@did-btcr2/keypair';
2
+ import { bytesToHex, hexToBytes } from '@noble/hashes/utils.js';
3
+ import { closeSync, openSync, readFileSync, writeFileSync } from 'node:fs';
4
+ import { CLIError } from '../error.js';
5
+ import { resolveKeyRef } from '../keystore/resolve-key-ref.js';
6
+ import { formatResult } from '../output.js';
7
+ /**
8
+ * Registers the `key` command group for managing keypairs in the encrypted
9
+ * keystore. All subcommands operate offline (no Bitcoin connection) through the
10
+ * keystore-backed KeyManager injected by the factory.
11
+ */
12
+ export function registerKeyCommand(program, factory, globals) {
13
+ const key = program.command('key').description('Manage keypairs in the encrypted keystore.');
14
+ const print = (result) => console.log(formatResult(result, globals()));
15
+ key
16
+ .command('generate')
17
+ .description('Generate a new keypair and store it.')
18
+ .option('--name <name>', 'A human-friendly name, stored as a tag and usable as a key reference.')
19
+ .option('--set-active', 'Make this the active key.', false)
20
+ .action((options) => {
21
+ const api = factory(undefined, globals());
22
+ assertNameAvailable(api.kms.kms, options.name);
23
+ const setActive = options.setActive ?? false;
24
+ const id = api.kms.generateKey({ ...(options.name && { tags: { name: options.name } }), setActive });
25
+ print({ action: 'key-generate', data: { keyId: id, publicKey: bytesToHex(api.kms.getPublicKey(id)), active: setActive } });
26
+ });
27
+ key
28
+ .command('list')
29
+ .alias('ls')
30
+ .description('List stored keys.')
31
+ .action(() => {
32
+ const kms = factory(undefined, globals()).kms.kms;
33
+ const active = kms.activeKeyId;
34
+ const data = kms.listKeys().map(id => {
35
+ const entry = kms.getEntry(id);
36
+ return {
37
+ keyId: id,
38
+ fingerprint: id.split(':').pop() ?? id,
39
+ ...(entry.tags?.name && { name: entry.tags.name }),
40
+ active: id === active,
41
+ };
42
+ });
43
+ print({ action: 'key-list', data });
44
+ });
45
+ key
46
+ .command('show <ref>')
47
+ .description('Show a key\'s public material and tags. Never prints the secret.')
48
+ .action((ref) => {
49
+ const kms = factory(undefined, globals()).kms.kms;
50
+ const id = resolveKeyRef(kms, ref);
51
+ const entry = kms.getEntry(id);
52
+ print({ action: 'key-show', data: { keyId: id, publicKey: bytesToHex(entry.publicKey), ...(entry.tags && { tags: entry.tags }) } });
53
+ });
54
+ key
55
+ .command('import')
56
+ .description('Import a key: a secret from a hex file, or a public key as watch-only.')
57
+ .option('--secret-file <path>', 'Path to a file containing a 32-byte secret key as hex.')
58
+ .option('--public <hex>', 'A 33-byte compressed public key as hex (imported watch-only).')
59
+ .option('--name <name>', 'A human-friendly name, stored as a tag.')
60
+ .option('--set-active', 'Make this the active key.', false)
61
+ .action((options) => {
62
+ if (Boolean(options.secretFile) === Boolean(options.public)) {
63
+ throw new CLIError('Provide exactly one of --secret-file or --public.', 'INVALID_ARGUMENT_ERROR');
64
+ }
65
+ const api = factory(undefined, globals());
66
+ assertNameAvailable(api.kms.kms, options.name);
67
+ const keyPair = options.secretFile
68
+ ? new SchnorrKeyPair({ secretKey: readHexFile(options.secretFile, 32, '--secret-file') })
69
+ : new SchnorrKeyPair({ publicKey: parseHex(options.public ?? '', 33, '--public') });
70
+ const setActive = options.setActive ?? false;
71
+ const id = api.kms.import(keyPair, { ...(options.name && { tags: { name: options.name } }), setActive });
72
+ print({ action: 'key-import', data: { keyId: id, publicKey: bytesToHex(api.kms.getPublicKey(id)), watchOnly: !options.secretFile, active: setActive } });
73
+ });
74
+ key
75
+ .command('export <ref>')
76
+ .description('Export a key. Public material by default; --secret writes the secret to a file.')
77
+ .option('--secret', 'Export the secret key. Requires --out.', false)
78
+ .option('--out <path>', 'Write the exported secret to this file (created 0600).')
79
+ .action((ref, options) => {
80
+ const api = factory(undefined, globals());
81
+ const id = resolveKeyRef(api.kms.kms, ref);
82
+ if (!options.secret) {
83
+ print({ action: 'key-export', data: { keyId: id, publicKey: bytesToHex(api.kms.getPublicKey(id)) } });
84
+ return;
85
+ }
86
+ if (!options.out) {
87
+ throw new CLIError('Exporting a secret requires --out <file> so it is not written to the terminal.', 'INVALID_ARGUMENT_ERROR');
88
+ }
89
+ const keyPair = api.kms.export(id);
90
+ if (!keyPair.hasSecretKey) {
91
+ throw new CLIError(`Key ${id} is watch-only and has no secret to export.`, 'INVALID_ARGUMENT_ERROR', { keyId: id });
92
+ }
93
+ process.stderr.write('warning: writing an unencrypted secret key to disk. Protect this file and delete it when done.\n');
94
+ writeSecretFile(options.out, bytesToHex(keyPair.secretKey.bytes));
95
+ print({ action: 'key-export', data: { keyId: id, secretWrittenTo: options.out } });
96
+ });
97
+ key
98
+ .command('delete <ref>')
99
+ .alias('rm')
100
+ .description('Delete a key from the keystore.')
101
+ .option('--force', 'Delete even if it is the active key.', false)
102
+ .action((ref, options) => {
103
+ const api = factory(undefined, globals());
104
+ const id = resolveKeyRef(api.kms.kms, ref);
105
+ api.kms.removeKey(id, { force: options.force ?? false });
106
+ print({ action: 'key-delete', data: { keyId: id, deleted: true } });
107
+ });
108
+ key
109
+ .command('use <ref>')
110
+ .description('Set the active key, persisted across invocations.')
111
+ .action((ref) => {
112
+ const api = factory(undefined, globals());
113
+ const id = resolveKeyRef(api.kms.kms, ref);
114
+ api.kms.setActive(id);
115
+ print({ action: 'key-use', data: { keyId: id, active: true } });
116
+ });
117
+ }
118
+ /** Throws if a name tag is already used by another key. */
119
+ function assertNameAvailable(kms, name) {
120
+ if (!name)
121
+ return;
122
+ if (kms.listKeys().some(id => kms.getEntry(id).tags?.name === name)) {
123
+ throw new CLIError(`A key named "${name}" already exists.`, 'INVALID_ARGUMENT_ERROR', { name });
124
+ }
125
+ }
126
+ /** Parses and length-checks a hex string into bytes. */
127
+ function parseHex(hex, expectedBytes, label) {
128
+ let bytes;
129
+ try {
130
+ bytes = hexToBytes(hex.trim());
131
+ }
132
+ catch {
133
+ throw new CLIError(`Invalid hex for ${label}.`, 'INVALID_ARGUMENT_ERROR', { label });
134
+ }
135
+ if (bytes.length !== expectedBytes) {
136
+ throw new CLIError(`${label} must be ${expectedBytes} bytes (${expectedBytes * 2} hex chars), got ${bytes.length}.`, 'INVALID_ARGUMENT_ERROR', { label });
137
+ }
138
+ return bytes;
139
+ }
140
+ /** Reads a file and parses its contents as length-checked hex bytes. */
141
+ function readHexFile(path, expectedBytes, label) {
142
+ let content;
143
+ try {
144
+ content = readFileSync(path, 'utf-8');
145
+ }
146
+ catch {
147
+ throw new CLIError(`Cannot read ${label} at ${path}.`, 'INVALID_ARGUMENT_ERROR', { label, path });
148
+ }
149
+ return parseHex(content, expectedBytes, label);
150
+ }
151
+ /**
152
+ * Writes an exported secret to a new file, created exclusively (O_CREAT|O_EXCL,
153
+ * mode 0600). The exclusive flag refuses to clobber an existing file or follow
154
+ * a pre-placed symlink, so the secret never lands in a loose-permissions or
155
+ * redirected target.
156
+ */
157
+ function writeSecretFile(path, contents) {
158
+ let fd;
159
+ try {
160
+ fd = openSync(path, 'wx', 0o600);
161
+ }
162
+ catch (error) {
163
+ if (error.code === 'EEXIST') {
164
+ throw new CLIError(`Refusing to overwrite existing file ${path}. Choose a new --out path.`, 'INVALID_ARGUMENT_ERROR', { path });
165
+ }
166
+ throw error;
167
+ }
168
+ try {
169
+ writeFileSync(fd, contents);
170
+ }
171
+ finally {
172
+ closeSync(fd);
173
+ }
174
+ }
175
+ //# sourceMappingURL=key.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"key.js","sourceRoot":"","sources":["../../../../src/commands/key.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ import { defaultConfigPath, readConfigFile, writeConfigFile } from '../config.js';
2
+ import { CLIError } from '../error.js';
3
+ import { formatResult } from '../output.js';
4
+ /** Registers the `profile` command group for managing configuration profiles. */
5
+ export function registerProfileCommand(program, globals) {
6
+ const profile = program.command('profile').description('Manage configuration profiles.');
7
+ const path = () => globals().config ?? defaultConfigPath();
8
+ const print = (result) => console.log(formatResult(result, globals()));
9
+ profile
10
+ .command('add <name>')
11
+ .description('Add an empty profile.')
12
+ .action((name) => {
13
+ writeConfigFile(path(), raw => {
14
+ if (raw.profiles === undefined || raw.profiles === null)
15
+ raw.profiles = {};
16
+ const profiles = raw.profiles;
17
+ if (profiles[name])
18
+ throw new CLIError(`Profile "${name}" already exists.`, 'INVALID_ARGUMENT_ERROR', { name });
19
+ profiles[name] = {};
20
+ });
21
+ print({ action: 'profile-add', data: { profile: name } });
22
+ });
23
+ profile
24
+ .command('use <name>')
25
+ .description('Set the active profile (writes defaults.profile).')
26
+ .action((name) => {
27
+ writeConfigFile(path(), raw => {
28
+ if (raw.defaults === undefined || raw.defaults === null)
29
+ raw.defaults = {};
30
+ raw.defaults.profile = name;
31
+ });
32
+ print({ action: 'profile-use', data: { profile: name } });
33
+ });
34
+ profile
35
+ .command('show [name]')
36
+ .description('Show a profile (defaults to the active profile).')
37
+ .action((name) => {
38
+ const file = readConfigFile(path()) ?? {};
39
+ const target = name ?? file.defaults?.profile;
40
+ if (!target) {
41
+ throw new CLIError('No profile specified and no active profile is set.', 'INVALID_ARGUMENT_ERROR');
42
+ }
43
+ const data = file.profiles?.[target];
44
+ if (!data) {
45
+ throw new CLIError(`Profile "${target}" not found.`, 'INVALID_ARGUMENT_ERROR', { profile: target });
46
+ }
47
+ print({ action: 'profile-show', data: { profile: target, ...data } });
48
+ });
49
+ profile
50
+ .command('remove <name>')
51
+ .alias('rm')
52
+ .description('Remove a profile.')
53
+ .action((name) => {
54
+ writeConfigFile(path(), raw => {
55
+ const profiles = raw.profiles;
56
+ if (!profiles?.[name])
57
+ throw new CLIError(`Profile "${name}" not found.`, 'INVALID_ARGUMENT_ERROR', { name });
58
+ delete profiles[name];
59
+ });
60
+ print({ action: 'profile-remove', data: { profile: name } });
61
+ });
62
+ }
63
+ //# sourceMappingURL=profile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile.js","sourceRoot":"","sources":["../../../../src/commands/profile.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,8 @@
1
+ import { KeyManagerSigner } from '@did-btcr2/key-manager';
1
2
  import { deriveNetwork } from '../config.js';
2
3
  import { CLIError } from '../error.js';
4
+ import { resolveKeyRef } from '../keystore/resolve-key-ref.js';
5
+ import { formatResult } from '../output.js';
3
6
  export function registerUpdateCommand(program, factory, globals) {
4
7
  program
5
8
  .command('update')
@@ -10,6 +13,9 @@ export function registerUpdateCommand(program, factory, globals) {
10
13
  .requiredOption('-m, --verification-method-id <id>', 'DID document verification method ID')
11
14
  .requiredOption('-b, --beacon-id <json>', 'Beacon ID as a JSON string', parseJsonArg('--beacon-id'))
12
15
  .action(async (options) => {
16
+ if (!/^\d+$/.test(options.sourceVersionId)) {
17
+ throw new CLIError('--source-version-id must be a non-negative integer.', 'INVALID_ARGUMENT_ERROR', { value: options.sourceVersionId });
18
+ }
13
19
  const parsed = {
14
20
  sourceDocument: options.sourceDocument,
15
21
  patches: options.patches,
@@ -21,15 +27,19 @@ export function registerUpdateCommand(program, factory, globals) {
21
27
  if (!did) {
22
28
  throw new CLIError('Source document must contain an "id" field.', 'INVALID_ARGUMENT_ERROR', options);
23
29
  }
24
- // The CLI does not yet have a way to load signing material (keystore,
25
- // KMS config, hardware wallet, etc.), so signed updates from the CLI are
26
- // not yet wired up. Drive the SDK directly with a `Signer` for now.
27
- // Variables above are kept so command parsing + validation still works.
28
- void deriveNetwork(did);
29
- void factory;
30
- void globals;
31
- void parsed;
32
- throw new CLIError('CLI signing is not yet implemented. Use @did-btcr2/api with a Signer directly.', 'NOT_IMPLEMENTED_ERROR', { command: 'update' });
30
+ const network = deriveNetwork(did);
31
+ const api = factory(network, globals());
32
+ const keyId = resolveKeyRef(api.kms.kms, globals().signingKey);
33
+ const signer = new KeyManagerSigner(api.kms.kms, keyId);
34
+ const data = await api.btcr2.update({
35
+ sourceDocument: parsed.sourceDocument,
36
+ patches: parsed.patches,
37
+ sourceVersionId: parsed.sourceVersionId,
38
+ verificationMethodId: parsed.verificationMethodId,
39
+ beaconId: parsed.beaconId,
40
+ signer,
41
+ });
42
+ console.log(formatResult({ action: 'update', data }, globals()));
33
43
  });
34
44
  }
35
45
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"update.js","sourceRoot":"","sources":["../../../../src/commands/update.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAmB,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGvC,MAAM,UAAU,qBAAqB,CACnC,OAAiB,EACjB,OAAoB,EACpB,OAA6B;IAE7B,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,8BAA8B,CAAC;SAC3C,cAAc,CACb,8BAA8B,EAC9B,oCAAoC,EACpC,YAAY,CAAC,mBAAmB,CAAC,CAClC;SACA,cAAc,CACb,8BAA8B,EAC9B,+BAA+B,CAChC;SACA,cAAc,CACb,sBAAsB,EACtB,8CAA8C,EAC9C,YAAY,CAAC,WAAW,CAAC,CAC1B;SACA,cAAc,CACb,mCAAmC,EACnC,qCAAqC,CACtC;SACA,cAAc,CACb,wBAAwB,EACxB,4BAA4B,EAC5B,YAAY,CAAC,aAAa,CAAC,CAC5B;SACA,MAAM,CAAC,KAAK,EAAE,OAMd,EAAE,EAAE;QACH,MAAM,MAAM,GAAyB;YACnC,cAAc,EAAS,OAAO,CAAC,cAAwD;YACvF,OAAO,EAAgB,OAAO,CAAC,OAA0C;YACzE,eAAe,EAAQ,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC;YACtD,oBAAoB,EAAG,OAAO,CAAC,oBAAoB;YACnD,QAAQ,EAAe,OAAO,CAAC,QAA4C;SAC5E,CAAC;QACF,MAAM,GAAG,GAAG,MAAM,CAAC,cAAc,EAAE,EAAE,CAAC;QACtC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,QAAQ,CAChB,6CAA6C,EAC7C,wBAAwB,EACxB,OAAO,CACR,CAAC;QACJ,CAAC;QACD,sEAAsE;QACtE,yEAAyE;QACzE,oEAAoE;QACpE,wEAAwE;QACxE,KAAK,aAAa,CAAC,GAAG,CAAC,CAAC;QACxB,KAAK,OAAO,CAAC;QACb,KAAK,OAAO,CAAC;QACb,KAAK,MAAM,CAAC;QACZ,MAAM,IAAI,QAAQ,CAChB,gFAAgF,EAChF,uBAAuB,EACvB,EAAE,OAAO,EAAE,QAAQ,EAAE,CACtB,CAAC;IACJ,CAAC,CAAC,CAAC;AACP,CAAC;AAED;;;GAGG;AACH,SAAS,YAAY,CAAC,QAAgB;IACpC,OAAO,CAAC,KAAa,EAAW,EAAE;QAChC,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,QAAQ,CAChB,oBAAoB,QAAQ,gCAAgC,EAC5D,wBAAwB,EACxB,EAAE,QAAQ,EAAE,KAAK,EAAE,CACpB,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"update.js","sourceRoot":"","sources":["../../../../src/commands/update.ts"],"names":[],"mappings":"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"}