@certen.io/cli 0.7.0 → 0.7.1
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/CHANGELOG.md +24 -0
- package/dist/commands/pending.d.ts +19 -0
- package/dist/commands/pending.js +105 -15
- package/dist/commands/pending.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# Changelog — @certen.io/cli
|
|
2
2
|
|
|
3
|
+
## 0.7.1 — sign a pending transaction by hash
|
|
4
|
+
|
|
5
|
+
### Added — `certen pending sign <target>` accepts what people actually have
|
|
6
|
+
|
|
7
|
+
A pending transaction was signable only by its inbox UUID. But the id a person is holding usually
|
|
8
|
+
comes from the explorer, from `queryTx`, or from a `/v1/sign` response — and that is a transaction
|
|
9
|
+
hash or a TxID, not an inbox id. The gap forced a lookup to translate one into the other, and got
|
|
10
|
+
an opaque gateway 400 when they guessed.
|
|
11
|
+
|
|
12
|
+
All four forms now resolve, with no `--type` flag to get wrong:
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
certen pending sign 4f3c…-…-… # inbox id (UUID) -> pending_action
|
|
16
|
+
certen pending sign 882d1793…b1ad811 # 64-hex hash -> pending_tx
|
|
17
|
+
certen pending sign 0x882d1793…b1ad811 # the same, 0x-prefixed
|
|
18
|
+
certen pending sign acc://882d…@panel.acme # TxID, as pasted
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The forms are disjoint, so the type is inferred rather than declared. Resolution lives in
|
|
22
|
+
`@certen.io/sdk` (`resolveSignTarget`) and is shared with the MCP server — two copies would drift,
|
|
23
|
+
and a drifted resolver signs the wrong preimage: a valid signature attached to nothing.
|
|
24
|
+
|
|
25
|
+
An unrecognised target is refused with `INVALID_SIGN_TARGET` and never guessed at.
|
|
26
|
+
|
|
3
27
|
## 0.7.0 — one response shape
|
|
4
28
|
|
|
5
29
|
**Breaking for `--json` consumers.** Requires a gateway from 2026-08 or later.
|
|
@@ -1,2 +1,21 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
+
/**
|
|
3
|
+
* Render a transaction memo for a terminal.
|
|
4
|
+
*
|
|
5
|
+
* The memo is the only field that says what a pending transaction is FOR, and it matters most for
|
|
6
|
+
* the ones the signer did not create — an authority transaction is pending on someone else's
|
|
7
|
+
* account, so without it the inbox offers only `writeData` and an unfamiliar URL.
|
|
8
|
+
*
|
|
9
|
+
* It is also written by whoever built that transaction, who is NOT the person being asked to sign.
|
|
10
|
+
* So it is sanitised before it reaches a terminal:
|
|
11
|
+
*
|
|
12
|
+
* - ANSI/control characters are stripped. A memo carrying escape codes could otherwise repaint the
|
|
13
|
+
* line, hide text, or forge output that looks like it came from the CLI.
|
|
14
|
+
* - Newlines collapse to spaces, so one row cannot masquerade as several.
|
|
15
|
+
* - Truncated, so a long memo cannot push the rest of the inbox off screen.
|
|
16
|
+
*
|
|
17
|
+
* A missing memo is reported as missing rather than blank — "no memo" is information: it means
|
|
18
|
+
* nobody said why this needs signing.
|
|
19
|
+
*/
|
|
20
|
+
export declare function describeMemo(memo: string | null | undefined): string;
|
|
2
21
|
export declare function registerPendingCommands(program: Command): void;
|
package/dist/commands/pending.js
CHANGED
|
@@ -1,10 +1,38 @@
|
|
|
1
|
-
import { CertenClient } from '@certen.io/sdk';
|
|
1
|
+
import { CertenClient, resolveSignTarget } from '@certen.io/sdk';
|
|
2
2
|
import { getApiKey, getApiUrl } from '../config.js';
|
|
3
|
-
import { printOutput, hint, isJsonMode } from '../output.js';
|
|
3
|
+
import { printOutput, hint, human, isJsonMode } from '../output.js';
|
|
4
4
|
import { resolveSignature } from '../signer.js';
|
|
5
|
+
import { UsageError } from '../errors.js';
|
|
5
6
|
async function getClient() {
|
|
6
7
|
return new CertenClient({ apiKey: await getApiKey(), baseUrl: getApiUrl() });
|
|
7
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* Render a transaction memo for a terminal.
|
|
11
|
+
*
|
|
12
|
+
* The memo is the only field that says what a pending transaction is FOR, and it matters most for
|
|
13
|
+
* the ones the signer did not create — an authority transaction is pending on someone else's
|
|
14
|
+
* account, so without it the inbox offers only `writeData` and an unfamiliar URL.
|
|
15
|
+
*
|
|
16
|
+
* It is also written by whoever built that transaction, who is NOT the person being asked to sign.
|
|
17
|
+
* So it is sanitised before it reaches a terminal:
|
|
18
|
+
*
|
|
19
|
+
* - ANSI/control characters are stripped. A memo carrying escape codes could otherwise repaint the
|
|
20
|
+
* line, hide text, or forge output that looks like it came from the CLI.
|
|
21
|
+
* - Newlines collapse to spaces, so one row cannot masquerade as several.
|
|
22
|
+
* - Truncated, so a long memo cannot push the rest of the inbox off screen.
|
|
23
|
+
*
|
|
24
|
+
* A missing memo is reported as missing rather than blank — "no memo" is information: it means
|
|
25
|
+
* nobody said why this needs signing.
|
|
26
|
+
*/
|
|
27
|
+
export function describeMemo(memo) {
|
|
28
|
+
if (!memo)
|
|
29
|
+
return 'memo: (none given)';
|
|
30
|
+
// eslint-disable-next-line no-control-regex
|
|
31
|
+
const clean = memo.replace(/[\u0000-\u001F\u007F-\u009F]/g, ' ').replace(/\s+/g, ' ').trim();
|
|
32
|
+
if (!clean)
|
|
33
|
+
return 'memo: (none given)';
|
|
34
|
+
return `memo: ${clean.length > 120 ? `${clean.slice(0, 117)}...` : clean}`;
|
|
35
|
+
}
|
|
8
36
|
export function registerPendingCommands(program) {
|
|
9
37
|
const pending = program.command('pending').description('Pending actions inbox');
|
|
10
38
|
pending
|
|
@@ -24,25 +52,81 @@ export function registerPendingCommands(program) {
|
|
|
24
52
|
limit: opts.limit,
|
|
25
53
|
offset: opts.offset,
|
|
26
54
|
});
|
|
27
|
-
|
|
55
|
+
// machineOnly: the generic table flattens `actions[]` into something unreadable, and the
|
|
56
|
+
// memo — the one field that says what each item IS — would be lost in it.
|
|
57
|
+
printOutput(result, { machineOnly: true });
|
|
58
|
+
if (isJsonMode())
|
|
59
|
+
return;
|
|
60
|
+
const actions = result.actions ?? [];
|
|
61
|
+
if (actions.length === 0) {
|
|
62
|
+
human('(nothing pending)');
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
for (const a of actions) {
|
|
66
|
+
// Principal before type: for an authority transaction it is an account the signer does
|
|
67
|
+
// NOT own, and that is the thing worth noticing.
|
|
68
|
+
human(`${a.id} ${a.type ?? '?'} ${a.principal ?? ''}`);
|
|
69
|
+
human(` ${describeMemo(a.memo)}`);
|
|
70
|
+
human(` status=${a.status ?? '?'} signed=${a.user_has_signed ? 'yes' : 'no'}`
|
|
71
|
+
+ (a.expires_at ? ` expires=${a.expires_at}` : ''));
|
|
72
|
+
}
|
|
28
73
|
});
|
|
29
74
|
pending
|
|
30
|
-
.command('sign <
|
|
31
|
-
.description('Create a sign request for a pending action')
|
|
32
|
-
.option('--identity <id>', 'Identity to sign as')
|
|
33
|
-
.option('--signer-url <url>', 'Signer URL')
|
|
75
|
+
.command('sign <target>')
|
|
76
|
+
.description('Create a sign request for a pending action (inbox id) or a pending transaction (hash or TxID)')
|
|
77
|
+
.option('--identity <id>', 'Identity to sign as (required with a transaction hash)')
|
|
78
|
+
.option('--signer-url <url>', 'Signer URL (required with a transaction hash)')
|
|
79
|
+
.option('--public-key <hex>', 'Public key that will sign, 64-char hex (required with a transaction hash)')
|
|
34
80
|
// Was documented as "accept/reject". The API takes a lowercase `approve` | `reject` |
|
|
35
81
|
// `abstain`; `accept` is rejected. The help text was sending people to a value that fails.
|
|
36
82
|
.option('--vote <vote>', 'Vote: approve | reject | abstain')
|
|
37
|
-
.action(async (
|
|
83
|
+
.action(async (rawTarget, opts) => {
|
|
84
|
+
// Inferred from the argument, not from a flag: an inbox id is a UUID and a transaction is a
|
|
85
|
+
// 64-hex hash, so the two are disjoint and a --type flag would only be a new way to get it
|
|
86
|
+
// wrong. Resolution happens BEFORE the client is built, so a bad target never opens a
|
|
87
|
+
// connection or reads a key.
|
|
88
|
+
let target;
|
|
89
|
+
try {
|
|
90
|
+
target = resolveSignTarget(rawTarget);
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
throw new UsageError(err.message, 'INVALID_SIGN_TARGET');
|
|
94
|
+
}
|
|
95
|
+
let params;
|
|
96
|
+
if (target.type === 'pending_tx') {
|
|
97
|
+
// A raw transaction has no inbox row behind it, so nothing derives these. Fail here with
|
|
98
|
+
// the CLI's own usage error rather than letting the gateway answer 400 — the caller can
|
|
99
|
+
// tell "you left a flag out" from "the gateway refused" only if we say so.
|
|
100
|
+
const missing = [
|
|
101
|
+
['identity', opts.identity],
|
|
102
|
+
['signer-url', opts.signerUrl],
|
|
103
|
+
['public-key', opts.publicKey],
|
|
104
|
+
].filter(([, v]) => !v).map(([flag]) => flag);
|
|
105
|
+
if (missing.length > 0) {
|
|
106
|
+
throw new UsageError(`signing by transaction hash requires --${missing.join(', --')}. `
|
|
107
|
+
+ 'An inbox id (UUID) derives these automatically; a raw transaction does not.', 'MISSING_SIGNER_DETAILS');
|
|
108
|
+
}
|
|
109
|
+
params = {
|
|
110
|
+
type: 'pending_tx',
|
|
111
|
+
targetId: target.targetId,
|
|
112
|
+
identity: opts.identity,
|
|
113
|
+
signerUrl: opts.signerUrl,
|
|
114
|
+
publicKey: opts.publicKey,
|
|
115
|
+
vote: opts.vote,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
params = {
|
|
120
|
+
type: 'pending_action',
|
|
121
|
+
targetId: target.targetId,
|
|
122
|
+
identity: opts.identity,
|
|
123
|
+
signerUrl: opts.signerUrl,
|
|
124
|
+
publicKey: opts.publicKey,
|
|
125
|
+
vote: opts.vote,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
38
128
|
const client = await getClient();
|
|
39
|
-
const result = await client.sign.create(
|
|
40
|
-
type: 'pending_action',
|
|
41
|
-
targetId: id,
|
|
42
|
-
identity: opts.identity,
|
|
43
|
-
signerUrl: opts.signerUrl,
|
|
44
|
-
vote: opts.vote,
|
|
45
|
-
});
|
|
129
|
+
const result = await client.sign.create(params);
|
|
46
130
|
printOutput(result);
|
|
47
131
|
if (isJsonMode())
|
|
48
132
|
return;
|
|
@@ -55,6 +139,12 @@ export function registerPendingCommands(program) {
|
|
|
55
139
|
hint('');
|
|
56
140
|
hint('This opened a sign request — the vote is not cast until the signature is submitted:');
|
|
57
141
|
hint(` certen pending submit ${requestId} --sign-with <key> --hash ${hash}`);
|
|
142
|
+
if (target.type === 'pending_tx') {
|
|
143
|
+
// The signing data was computed FOR the key named by --public-key, and the vote is folded
|
|
144
|
+
// into the preimage. A signature from any other key verifies against nothing, which fails
|
|
145
|
+
// silently — the transaction simply stays pending.
|
|
146
|
+
hint(` (sign with the key for --public-key ${opts.publicKey}; no other key fits this request)`);
|
|
147
|
+
}
|
|
58
148
|
}
|
|
59
149
|
});
|
|
60
150
|
pending
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pending.js","sourceRoot":"","sources":["../../src/commands/pending.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"pending.js","sourceRoot":"","sources":["../../src/commands/pending.ts"],"names":[],"mappings":"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"}
|