@mccaskie-labs/workbench-config 0.1.5 → 0.1.6
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 +6 -0
- package/capabilities/email-inbound.json +128 -0
- package/capabilities/email-inbound.md +19 -0
- package/dist/capabilities.gen.d.ts +102 -1
- package/dist/capabilities.gen.js +129 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "./schema.json",
|
|
3
|
+
"format": 1,
|
|
4
|
+
"component": "email-inbound",
|
|
5
|
+
"title": "Inbound email to the project's own Worker",
|
|
6
|
+
"summary": "Email Routing receives mail on a domain in the project's namespace and runs one routing rule per address, each sending the mail to one of the project's own Workers. The Worker's email() handler parses it with postal-mime and the app stores or rejects it. Mail is never forwarded outside the project.",
|
|
7
|
+
"status": "built",
|
|
8
|
+
"surfaces": {
|
|
9
|
+
"tools": [
|
|
10
|
+
"cf_email_routing_enable",
|
|
11
|
+
"cf_email_routing_list",
|
|
12
|
+
"cf_email_routing_rule_create",
|
|
13
|
+
"cf_email_routing_rule_delete"
|
|
14
|
+
]
|
|
15
|
+
},
|
|
16
|
+
"limits": [
|
|
17
|
+
{
|
|
18
|
+
"id": "email-inbound.address-length",
|
|
19
|
+
"value": 90,
|
|
20
|
+
"unit": "characters",
|
|
21
|
+
"per": "address",
|
|
22
|
+
"enforced_by": "control",
|
|
23
|
+
"refusal": "invalid_address"
|
|
24
|
+
}
|
|
25
|
+
],
|
|
26
|
+
"actions": [
|
|
27
|
+
{
|
|
28
|
+
"tool": "cf_email_routing_enable",
|
|
29
|
+
"gate": "free",
|
|
30
|
+
"ships": "4"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"tool": "cf_email_routing_list",
|
|
34
|
+
"gate": "free",
|
|
35
|
+
"ships": "4"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"tool": "cf_email_routing_rule_create",
|
|
39
|
+
"gate": "free",
|
|
40
|
+
"ships": "4"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"tool": "cf_email_routing_rule_delete",
|
|
44
|
+
"gate": "two_step",
|
|
45
|
+
"ships": "4"
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
"errors": [
|
|
49
|
+
{
|
|
50
|
+
"code": "out_of_scope",
|
|
51
|
+
"http": 403,
|
|
52
|
+
"retryable": false,
|
|
53
|
+
"meaning": "A domain outside the project's namespace, another project's Worker or another project's rule"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"code": "catch_all",
|
|
57
|
+
"http": 400,
|
|
58
|
+
"retryable": false,
|
|
59
|
+
"meaning": "A catch-all address; Control routes only one literal address per rule"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"code": "routing_not_enabled",
|
|
63
|
+
"http": 409,
|
|
64
|
+
"retryable": false,
|
|
65
|
+
"meaning": "Email Routing isn't on for the address's domain yet (cf_email_routing_enable)"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"code": "name_taken",
|
|
69
|
+
"http": 409,
|
|
70
|
+
"retryable": false,
|
|
71
|
+
"meaning": "A mail record or rule exists that Control didn't create for the project; Control never adopts"
|
|
72
|
+
}
|
|
73
|
+
],
|
|
74
|
+
"rules": [
|
|
75
|
+
{
|
|
76
|
+
"id": "email-inbound.own-worker",
|
|
77
|
+
"kind": "must",
|
|
78
|
+
"text": "Route an address only to one of the project's own Workers. A rule naming another project's Worker is refused with out_of_scope.",
|
|
79
|
+
"enforced_by": "control",
|
|
80
|
+
"probe": "email-inbound.other-worker"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"id": "email-inbound.no-forward",
|
|
84
|
+
"kind": "must_not",
|
|
85
|
+
"text": "Forward inbound mail outside the project. The template's receiveEmail gives the app the parsed mail and a reject function, not the message.",
|
|
86
|
+
"enforced_by": "review",
|
|
87
|
+
"probe": "email-inbound.roundtrip"
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"id": "email-inbound.reject-on-failure",
|
|
91
|
+
"kind": "must",
|
|
92
|
+
"text": "Reject a message the app can't store (throw from handleEmail, or call reject) rather than drop it silently.",
|
|
93
|
+
"enforced_by": "review",
|
|
94
|
+
"probe": "email-inbound.roundtrip"
|
|
95
|
+
}
|
|
96
|
+
],
|
|
97
|
+
"examples": [
|
|
98
|
+
{
|
|
99
|
+
"id": "email-inbound.example.handler",
|
|
100
|
+
"title": "Store inbound mail",
|
|
101
|
+
"lang": "ts",
|
|
102
|
+
"probe": "email-inbound.roundtrip",
|
|
103
|
+
"code": "export async function handleEmail(mail, env, ctx, { reject }) {\n if (!mail.to.some((t) => t.address === 'inbox@wb-probe-staging.mccaskielabs.app')) return reject('Unknown mailbox')\n await saveMail(env, { message_id: mail.message_id, subject: mail.subject, text: mail.text, received_at: mail.received_at })\n}"
|
|
104
|
+
}
|
|
105
|
+
],
|
|
106
|
+
"probes": [
|
|
107
|
+
{
|
|
108
|
+
"id": "email-inbound.roundtrip",
|
|
109
|
+
"half": "runtime",
|
|
110
|
+
"expect": "pass",
|
|
111
|
+
"note": "Sends a mail through the Gateway to inbox@ on the receiving domain; the Email Worker stores it and the console shows send-to-stored time. Needs step 4.9 (outbound) and a store (step 4.11)"
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"id": "email-inbound.other-worker",
|
|
115
|
+
"half": "drill",
|
|
116
|
+
"expect": "refused_as_expected",
|
|
117
|
+
"refusal": "out_of_scope",
|
|
118
|
+
"note": "cf_email_routing_rule_create naming another project's Worker"
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"id": "email-inbound.rule-delete",
|
|
122
|
+
"half": "drill",
|
|
123
|
+
"expect": "pass",
|
|
124
|
+
"two_step": true,
|
|
125
|
+
"note": "cf_email_routing_rule_delete returns a confirmation and changes nothing until Robert approves"
|
|
126
|
+
}
|
|
127
|
+
]
|
|
128
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Inbound email
|
|
2
|
+
|
|
3
|
+
A project receives mail on a domain in its namespace, for example `wb-probe-staging.mccaskielabs.app`, and each address it uses is routed to one of its own Workers. Project-owned zones such as `wbprobe.com` join the namespace with `cf_zone_attach` (phase 6).
|
|
4
|
+
|
|
5
|
+
## Setting it up (Claude, through Control)
|
|
6
|
+
|
|
7
|
+
1. `cf_email_routing_enable domain=<domain>`. Cloudflare adds its MX and SPF records on that name only; the apex's locked-down baseline stays as it is. Control records the records for the project, so `cf_dns_delete` removes them again.
|
|
8
|
+
2. `cf_email_routing_rule_create address=inbox@<domain> worker=<id>-staging`. One literal address, one Worker. No catch-alls, no forwarding.
|
|
9
|
+
3. `cf_email_routing_list` shows the domains and rules. `cf_email_routing_rule_delete` (two-step) stops an address.
|
|
10
|
+
|
|
11
|
+
## In the Worker
|
|
12
|
+
|
|
13
|
+
The template's `src/email.js` exports `receiveEmail`, and `src/index.js` wires it to `handleEmail(mail, env, ctx, { reject })`. `mail` has `received_at`, `envelope_from`, `envelope_to`, `raw_size`, `message_id`, `from`, `to`, `subject`, `date`, `text`, `html`, `headers` and `attachments` (each with `filename`, `mime_type`, `content_id`, `size` and `content`). Store what the app needs and return, or call `reject(reason)` to bounce the message. A handler that throws rejects it too.
|
|
14
|
+
|
|
15
|
+
The starter `handleEmail` rejects everything, so routing an address before the app handles mail bounces it rather than losing it.
|
|
16
|
+
|
|
17
|
+
## Limits
|
|
18
|
+
|
|
19
|
+
Email Routing takes messages up to 25 MiB. Addresses are at most 90 characters, and the part before `@` takes letters, digits, dot, underscore, plus and hyphen.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const MANIFEST_VERSION: "
|
|
1
|
+
export declare const MANIFEST_VERSION: "928d1b370728";
|
|
2
2
|
export declare const capabilities: {
|
|
3
3
|
readonly ai: {
|
|
4
4
|
readonly $schema: "./schema.json";
|
|
@@ -416,6 +416,107 @@ export declare const capabilities: {
|
|
|
416
416
|
readonly note: "sb_query on production with a write returns a confirmation, not a result";
|
|
417
417
|
}];
|
|
418
418
|
};
|
|
419
|
+
readonly "email-inbound": {
|
|
420
|
+
readonly $schema: "./schema.json";
|
|
421
|
+
readonly format: 1;
|
|
422
|
+
readonly component: "email-inbound";
|
|
423
|
+
readonly title: "Inbound email to the project's own Worker";
|
|
424
|
+
readonly summary: "Email Routing receives mail on a domain in the project's namespace and runs one routing rule per address, each sending the mail to one of the project's own Workers. The Worker's email() handler parses it with postal-mime and the app stores or rejects it. Mail is never forwarded outside the project.";
|
|
425
|
+
readonly status: "built";
|
|
426
|
+
readonly surfaces: {
|
|
427
|
+
readonly tools: readonly ["cf_email_routing_enable", "cf_email_routing_list", "cf_email_routing_rule_create", "cf_email_routing_rule_delete"];
|
|
428
|
+
};
|
|
429
|
+
readonly limits: readonly [{
|
|
430
|
+
readonly id: "email-inbound.address-length";
|
|
431
|
+
readonly value: 90;
|
|
432
|
+
readonly unit: "characters";
|
|
433
|
+
readonly per: "address";
|
|
434
|
+
readonly enforced_by: "control";
|
|
435
|
+
readonly refusal: "invalid_address";
|
|
436
|
+
}];
|
|
437
|
+
readonly actions: readonly [{
|
|
438
|
+
readonly tool: "cf_email_routing_enable";
|
|
439
|
+
readonly gate: "free";
|
|
440
|
+
readonly ships: "4";
|
|
441
|
+
}, {
|
|
442
|
+
readonly tool: "cf_email_routing_list";
|
|
443
|
+
readonly gate: "free";
|
|
444
|
+
readonly ships: "4";
|
|
445
|
+
}, {
|
|
446
|
+
readonly tool: "cf_email_routing_rule_create";
|
|
447
|
+
readonly gate: "free";
|
|
448
|
+
readonly ships: "4";
|
|
449
|
+
}, {
|
|
450
|
+
readonly tool: "cf_email_routing_rule_delete";
|
|
451
|
+
readonly gate: "two_step";
|
|
452
|
+
readonly ships: "4";
|
|
453
|
+
}];
|
|
454
|
+
readonly errors: readonly [{
|
|
455
|
+
readonly code: "out_of_scope";
|
|
456
|
+
readonly http: 403;
|
|
457
|
+
readonly retryable: false;
|
|
458
|
+
readonly meaning: "A domain outside the project's namespace, another project's Worker or another project's rule";
|
|
459
|
+
}, {
|
|
460
|
+
readonly code: "catch_all";
|
|
461
|
+
readonly http: 400;
|
|
462
|
+
readonly retryable: false;
|
|
463
|
+
readonly meaning: "A catch-all address; Control routes only one literal address per rule";
|
|
464
|
+
}, {
|
|
465
|
+
readonly code: "routing_not_enabled";
|
|
466
|
+
readonly http: 409;
|
|
467
|
+
readonly retryable: false;
|
|
468
|
+
readonly meaning: "Email Routing isn't on for the address's domain yet (cf_email_routing_enable)";
|
|
469
|
+
}, {
|
|
470
|
+
readonly code: "name_taken";
|
|
471
|
+
readonly http: 409;
|
|
472
|
+
readonly retryable: false;
|
|
473
|
+
readonly meaning: "A mail record or rule exists that Control didn't create for the project; Control never adopts";
|
|
474
|
+
}];
|
|
475
|
+
readonly rules: readonly [{
|
|
476
|
+
readonly id: "email-inbound.own-worker";
|
|
477
|
+
readonly kind: "must";
|
|
478
|
+
readonly text: "Route an address only to one of the project's own Workers. A rule naming another project's Worker is refused with out_of_scope.";
|
|
479
|
+
readonly enforced_by: "control";
|
|
480
|
+
readonly probe: "email-inbound.other-worker";
|
|
481
|
+
}, {
|
|
482
|
+
readonly id: "email-inbound.no-forward";
|
|
483
|
+
readonly kind: "must_not";
|
|
484
|
+
readonly text: "Forward inbound mail outside the project. The template's receiveEmail gives the app the parsed mail and a reject function, not the message.";
|
|
485
|
+
readonly enforced_by: "review";
|
|
486
|
+
readonly probe: "email-inbound.roundtrip";
|
|
487
|
+
}, {
|
|
488
|
+
readonly id: "email-inbound.reject-on-failure";
|
|
489
|
+
readonly kind: "must";
|
|
490
|
+
readonly text: "Reject a message the app can't store (throw from handleEmail, or call reject) rather than drop it silently.";
|
|
491
|
+
readonly enforced_by: "review";
|
|
492
|
+
readonly probe: "email-inbound.roundtrip";
|
|
493
|
+
}];
|
|
494
|
+
readonly examples: readonly [{
|
|
495
|
+
readonly id: "email-inbound.example.handler";
|
|
496
|
+
readonly title: "Store inbound mail";
|
|
497
|
+
readonly lang: "ts";
|
|
498
|
+
readonly code: "export async function handleEmail(mail, env, ctx, { reject }) {\n if (!mail.to.some((t) => t.address === 'inbox@wb-probe-staging.mccaskielabs.app')) return reject('Unknown mailbox')\n await saveMail(env, { message_id: mail.message_id, subject: mail.subject, text: mail.text, received_at: mail.received_at })\n}";
|
|
499
|
+
readonly probe: "email-inbound.roundtrip";
|
|
500
|
+
}];
|
|
501
|
+
readonly probes: readonly [{
|
|
502
|
+
readonly id: "email-inbound.roundtrip";
|
|
503
|
+
readonly half: "runtime";
|
|
504
|
+
readonly expect: "pass";
|
|
505
|
+
readonly note: "Sends a mail through the Gateway to inbox@ on the receiving domain; the Email Worker stores it and the console shows send-to-stored time. Needs step 4.9 (outbound) and a store (step 4.11)";
|
|
506
|
+
}, {
|
|
507
|
+
readonly id: "email-inbound.other-worker";
|
|
508
|
+
readonly half: "drill";
|
|
509
|
+
readonly expect: "refused_as_expected";
|
|
510
|
+
readonly refusal: "out_of_scope";
|
|
511
|
+
readonly note: "cf_email_routing_rule_create naming another project's Worker";
|
|
512
|
+
}, {
|
|
513
|
+
readonly id: "email-inbound.rule-delete";
|
|
514
|
+
readonly half: "drill";
|
|
515
|
+
readonly expect: "pass";
|
|
516
|
+
readonly two_step: true;
|
|
517
|
+
readonly note: "cf_email_routing_rule_delete returns a confirmation and changes nothing until Robert approves";
|
|
518
|
+
}];
|
|
519
|
+
};
|
|
419
520
|
readonly gateway: {
|
|
420
521
|
readonly $schema: "./schema.json";
|
|
421
522
|
readonly format: 1;
|
package/dist/capabilities.gen.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Generated by `npm run capabilities:build` from capabilities/*.json. Do not edit.
|
|
2
2
|
// check:capabilities fails in Checks when this file is stale.
|
|
3
|
-
export const MANIFEST_VERSION = "
|
|
3
|
+
export const MANIFEST_VERSION = "928d1b370728";
|
|
4
4
|
export const capabilities = {
|
|
5
5
|
"ai": {
|
|
6
6
|
"$schema": "./schema.json",
|
|
@@ -577,6 +577,134 @@ export const capabilities = {
|
|
|
577
577
|
}
|
|
578
578
|
]
|
|
579
579
|
},
|
|
580
|
+
"email-inbound": {
|
|
581
|
+
"$schema": "./schema.json",
|
|
582
|
+
"format": 1,
|
|
583
|
+
"component": "email-inbound",
|
|
584
|
+
"title": "Inbound email to the project's own Worker",
|
|
585
|
+
"summary": "Email Routing receives mail on a domain in the project's namespace and runs one routing rule per address, each sending the mail to one of the project's own Workers. The Worker's email() handler parses it with postal-mime and the app stores or rejects it. Mail is never forwarded outside the project.",
|
|
586
|
+
"status": "built",
|
|
587
|
+
"surfaces": {
|
|
588
|
+
"tools": [
|
|
589
|
+
"cf_email_routing_enable",
|
|
590
|
+
"cf_email_routing_list",
|
|
591
|
+
"cf_email_routing_rule_create",
|
|
592
|
+
"cf_email_routing_rule_delete"
|
|
593
|
+
]
|
|
594
|
+
},
|
|
595
|
+
"limits": [
|
|
596
|
+
{
|
|
597
|
+
"id": "email-inbound.address-length",
|
|
598
|
+
"value": 90,
|
|
599
|
+
"unit": "characters",
|
|
600
|
+
"per": "address",
|
|
601
|
+
"enforced_by": "control",
|
|
602
|
+
"refusal": "invalid_address"
|
|
603
|
+
}
|
|
604
|
+
],
|
|
605
|
+
"actions": [
|
|
606
|
+
{
|
|
607
|
+
"tool": "cf_email_routing_enable",
|
|
608
|
+
"gate": "free",
|
|
609
|
+
"ships": "4"
|
|
610
|
+
},
|
|
611
|
+
{
|
|
612
|
+
"tool": "cf_email_routing_list",
|
|
613
|
+
"gate": "free",
|
|
614
|
+
"ships": "4"
|
|
615
|
+
},
|
|
616
|
+
{
|
|
617
|
+
"tool": "cf_email_routing_rule_create",
|
|
618
|
+
"gate": "free",
|
|
619
|
+
"ships": "4"
|
|
620
|
+
},
|
|
621
|
+
{
|
|
622
|
+
"tool": "cf_email_routing_rule_delete",
|
|
623
|
+
"gate": "two_step",
|
|
624
|
+
"ships": "4"
|
|
625
|
+
}
|
|
626
|
+
],
|
|
627
|
+
"errors": [
|
|
628
|
+
{
|
|
629
|
+
"code": "out_of_scope",
|
|
630
|
+
"http": 403,
|
|
631
|
+
"retryable": false,
|
|
632
|
+
"meaning": "A domain outside the project's namespace, another project's Worker or another project's rule"
|
|
633
|
+
},
|
|
634
|
+
{
|
|
635
|
+
"code": "catch_all",
|
|
636
|
+
"http": 400,
|
|
637
|
+
"retryable": false,
|
|
638
|
+
"meaning": "A catch-all address; Control routes only one literal address per rule"
|
|
639
|
+
},
|
|
640
|
+
{
|
|
641
|
+
"code": "routing_not_enabled",
|
|
642
|
+
"http": 409,
|
|
643
|
+
"retryable": false,
|
|
644
|
+
"meaning": "Email Routing isn't on for the address's domain yet (cf_email_routing_enable)"
|
|
645
|
+
},
|
|
646
|
+
{
|
|
647
|
+
"code": "name_taken",
|
|
648
|
+
"http": 409,
|
|
649
|
+
"retryable": false,
|
|
650
|
+
"meaning": "A mail record or rule exists that Control didn't create for the project; Control never adopts"
|
|
651
|
+
}
|
|
652
|
+
],
|
|
653
|
+
"rules": [
|
|
654
|
+
{
|
|
655
|
+
"id": "email-inbound.own-worker",
|
|
656
|
+
"kind": "must",
|
|
657
|
+
"text": "Route an address only to one of the project's own Workers. A rule naming another project's Worker is refused with out_of_scope.",
|
|
658
|
+
"enforced_by": "control",
|
|
659
|
+
"probe": "email-inbound.other-worker"
|
|
660
|
+
},
|
|
661
|
+
{
|
|
662
|
+
"id": "email-inbound.no-forward",
|
|
663
|
+
"kind": "must_not",
|
|
664
|
+
"text": "Forward inbound mail outside the project. The template's receiveEmail gives the app the parsed mail and a reject function, not the message.",
|
|
665
|
+
"enforced_by": "review",
|
|
666
|
+
"probe": "email-inbound.roundtrip"
|
|
667
|
+
},
|
|
668
|
+
{
|
|
669
|
+
"id": "email-inbound.reject-on-failure",
|
|
670
|
+
"kind": "must",
|
|
671
|
+
"text": "Reject a message the app can't store (throw from handleEmail, or call reject) rather than drop it silently.",
|
|
672
|
+
"enforced_by": "review",
|
|
673
|
+
"probe": "email-inbound.roundtrip"
|
|
674
|
+
}
|
|
675
|
+
],
|
|
676
|
+
"examples": [
|
|
677
|
+
{
|
|
678
|
+
"id": "email-inbound.example.handler",
|
|
679
|
+
"title": "Store inbound mail",
|
|
680
|
+
"lang": "ts",
|
|
681
|
+
"code": "export async function handleEmail(mail, env, ctx, { reject }) {\n if (!mail.to.some((t) => t.address === 'inbox@wb-probe-staging.mccaskielabs.app')) return reject('Unknown mailbox')\n await saveMail(env, { message_id: mail.message_id, subject: mail.subject, text: mail.text, received_at: mail.received_at })\n}",
|
|
682
|
+
"probe": "email-inbound.roundtrip"
|
|
683
|
+
}
|
|
684
|
+
],
|
|
685
|
+
"probes": [
|
|
686
|
+
{
|
|
687
|
+
"id": "email-inbound.roundtrip",
|
|
688
|
+
"half": "runtime",
|
|
689
|
+
"expect": "pass",
|
|
690
|
+
"note": "Sends a mail through the Gateway to inbox@ on the receiving domain; the Email Worker stores it and the console shows send-to-stored time. Needs step 4.9 (outbound) and a store (step 4.11)"
|
|
691
|
+
},
|
|
692
|
+
{
|
|
693
|
+
"id": "email-inbound.other-worker",
|
|
694
|
+
"half": "drill",
|
|
695
|
+
"expect": "refused_as_expected",
|
|
696
|
+
"refusal": "out_of_scope",
|
|
697
|
+
"note": "cf_email_routing_rule_create naming another project's Worker"
|
|
698
|
+
},
|
|
699
|
+
{
|
|
700
|
+
"id": "email-inbound.rule-delete",
|
|
701
|
+
"half": "drill",
|
|
702
|
+
"expect": "pass",
|
|
703
|
+
"two_step": true,
|
|
704
|
+
"note": "cf_email_routing_rule_delete returns a confirmation and changes nothing until Robert approves"
|
|
705
|
+
}
|
|
706
|
+
]
|
|
707
|
+
},
|
|
580
708
|
"gateway": {
|
|
581
709
|
"$schema": "./schema.json",
|
|
582
710
|
"format": 1,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mccaskie-labs/workbench-config",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Workbench app configuration: WORKBENCH_ENV, typed variables that fail by name, secrets that are never printed, and the capabilities manifest.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|