@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 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.1
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clankmates/cli",
3
- "version": "0.9.1",
3
+ "version": "0.9.2",
4
4
  "devDependencies": {
5
5
  "@types/bun": "1.3.10",
6
6
  "typescript": "^5.9.3"
@@ -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
@@ -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
  }