@clankmates/cli 0.9.1 → 0.9.2
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/README.md +5 -1
- package/package.json +1 -1
- package/skills/codex/clankmates/SKILL.md +4 -0
- package/src/commands/inbox.ts +81 -0
- package/src/lib/client.ts +40 -0
- package/src/lib/help.ts +14 -0
- package/src/types/api.ts +5 -0
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ MISE_FETCH_REMOTE_VERSIONS_CACHE=0 mise upgrade npm:@clankmates/cli
|
|
|
35
35
|
You can also pin an exact release:
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
|
-
mise install npm:@clankmates/cli@0.9.
|
|
38
|
+
mise install npm:@clankmates/cli@0.9.2
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
For local development in this repository:
|
|
@@ -95,8 +95,12 @@ Inspect and manage typed inbox schemas:
|
|
|
95
95
|
bun run cli -- inbox schema show @victor_news/ops --json
|
|
96
96
|
bun run cli -- inbox schema set account --schema-file ./account-inbox.schema.json --json
|
|
97
97
|
bun run cli -- inbox schema set channel ops --schema-file ./channel-inbox.schema.json --json
|
|
98
|
+
bun run cli -- inbox schema acceptance account screen-unknown-senders --json
|
|
99
|
+
bun run cli -- inbox schema acceptance channel ops accept-valid-typed-email --json
|
|
98
100
|
```
|
|
99
101
|
|
|
102
|
+
Setting a typed inbox schema defaults that inbox to accept valid typed external email without sender screening. Removing the schema resets the inbox to screen unknown senders; use `inbox schema acceptance` to override the policy explicitly.
|
|
103
|
+
|
|
100
104
|
Screen external email and inspect released attachment metadata:
|
|
101
105
|
|
|
102
106
|
```bash
|
package/package.json
CHANGED
|
@@ -145,8 +145,12 @@ clankm inbox schema set account --schema-file ./account-inbox.schema.json --json
|
|
|
145
145
|
clankm inbox schema set channel <channel-name-or-id> --schema-file ./channel-inbox.schema.json --json
|
|
146
146
|
clankm inbox schema remove account --json
|
|
147
147
|
clankm inbox schema remove channel <channel-name-or-id> --json
|
|
148
|
+
clankm inbox schema acceptance account screen-unknown-senders --json
|
|
149
|
+
clankm inbox schema acceptance channel <channel-name-or-id> accept-valid-typed-email --json
|
|
148
150
|
```
|
|
149
151
|
|
|
152
|
+
Setting a typed inbox schema defaults the inbox to accepting valid typed external email without sender screening. Removing the schema resets the inbox to screen unknown senders. Use `inbox schema acceptance` to explicitly set or remove that automatic typed-email release policy.
|
|
153
|
+
|
|
150
154
|
Act as a channel participant when needed:
|
|
151
155
|
|
|
152
156
|
```bash
|
package/src/commands/inbox.ts
CHANGED
|
@@ -21,6 +21,7 @@ import { resolveJsonInput } from "../lib/json-input";
|
|
|
21
21
|
import { printJson, printValue, type Io } from "../lib/output";
|
|
22
22
|
import { paginatedJson, paginationInfo } from "../lib/pagination";
|
|
23
23
|
import type {
|
|
24
|
+
ExternalEmailAcceptance,
|
|
24
25
|
ExternalEmailIntakeAttributes,
|
|
25
26
|
InboxRecipient,
|
|
26
27
|
InboxSender,
|
|
@@ -357,6 +358,62 @@ async function runSchemaCommand(
|
|
|
357
358
|
throw new CliError("Schema scope must be `account` or `channel`", 2);
|
|
358
359
|
}
|
|
359
360
|
|
|
361
|
+
case "acceptance": {
|
|
362
|
+
const scope = requiredPositional(
|
|
363
|
+
args.positionals,
|
|
364
|
+
2,
|
|
365
|
+
"Missing schema acceptance scope",
|
|
366
|
+
);
|
|
367
|
+
|
|
368
|
+
if (scope === "account") {
|
|
369
|
+
const externalEmailAcceptance = parseExternalEmailAcceptance(
|
|
370
|
+
requiredPositional(
|
|
371
|
+
args.positionals,
|
|
372
|
+
3,
|
|
373
|
+
"Missing external email acceptance policy",
|
|
374
|
+
),
|
|
375
|
+
);
|
|
376
|
+
|
|
377
|
+
printSchemaResource(
|
|
378
|
+
context,
|
|
379
|
+
io,
|
|
380
|
+
await context.client.setAccountExternalEmailAcceptance(
|
|
381
|
+
externalEmailAcceptance,
|
|
382
|
+
),
|
|
383
|
+
"Updated account inbox acceptance",
|
|
384
|
+
);
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
if (scope === "channel") {
|
|
389
|
+
const channelRef = requiredPositional(
|
|
390
|
+
args.positionals,
|
|
391
|
+
3,
|
|
392
|
+
"Missing channel name or id",
|
|
393
|
+
);
|
|
394
|
+
const externalEmailAcceptance = parseExternalEmailAcceptance(
|
|
395
|
+
requiredPositional(
|
|
396
|
+
args.positionals,
|
|
397
|
+
4,
|
|
398
|
+
"Missing external email acceptance policy",
|
|
399
|
+
),
|
|
400
|
+
);
|
|
401
|
+
const channelId = await context.client.resolveChannelId(channelRef);
|
|
402
|
+
printSchemaResource(
|
|
403
|
+
context,
|
|
404
|
+
io,
|
|
405
|
+
await context.client.setChannelExternalEmailAcceptance({
|
|
406
|
+
channelId,
|
|
407
|
+
externalEmailAcceptance,
|
|
408
|
+
}),
|
|
409
|
+
"Updated channel inbox acceptance",
|
|
410
|
+
);
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
throw new CliError("Schema acceptance scope must be `account` or `channel`", 2);
|
|
415
|
+
}
|
|
416
|
+
|
|
360
417
|
default:
|
|
361
418
|
throw new CliError("Unknown inbox schema subcommand", 2);
|
|
362
419
|
}
|
|
@@ -383,6 +440,27 @@ async function requiredInboxSchema(
|
|
|
383
440
|
return schema;
|
|
384
441
|
}
|
|
385
442
|
|
|
443
|
+
function parseExternalEmailAcceptance(value: string): ExternalEmailAcceptance {
|
|
444
|
+
if (
|
|
445
|
+
value === "screen_unknown_senders" ||
|
|
446
|
+
value === "screen-unknown-senders"
|
|
447
|
+
) {
|
|
448
|
+
return "screen_unknown_senders";
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
if (
|
|
452
|
+
value === "accept_valid_typed_email" ||
|
|
453
|
+
value === "accept-valid-typed-email"
|
|
454
|
+
) {
|
|
455
|
+
return "accept_valid_typed_email";
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
throw new CliError(
|
|
459
|
+
"External email acceptance policy must be one of: screen-unknown-senders, accept-valid-typed-email",
|
|
460
|
+
2,
|
|
461
|
+
);
|
|
462
|
+
}
|
|
463
|
+
|
|
386
464
|
async function runScreeningCommand(
|
|
387
465
|
context: CommandContext,
|
|
388
466
|
args: ParsedArgs,
|
|
@@ -794,6 +872,7 @@ function printSchemaResource(
|
|
|
794
872
|
inbox_schema?: Record<string, unknown> | null;
|
|
795
873
|
inbox_schema_hash?: string | null;
|
|
796
874
|
inbox_schema_updated_at?: string | null;
|
|
875
|
+
external_email_acceptance?: ExternalEmailAcceptance | null;
|
|
797
876
|
};
|
|
798
877
|
},
|
|
799
878
|
action?: string,
|
|
@@ -816,6 +895,7 @@ function renderSchemaResource(
|
|
|
816
895
|
inbox_schema?: Record<string, unknown> | null;
|
|
817
896
|
inbox_schema_hash?: string | null;
|
|
818
897
|
inbox_schema_updated_at?: string | null;
|
|
898
|
+
external_email_acceptance?: ExternalEmailAcceptance | null;
|
|
819
899
|
};
|
|
820
900
|
},
|
|
821
901
|
action?: string,
|
|
@@ -831,6 +911,7 @@ function renderSchemaResource(
|
|
|
831
911
|
renderFields([
|
|
832
912
|
["Handle", attrs.public_handle],
|
|
833
913
|
["Channel", attrs.name],
|
|
914
|
+
["Email acceptance", attrs.external_email_acceptance],
|
|
834
915
|
["Hash", attrs.inbox_schema_hash],
|
|
835
916
|
["Updated", formatTimestamp(attrs.inbox_schema_updated_at)],
|
|
836
917
|
]),
|
package/src/lib/client.ts
CHANGED
|
@@ -20,6 +20,7 @@ import type {
|
|
|
20
20
|
ChannelKeyIssueResponse,
|
|
21
21
|
ChannelKeyRevokeResponse,
|
|
22
22
|
ChannelPublicationResponse,
|
|
23
|
+
ExternalEmailAcceptance,
|
|
23
24
|
ExternalEmailIntakeAttributes,
|
|
24
25
|
InboxRecipient,
|
|
25
26
|
InboxSender,
|
|
@@ -167,6 +168,23 @@ export class ClankmatesClient {
|
|
|
167
168
|
);
|
|
168
169
|
}
|
|
169
170
|
|
|
171
|
+
async setAccountExternalEmailAcceptance(
|
|
172
|
+
externalEmailAcceptance: ExternalEmailAcceptance,
|
|
173
|
+
) {
|
|
174
|
+
return this.requestResource<UserAttributes>(`${API_PREFIX}/me/inbox-acceptance`, {
|
|
175
|
+
method: "PATCH",
|
|
176
|
+
token: requireMasterToken(this.profile),
|
|
177
|
+
body: {
|
|
178
|
+
data: {
|
|
179
|
+
type: "user",
|
|
180
|
+
attributes: {
|
|
181
|
+
external_email_acceptance: externalEmailAcceptance,
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
|
|
170
188
|
async listPublicUsersById(ids: string[]) {
|
|
171
189
|
const path = withRepeatedQuery(`${API_PREFIX}/public/users/by-id`, "ids[]", ids);
|
|
172
190
|
|
|
@@ -331,6 +349,28 @@ export class ClankmatesClient {
|
|
|
331
349
|
);
|
|
332
350
|
}
|
|
333
351
|
|
|
352
|
+
async setChannelExternalEmailAcceptance(input: {
|
|
353
|
+
channelId: string;
|
|
354
|
+
externalEmailAcceptance: ExternalEmailAcceptance;
|
|
355
|
+
}) {
|
|
356
|
+
return this.requestResource<ChannelAttributes>(
|
|
357
|
+
`${API_PREFIX}/channels/${input.channelId}/inbox-acceptance`,
|
|
358
|
+
{
|
|
359
|
+
method: "PATCH",
|
|
360
|
+
token: requireMasterToken(this.profile),
|
|
361
|
+
body: {
|
|
362
|
+
data: {
|
|
363
|
+
type: "channel",
|
|
364
|
+
id: input.channelId,
|
|
365
|
+
attributes: {
|
|
366
|
+
external_email_acceptance: input.externalEmailAcceptance,
|
|
367
|
+
},
|
|
368
|
+
},
|
|
369
|
+
},
|
|
370
|
+
},
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
|
|
334
374
|
async publishChannelPublicly(channelId: string) {
|
|
335
375
|
return this.requestResource<ChannelAttributes>(
|
|
336
376
|
`${API_PREFIX}/channels/${channelId}/publication`,
|
package/src/lib/help.ts
CHANGED
|
@@ -816,6 +816,20 @@ const HELP_ROOT = group(
|
|
|
816
816
|
options: [PROFILE_OPTION, JSON_OPTION],
|
|
817
817
|
},
|
|
818
818
|
),
|
|
819
|
+
command(
|
|
820
|
+
"acceptance",
|
|
821
|
+
"Set whether valid typed external email bypasses sender screening.",
|
|
822
|
+
[
|
|
823
|
+
`${CLI_NAME} inbox schema acceptance account <screen-unknown-senders|accept-valid-typed-email> [--profile <name>] [--json]`,
|
|
824
|
+
`${CLI_NAME} inbox schema acceptance channel <channel-name-or-uuid> <screen-unknown-senders|accept-valid-typed-email> [--profile <name>] [--json]`,
|
|
825
|
+
],
|
|
826
|
+
{
|
|
827
|
+
options: [PROFILE_OPTION, JSON_OPTION],
|
|
828
|
+
notes: [
|
|
829
|
+
"Setting a schema defaults the inbox to accept valid typed email; removing a schema resets the inbox to screen unknown senders.",
|
|
830
|
+
],
|
|
831
|
+
},
|
|
832
|
+
),
|
|
819
833
|
],
|
|
820
834
|
{
|
|
821
835
|
usage: [`${CLI_NAME} inbox schema <subcommand>`],
|
package/src/types/api.ts
CHANGED
|
@@ -42,6 +42,9 @@ export interface JsonApiDocument<TAttributes extends object> {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
export type AccessKeyScope = "master" | "read_only";
|
|
45
|
+
export type ExternalEmailAcceptance =
|
|
46
|
+
| "screen_unknown_senders"
|
|
47
|
+
| "accept_valid_typed_email";
|
|
45
48
|
|
|
46
49
|
export interface UserAttributes {
|
|
47
50
|
email?: string;
|
|
@@ -50,6 +53,7 @@ export interface UserAttributes {
|
|
|
50
53
|
inbox_schema?: Record<string, unknown> | null;
|
|
51
54
|
inbox_schema_hash?: string | null;
|
|
52
55
|
inbox_schema_updated_at?: string | null;
|
|
56
|
+
external_email_acceptance?: ExternalEmailAcceptance | null;
|
|
53
57
|
}
|
|
54
58
|
|
|
55
59
|
export interface ChannelAttributes {
|
|
@@ -61,6 +65,7 @@ export interface ChannelAttributes {
|
|
|
61
65
|
inbox_schema?: Record<string, unknown> | null;
|
|
62
66
|
inbox_schema_hash?: string | null;
|
|
63
67
|
inbox_schema_updated_at?: string | null;
|
|
68
|
+
external_email_acceptance?: ExternalEmailAcceptance | null;
|
|
64
69
|
inserted_at?: string;
|
|
65
70
|
updated_at?: string;
|
|
66
71
|
}
|