@provos/ironcurtain 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/LICENSE +0 -1
  2. package/README.md +20 -1
  3. package/dist/cli.js +15 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/config/config-command.d.ts +1 -0
  6. package/dist/config/config-command.js +138 -34
  7. package/dist/config/config-command.js.map +1 -1
  8. package/dist/config/constitution-user-base.md +2 -0
  9. package/dist/config/first-start.js +31 -3
  10. package/dist/config/first-start.js.map +1 -1
  11. package/dist/config/generated/compiled-policy.json +158 -64
  12. package/dist/config/generated/test-scenarios.json +144 -293
  13. package/dist/config/generated/tool-annotations.json +17 -3
  14. package/dist/config/index.js +49 -17
  15. package/dist/config/index.js.map +1 -1
  16. package/dist/config/paths.js +9 -4
  17. package/dist/config/paths.js.map +1 -1
  18. package/dist/config/user-config.d.ts +47 -0
  19. package/dist/config/user-config.js +97 -4
  20. package/dist/config/user-config.js.map +1 -1
  21. package/dist/docker/adapters/claude-code.js +14 -3
  22. package/dist/docker/adapters/claude-code.js.map +1 -1
  23. package/dist/docker/agent-adapter.d.ts +2 -0
  24. package/dist/docker/audit-log-tailer.d.ts +4 -3
  25. package/dist/docker/audit-log-tailer.js +9 -7
  26. package/dist/docker/audit-log-tailer.js.map +1 -1
  27. package/dist/docker/docker-agent-session.d.ts +11 -0
  28. package/dist/docker/docker-agent-session.js +103 -22
  29. package/dist/docker/docker-agent-session.js.map +1 -1
  30. package/dist/docker/docker-manager.js +82 -15
  31. package/dist/docker/docker-manager.js.map +1 -1
  32. package/dist/docker/managed-proxy.d.ts +7 -3
  33. package/dist/docker/managed-proxy.js +98 -8
  34. package/dist/docker/managed-proxy.js.map +1 -1
  35. package/dist/docker/mitm-proxy.d.ts +7 -4
  36. package/dist/docker/mitm-proxy.js +152 -62
  37. package/dist/docker/mitm-proxy.js.map +1 -1
  38. package/dist/docker/orientation.d.ts +1 -1
  39. package/dist/docker/orientation.js +5 -2
  40. package/dist/docker/orientation.js.map +1 -1
  41. package/dist/docker/platform.d.ts +20 -0
  42. package/dist/docker/platform.js +24 -0
  43. package/dist/docker/platform.js.map +1 -0
  44. package/dist/docker/provider-config.d.ts +38 -2
  45. package/dist/docker/provider-config.js +61 -0
  46. package/dist/docker/provider-config.js.map +1 -1
  47. package/dist/docker/types.d.ts +48 -6
  48. package/dist/pipeline/compile.js +2 -2
  49. package/dist/pipeline/compile.js.map +1 -1
  50. package/dist/pipeline/constitution-compiler.js +5 -2
  51. package/dist/pipeline/constitution-compiler.js.map +1 -1
  52. package/dist/pipeline/handwritten-scenarios.js +9 -10
  53. package/dist/pipeline/handwritten-scenarios.js.map +1 -1
  54. package/dist/pipeline/policy-verifier.d.ts +1 -1
  55. package/dist/pipeline/policy-verifier.js +7 -4
  56. package/dist/pipeline/policy-verifier.js.map +1 -1
  57. package/dist/pipeline/types.d.ts +7 -1
  58. package/dist/servers/fetch-server.d.ts +4 -3
  59. package/dist/servers/fetch-server.js +72 -10
  60. package/dist/servers/fetch-server.js.map +1 -1
  61. package/dist/servers/search-providers.d.ts +29 -0
  62. package/dist/servers/search-providers.js +156 -0
  63. package/dist/servers/search-providers.js.map +1 -0
  64. package/dist/session/index.js +16 -6
  65. package/dist/session/index.js.map +1 -1
  66. package/dist/signal/bot-command.d.ts +13 -0
  67. package/dist/signal/bot-command.js +54 -0
  68. package/dist/signal/bot-command.js.map +1 -0
  69. package/dist/signal/format.d.ts +31 -0
  70. package/dist/signal/format.js +101 -0
  71. package/dist/signal/format.js.map +1 -0
  72. package/dist/signal/index.d.ts +16 -0
  73. package/dist/signal/index.js +13 -0
  74. package/dist/signal/index.js.map +1 -0
  75. package/dist/signal/markdown-to-signal.d.ts +29 -0
  76. package/dist/signal/markdown-to-signal.js +154 -0
  77. package/dist/signal/markdown-to-signal.js.map +1 -0
  78. package/dist/signal/setup-signal.d.ts +48 -0
  79. package/dist/signal/setup-signal.js +443 -0
  80. package/dist/signal/setup-signal.js.map +1 -0
  81. package/dist/signal/signal-bot-daemon.d.ts +142 -0
  82. package/dist/signal/signal-bot-daemon.js +504 -0
  83. package/dist/signal/signal-bot-daemon.js.map +1 -0
  84. package/dist/signal/signal-config.d.ts +64 -0
  85. package/dist/signal/signal-config.js +53 -0
  86. package/dist/signal/signal-config.js.map +1 -0
  87. package/dist/signal/signal-container.d.ts +37 -0
  88. package/dist/signal/signal-container.js +112 -0
  89. package/dist/signal/signal-container.js.map +1 -0
  90. package/dist/signal/signal-transport.d.ts +34 -0
  91. package/dist/signal/signal-transport.js +70 -0
  92. package/dist/signal/signal-transport.js.map +1 -0
  93. package/dist/trusted-process/mcp-proxy-server.js +34 -3
  94. package/dist/trusted-process/mcp-proxy-server.js.map +1 -1
  95. package/dist/trusted-process/path-utils.d.ts +5 -1
  96. package/dist/trusted-process/path-utils.js +47 -4
  97. package/dist/trusted-process/path-utils.js.map +1 -1
  98. package/dist/trusted-process/tcp-server-transport.d.ts +43 -0
  99. package/dist/trusted-process/tcp-server-transport.js +119 -0
  100. package/dist/trusted-process/tcp-server-transport.js.map +1 -0
  101. package/dist/types/argument-roles.js +20 -5
  102. package/dist/types/argument-roles.js.map +1 -1
  103. package/docker/Dockerfile.base.arm64 +23 -0
  104. package/package.json +6 -3
  105. package/src/config/constitution-user-base.md +2 -0
  106. package/src/config/generated/compiled-policy.json +158 -64
  107. package/src/config/generated/test-scenarios.json +144 -293
  108. package/src/config/generated/tool-annotations.json +17 -3
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Formatting utilities for Signal messages.
3
+ *
4
+ * All functions produce plain text with Signal's styled markup
5
+ * (**bold**, *italic*, `mono`, ~strike~). Output is intended
6
+ * to be sent with `text_mode: "styled"`.
7
+ */
8
+ import type { EscalationRequest, BudgetStatus } from '../session/types.js';
9
+ /** Maximum length for a single Signal message. */
10
+ export declare const SIGNAL_MAX_MESSAGE_LENGTH = 2000;
11
+ /**
12
+ * Formats an escalation request as a styled text banner.
13
+ * Includes tool name, arguments, reason, and instructions
14
+ * for the user to reply "approve" or "deny".
15
+ */
16
+ export declare function formatEscalationBanner(request: EscalationRequest): string;
17
+ /**
18
+ * Formats budget status for the /budget command.
19
+ * Shows current turn consumption and session totals.
20
+ */
21
+ export declare function formatBudgetMessage(status: BudgetStatus): string;
22
+ /**
23
+ * Formats a compact budget summary for session end messages.
24
+ */
25
+ export declare function formatBudgetSummary(status: BudgetStatus): string;
26
+ /**
27
+ * Splits a message into chunks respecting the max length.
28
+ * Prefers splitting at double-newlines (paragraph breaks),
29
+ * then single newlines, then at the hard limit.
30
+ */
31
+ export declare function splitMessage(text: string, maxLength: number): string[];
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Formatting utilities for Signal messages.
3
+ *
4
+ * All functions produce plain text with Signal's styled markup
5
+ * (**bold**, *italic*, `mono`, ~strike~). Output is intended
6
+ * to be sent with `text_mode: "styled"`.
7
+ */
8
+ /** Maximum length for a single Signal message. */
9
+ export const SIGNAL_MAX_MESSAGE_LENGTH = 2000;
10
+ /**
11
+ * Formats an escalation request as a styled text banner.
12
+ * Includes tool name, arguments, reason, and instructions
13
+ * for the user to reply "approve" or "deny".
14
+ */
15
+ export function formatEscalationBanner(request) {
16
+ const separator = '\u2501'.repeat(30); // box drawing heavy horizontal
17
+ const header = '**ESCALATION: Human approval required**';
18
+ const toolLine = `Tool: \`${request.serverName}/${request.toolName}\``;
19
+ const argsLine = `Arguments: \`${JSON.stringify(request.arguments)}\``;
20
+ const reasonLine = `Reason: *${request.reason}*`;
21
+ const instructions = '**Reply "approve" or "deny"**';
22
+ return [separator, header, separator, toolLine, argsLine, reasonLine, separator, instructions, separator].join('\n');
23
+ }
24
+ /**
25
+ * Formats budget status for the /budget command.
26
+ * Shows current turn consumption and session totals.
27
+ */
28
+ export function formatBudgetMessage(status) {
29
+ const { limits, cumulative } = status;
30
+ const lines = ['**Current turn budget:**'];
31
+ if (status.tokenTrackingAvailable) {
32
+ lines.push(formatBudgetLine('Tokens', status.totalTokens, limits.maxTotalTokens, (v) => v.toLocaleString()));
33
+ }
34
+ else {
35
+ lines.push(' Tokens: N/A');
36
+ }
37
+ lines.push(formatBudgetLine('Steps', status.stepCount, limits.maxSteps, String));
38
+ lines.push(formatBudgetLine('Time', status.elapsedSeconds, limits.maxSessionSeconds, (v) => `${Math.round(v)}s`));
39
+ lines.push(formatBudgetLine('Est. cost', status.estimatedCostUsd, limits.maxEstimatedCostUsd, (v) => `$${v.toFixed(2)}`));
40
+ lines.push('');
41
+ lines.push('**Session totals:**');
42
+ if (status.tokenTrackingAvailable) {
43
+ lines.push(` Tokens: ${cumulative.totalTokens.toLocaleString()}`);
44
+ }
45
+ else {
46
+ lines.push(' Tokens: N/A');
47
+ }
48
+ lines.push(` Steps: ${cumulative.stepCount}`);
49
+ lines.push(` Active time: ${Math.round(cumulative.activeSeconds)}s`);
50
+ lines.push(` Est. cost: $${cumulative.estimatedCostUsd.toFixed(2)}`);
51
+ return lines.join('\n');
52
+ }
53
+ /**
54
+ * Formats a compact budget summary for session end messages.
55
+ */
56
+ export function formatBudgetSummary(status) {
57
+ const { cumulative } = status;
58
+ const tokensPart = status.tokenTrackingAvailable ? `${cumulative.totalTokens.toLocaleString()} tokens, ` : '';
59
+ return (`Session: ${tokensPart}` +
60
+ `${cumulative.stepCount} steps` +
61
+ `, ${Math.round(cumulative.activeSeconds)}s` +
62
+ `, ~$${cumulative.estimatedCostUsd.toFixed(2)}`);
63
+ }
64
+ /**
65
+ * Splits a message into chunks respecting the max length.
66
+ * Prefers splitting at double-newlines (paragraph breaks),
67
+ * then single newlines, then at the hard limit.
68
+ */
69
+ export function splitMessage(text, maxLength) {
70
+ if (text.length <= maxLength)
71
+ return [text];
72
+ const chunks = [];
73
+ let remaining = text;
74
+ while (remaining.length > maxLength) {
75
+ // Try to find a paragraph break within the limit
76
+ let splitIdx = remaining.lastIndexOf('\n\n', maxLength);
77
+ if (splitIdx <= 0) {
78
+ // Fall back to line break
79
+ splitIdx = remaining.lastIndexOf('\n', maxLength);
80
+ }
81
+ if (splitIdx <= 0) {
82
+ // Hard split at max length
83
+ splitIdx = maxLength;
84
+ }
85
+ chunks.push(remaining.substring(0, splitIdx).trimEnd());
86
+ remaining = remaining.substring(splitIdx).trimStart();
87
+ }
88
+ if (remaining.length > 0) {
89
+ chunks.push(remaining);
90
+ }
91
+ return chunks;
92
+ }
93
+ // --- Private helpers ---
94
+ function formatBudgetLine(label, current, limit, format) {
95
+ const currentStr = format(current);
96
+ if (limit === null)
97
+ return ` ${label}: ${currentStr} (no limit)`;
98
+ const pct = limit > 0 ? Math.round((current / limit) * 100) : 0;
99
+ return ` ${label}: ${currentStr} / ${format(limit)} (${pct}%)`;
100
+ }
101
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/signal/format.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Signal transport module public API.
3
+ */
4
+ export { SignalBotDaemon } from './signal-bot-daemon.js';
5
+ export type { SignalBotDaemonOptions, SignalEnvelope } from './signal-bot-daemon.js';
6
+ export { parseSignalEnvelope, isAuthorizedSender, normalizePhoneNumber } from './signal-bot-daemon.js';
7
+ export { SignalSessionTransport } from './signal-transport.js';
8
+ export { createSignalContainerManager } from './signal-container.js';
9
+ export type { SignalContainerConfig, SignalContainerManager } from './signal-container.js';
10
+ export { resolveSignalConfig, getSignalDataDir, SIGNAL_DEFAULTS } from './signal-config.js';
11
+ export type { SignalConfig, ResolvedSignalConfig } from './signal-config.js';
12
+ export { markdownToSignal } from './markdown-to-signal.js';
13
+ export { formatEscalationBanner, formatBudgetMessage, formatBudgetSummary, splitMessage, SIGNAL_MAX_MESSAGE_LENGTH, } from './format.js';
14
+ export { runBot } from './bot-command.js';
15
+ export type { BotOptions } from './bot-command.js';
16
+ export { runSignalSetup } from './setup-signal.js';
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Signal transport module public API.
3
+ */
4
+ export { SignalBotDaemon } from './signal-bot-daemon.js';
5
+ export { parseSignalEnvelope, isAuthorizedSender, normalizePhoneNumber } from './signal-bot-daemon.js';
6
+ export { SignalSessionTransport } from './signal-transport.js';
7
+ export { createSignalContainerManager } from './signal-container.js';
8
+ export { resolveSignalConfig, getSignalDataDir, SIGNAL_DEFAULTS } from './signal-config.js';
9
+ export { markdownToSignal } from './markdown-to-signal.js';
10
+ export { formatEscalationBanner, formatBudgetMessage, formatBudgetSummary, splitMessage, SIGNAL_MAX_MESSAGE_LENGTH, } from './format.js';
11
+ export { runBot } from './bot-command.js';
12
+ export { runSignalSetup } from './setup-signal.js';
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/signal/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAEvG,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,OAAO,EAAE,4BAA4B,EAAE,MAAM,uBAAuB,CAAC;AAGrE,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAG5F,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,EACL,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,EACnB,YAAY,EACZ,yBAAyB,GAC1B,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAG1C,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Converts Markdown to Signal-compatible styled text.
3
+ *
4
+ * Signal's styled text mode supports a subset of inline Markdown:
5
+ * **bold**, *italic*, `mono`, ~strike~ (single tilde).
6
+ *
7
+ * Block-level elements (headings, code blocks, blockquotes, lists)
8
+ * are mapped to plain text with structural whitespace since Signal
9
+ * has no native block formatting.
10
+ *
11
+ * Uses the `marked` lexer to produce an AST, then walks it to emit
12
+ * Signal-compatible markup. This avoids regex-based conversion which
13
+ * would be fragile with nested or overlapping markup.
14
+ */
15
+ /**
16
+ * Converts a Markdown string to Signal-compatible styled text.
17
+ *
18
+ * The returned string contains Signal's inline markup syntax
19
+ * (**bold**, *italic*, `mono`, ~strike~) and is intended to be
20
+ * sent with `text_mode: "styled"` via the signal-cli REST API.
21
+ *
22
+ * Limitations:
23
+ * - No syntax highlighting in code blocks
24
+ * - Headers are bold text, not visually distinct sizes
25
+ * - Tables are rendered as monospace text
26
+ * - Images are replaced with "[Image: alt]" placeholder
27
+ * - Nested blockquotes lose depth distinction
28
+ */
29
+ export declare function markdownToSignal(markdown: string): string;
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Converts Markdown to Signal-compatible styled text.
3
+ *
4
+ * Signal's styled text mode supports a subset of inline Markdown:
5
+ * **bold**, *italic*, `mono`, ~strike~ (single tilde).
6
+ *
7
+ * Block-level elements (headings, code blocks, blockquotes, lists)
8
+ * are mapped to plain text with structural whitespace since Signal
9
+ * has no native block formatting.
10
+ *
11
+ * Uses the `marked` lexer to produce an AST, then walks it to emit
12
+ * Signal-compatible markup. This avoids regex-based conversion which
13
+ * would be fragile with nested or overlapping markup.
14
+ */
15
+ import { marked } from 'marked';
16
+ /**
17
+ * Converts a Markdown string to Signal-compatible styled text.
18
+ *
19
+ * The returned string contains Signal's inline markup syntax
20
+ * (**bold**, *italic*, `mono`, ~strike~) and is intended to be
21
+ * sent with `text_mode: "styled"` via the signal-cli REST API.
22
+ *
23
+ * Limitations:
24
+ * - No syntax highlighting in code blocks
25
+ * - Headers are bold text, not visually distinct sizes
26
+ * - Tables are rendered as monospace text
27
+ * - Images are replaced with "[Image: alt]" placeholder
28
+ * - Nested blockquotes lose depth distinction
29
+ */
30
+ export function markdownToSignal(markdown) {
31
+ const tokens = marked.lexer(markdown);
32
+ const output = [];
33
+ function emit(text) {
34
+ output.push(text);
35
+ }
36
+ function walkTokens(tokens) {
37
+ for (const token of tokens) {
38
+ switch (token.type) {
39
+ case 'heading': {
40
+ const heading = token;
41
+ emit('**');
42
+ walkInline(heading.tokens);
43
+ emit('**\n\n');
44
+ break;
45
+ }
46
+ case 'paragraph': {
47
+ const paragraph = token;
48
+ walkInline(paragraph.tokens);
49
+ emit('\n\n');
50
+ break;
51
+ }
52
+ case 'code': {
53
+ const code = token;
54
+ emit('`');
55
+ emit(code.text);
56
+ emit('`');
57
+ emit('\n\n');
58
+ break;
59
+ }
60
+ case 'blockquote': {
61
+ const blockquote = token;
62
+ emit('| ');
63
+ walkTokens(blockquote.tokens);
64
+ break;
65
+ }
66
+ case 'list': {
67
+ const list = token;
68
+ let idx = list.start || 1;
69
+ for (const item of list.items) {
70
+ emit(list.ordered ? `${idx}. ` : '- ');
71
+ walkTokens(item.tokens);
72
+ idx++;
73
+ }
74
+ break;
75
+ }
76
+ case 'space':
77
+ emit('\n');
78
+ break;
79
+ case 'hr':
80
+ emit('---\n\n');
81
+ break;
82
+ default:
83
+ if ('text' in token && typeof token.text === 'string') {
84
+ emit(token.text);
85
+ }
86
+ break;
87
+ }
88
+ }
89
+ }
90
+ function walkInline(tokens) {
91
+ if (!tokens)
92
+ return;
93
+ for (const token of tokens) {
94
+ switch (token.type) {
95
+ case 'strong': {
96
+ const strong = token;
97
+ emit('**');
98
+ walkInline(strong.tokens);
99
+ emit('**');
100
+ break;
101
+ }
102
+ case 'em': {
103
+ const em = token;
104
+ emit('*');
105
+ walkInline(em.tokens);
106
+ emit('*');
107
+ break;
108
+ }
109
+ case 'codespan': {
110
+ const codespan = token;
111
+ emit('`');
112
+ emit(codespan.text);
113
+ emit('`');
114
+ break;
115
+ }
116
+ case 'del': {
117
+ // Markdown ~~ -> Signal single ~
118
+ const del = token;
119
+ emit('~');
120
+ walkInline(del.tokens);
121
+ emit('~');
122
+ break;
123
+ }
124
+ case 'link': {
125
+ const link = token;
126
+ walkInline(link.tokens);
127
+ emit(` (${link.href})`);
128
+ break;
129
+ }
130
+ case 'image': {
131
+ const image = token;
132
+ emit(`[Image: ${image.text || 'no description'}]`);
133
+ break;
134
+ }
135
+ case 'text': {
136
+ const textToken = token;
137
+ emit(textToken.text);
138
+ break;
139
+ }
140
+ case 'br':
141
+ emit('\n');
142
+ break;
143
+ default:
144
+ if ('text' in token && typeof token.text === 'string') {
145
+ emit(token.text);
146
+ }
147
+ break;
148
+ }
149
+ }
150
+ }
151
+ walkTokens(tokens);
152
+ return output.join('').trimEnd();
153
+ }
154
+ //# sourceMappingURL=markdown-to-signal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown-to-signal.js","sourceRoot":"","sources":["../../src/signal/markdown-to-signal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Interactive Signal onboarding wizard.
3
+ *
4
+ * Implements `ironcurtain setup-signal` with two modes:
5
+ * - Full setup: Docker check, container start, registration,
6
+ * recipient identity verification, and config save.
7
+ * - Re-trust (`--re-trust`): Re-verify a changed identity key without
8
+ * repeating the full registration flow.
9
+ *
10
+ * Uses @clack/prompts for consistent terminal UI with other IronCurtain
11
+ * interactive commands (config, first-start).
12
+ */
13
+ /** Validates a phone number in E.164 format. Returns error string or undefined. */
14
+ export declare function validatePhoneNumber(value: string | undefined): string | undefined;
15
+ /**
16
+ * Registers a new phone number with Signal via the signal-cli REST API.
17
+ * Handles the captcha and SMS verification code flow.
18
+ */
19
+ export declare function registerNewNumber(baseUrl: string): Promise<string>;
20
+ /**
21
+ * Sends a random challenge code to the recipient via Signal,
22
+ * waits for the user to type it into the terminal, then
23
+ * captures and returns the recipient's identity key.
24
+ *
25
+ * The identity key comes from signal-cli's identity endpoint
26
+ * after a successful message exchange has occurred.
27
+ */
28
+ export declare function verifyRecipientIdentity(baseUrl: string, botNumber: string, recipientNumber: string): Promise<string>;
29
+ /**
30
+ * Re-verifies a changed identity key without repeating full registration.
31
+ * Used when the transport detects an identity key change at runtime.
32
+ */
33
+ export declare function runReTrust(): Promise<void>;
34
+ /**
35
+ * Runs the interactive Signal setup wizard.
36
+ *
37
+ * Steps:
38
+ * 1. Validate Docker availability
39
+ * 2. Pull and start signal-cli container
40
+ * 3. Register new number (or reuse existing account)
41
+ * 4. Configure recipient number
42
+ * 5. Challenge-response identity verification
43
+ * 6. Capture and store identity key
44
+ * 7. Save config
45
+ */
46
+ export declare function runSignalSetup(options?: {
47
+ reTrust?: boolean;
48
+ }): Promise<void>;