Repository navigation
Expand file tree
/
Copy pathworkerd.capnp
More file actions
1204 lines (1005 loc) · 51.7 KB
/
Copy pathworkerd.capnp
File metadata and controls
1204 lines (1005 loc) · 51.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# Copyright (c) 2017-2022 Cloudflare, Inc.
# Licensed under the Apache 2.0 license found in the LICENSE file or at:
# https://opensource.org/licenses/Apache-2.0
@0xe6afd26682091c01;
# This file defines the schema for configuring the workerd runtime.
#
# A config file can be written as a `.capnp` file that imports this file and then defines a
# constant of type `Config`. Alternatively, various higher-level tooling (e.g. wrangler) may
# generate configs for you, outputting a binary Cap'n Proto file.
#
# To start a server with a config, do:
#
# workerd serve my-config.capnp constantName
#
# You can also build a new self-contained binary which combines the `workerd` binary with your
# configuration and all your source code:
#
# workerd compile my-config.capnp constantName -o my-server-bin
#
# This binary can then be run stand-alone.
#
# A common theme in this configuration is capability-based design. We generally like to avoid
# giving a Worker the ability to access external resources by name, since this makes it hard
# to see and restrict what each Worker can access. Instead, the default is that a Worker has
# access to no privileged resources at all, and you must explicitly declare "bindings" to give
# it access to specific resources. A binding gives the Worker a JavaScript API object that points
# to a specific resource. This means that by changing config alone, you can fully control which
# resources an Worker connects to. (You can even disallow access to the public internet, although
# public internet access is granted by default.)
#
# This config format is fairly powerful, allowing you to do things like define a TLS-terminating
# reverse proxy server without using any actual JavaScript code. However, you should not be
# afraid to fall back to code for anything the config cannot express, as Workers are very fast
# to execute!
# Any capnp files imported here must be:
# 1. embedded using wd_cc_embed
# 2. added to `tryImportBulitin` in schema-file.c++ (grep for '"/workerd/workerd.capnp"').
using Cxx = import "/capnp/c++.capnp";
$Cxx.namespace("workerd::server::config");
$Cxx.allowCancellation;
struct Config {
# Top-level configuration for a workerd instance.
services @0 :List(Service);
# List of named services defined by this server. These names are private; they are only used
# to refer to the services from elsewhere in this config file, as well as for logging and the
# like. Services are not reachable until you configure some way to make them reachable, such
# as via a Socket.
#
# If you do not define any service called "internet", one is defined implicitly, representing
# the ability to access public internet servers. An explicit definition would look like:
#
# ( name = "internet",
# network = (
# allow = ["public"], # Allows connections to publicly-routable addresses only.
# tlsOptions = (trustBrowserCas = true)
# )
# )
#
# The "internet" service backs the global `fetch()` function in a Worker, unless that Worker's
# configuration specifies some other service using the `globalOutbound` setting.
sockets @1 :List(Socket);
# List of sockets on which this server will listen, and the services that will be exposed
# through them.
v8Flags @2 :List(Text);
# List of "command-line" flags to pass to V8, like "--expose-gc". We put these in the config
# rather than on the actual command line because for most use cases, managing these via the
# config file is probably cleaner and easier than passing on the actual CLI.
#
# WARNING: Use at your own risk. V8 flags can have all sorts of wild effects including completely
# breaking everything. V8 flags also generally do not come with any guarantee of stability
# between V8 versions. Most users should not set any V8 flags.
extensions @3 :List(Extension);
# Extensions provide capabilities to all workers. Extensions are usually prepared separately
# and are late-linked with the app using this config field.
autogates @4 :List(Text);
# A list of gates which are enabled.
# These are used to gate features/changes in workerd and in our internal repo. See the equivalent
# config definition in our internal repo for more details.
structuredLogging @5 :Bool = false;
# If true, logs will be emitted as JSON for structured logging.
# When false, logs use the traditional human-readable format.
# This affects the format of logs from KJ_LOG and exception reporting as well as js logs.
# This won't work for logs coming from service worker syntax workers with the old module registry.
# Note: This field is obsolete and deprecated. Use the logging struct instead.
logging @6 : LoggingOptions;
# Console and Stdio logging configuration options.
}
struct LoggingOptions {
structuredLogging @0 :Bool = false;
# Override of top-level structured logging (only when true).
# If true, logs will be emitted as JSON for structured logging.
# When false, logs use the traditional human-readable format.
# This affects the format of logs from KJ_LOG and exception reporting as well as js logs.
# This won't work for logs coming from service worker syntax workers with the old module registry.
stdoutPrefix @1 :Text;
# Set a custom prefix for process.stdout. Defaults to "stdout: ".
stderrPrefix @2 :Text;
# Set a custom prefix for process.stderr. Defaults to "stderr: ".
}
# ========================================================================================
# Sockets
struct Socket {
name @0 :Text;
# Each socket has a unique name which can be used on the command line to override the socket's
# address with `--socket-addr <name>=<addr>` or `--socket-fd <name>=<fd>`.
address @1 :Text;
# Address/port on which this socket will listen. Optional; if not specified, then you will be
# required to specify the socket on the command line with with `--socket-addr <name>=<addr>` or
# `--socket-fd <name>=<fd>`.
#
# Examples:
# - "*:80": Listen on port 80 on all local IPv4 and IPv6 interfaces.
# - "1.2.3.4": Listen on the specific IPv4 address on the default port for the protocol.
# - "1.2.3.4:80": Listen on the specific IPv4 address and port.
# - "1234:5678::abcd": Listen on the specific IPv6 address on the default port for the protocol.
# - "[1234:5678::abcd]:80": Listen on the specific IPv6 address and port.
# - "unix:/path/to/socket": Listen on a Unix socket.
# - "unix-abstract:name": On Linux, listen on the given "abstract" Unix socket name.
# - "example.com:80": Perform a DNS lookup to determine the address, and then listen on it. If
# this resolves to multiple addresses, listen on all of them.
#
# UDP sockets currently bind only the first address when a hostname resolves to multiple
# addresses. Specify a numeric address when selecting the address family matters.
#
# (These are the formats supported by KJ's parseAddress().)
union {
http @2 :HttpOptions;
https :group {
options @3 :HttpOptions;
tlsOptions @4 :TlsOptions;
}
tcp :group {
tlsOptions @6 :TlsOptions;
}
udp :group {
# Listen for UDP datagrams. Bindings to this service will only support the `connect()`
# method, same as `tcp`; `fetch()` will throw an exception. Unlike `tcp`, the delivered
# Socket's `readable`/`writable` are value-mode: each chunk read or written is exactly one
# datagram (see Socket.protocol).
#
# Datagrams from a given peer address/port are grouped into one flow, dispatched to one
# `connect()` call, until no datagram has been seen from that peer for `idleTimeoutMs`.
idleTimeoutMs @7 :UInt32 = 30000;
# Bound, in bytes, on datagrams queued for one flow waiting to be consumed by
# `DatagramChannel::receive()`. The listener keeps
# draining the kernel socket regardless of whether this flow's queue has room, so one slow
# flow does not block delivery to other peers sharing the same socket.
# Once `maxPendingBytes` worth of datagrams are queued, further arrivals for this flow are
# dropped rather than buffered.
maxPendingBytes @8 :UInt32 = 262144;
}
# TODO(someday): TCP proxy, SMTP, Cap'n Proto, ...
}
service @5 :ServiceDesignator;
# Service name which should handle requests on this socket.
# TODO(someday): Support mapping different hostnames to different services? Or should that be
# done strictly via JavaScript?
}
# ========================================================================================
# Services
struct Service {
# Defines a named service. Each server has a list of named services. The names are private,
# used to refer to the services within this same config file.
name @0 :Text;
# Name of the service. Used only to refer to the service from elsewhere in the config file.
# Services are not accessible unless you explicitly configure them to be, such as through a
# `Socket` or through a binding from another Worker.
union {
unspecified @1 :Void;
# (This catches when someone forgets to specify one of the union members. Do not set this.)
worker @2 :Worker;
# A Worker!
network @3 :Network;
# A service that implements access to a network. fetch() requests are routed according to
# the URL hostname.
external @4 :ExternalServer;
# A service that forwards all requests to a specific remote server. Typically used to
# connect to a back-end server on your internal network.
disk @5 :DiskDirectory;
# An HTTP service backed by a directory on disk, supporting a basic HTTP GET/PUT. Generally
# not intended to be exposed directly to the internet; typically you want to bind this into
# a Worker that adds logic for setting Content-Type and the like.
}
# TODO(someday): Allow defining a list of middlewares to stack on top of the service. This would
# be a list of Worker names, where each Worker must have a binding called `next`. This
# implicitly creates an inherited worker that wraps this service, with the `next` binding
# pointing to the service itself (or to the next middleware in the stack).
}
struct ServiceDesignator {
# A reference to a service from elsewhere in the config file, e.g. from a service binding in a
# Worker.
#
# In the case that only `name` needs to be specified, then you can provide a raw string wherever
# `ServiceDesignator` is needed. Cap'n proto automatically assumes the string is intended to be
# the value for `name`, since that is the first field. In other words, if you would otherwise
# write something like:
#
# bindings = [(service = (name = "foo"))]
#
# You can write this instead, which is equivalent:
#
# bindings = [(service = "foo")]
name @0 :Text;
# Name of the service in the Config.services list.
entrypoint @1 :Text;
# A modules-syntax Worker can export multiple named entrypoints. `export default {` specifies
# the default entrypoint, whereas `export let foo = {` defines an entrypoint named `foo`. If
# `entrypoint` is specified here, it names an alternate entrypoint to use on the target worker,
# otherwise the default is used.
props :union {
# Value to provide in `ctx.props` in the target worker.
empty @2 :Void;
# Empty object. (This is the default.)
json @3 :Text;
# A JSON-encoded value.
}
# TODO(someday): Options to specify which event types are allowed.
# TODO(someday): Allow adding an outgoing middleware stack here (see TODO in Service, above).
}
struct WorkflowsEngine {
# Defines an engine that allows running Workflows defined on this worker.
# These workflows are exposed through the `ctx.exports.*` mechanism
#
# Each Workflow gets assigned its own ActorNamespace, but all of them use the same underlying ActorClass
# to run the Workflows code.
#
# Additionally, a list of workflows can be given to specify which workflows can run or not,
# i.e., which workflows get a binding built for them.
actorClass @0 :ServiceDesignator;
# The actor class implementing the Workflows engine which all local Workflow-related ActorNamespaces
# use to instantiate actors
workflows @1 :List(Workflow);
# List of local workflows that can run for this worker. This controls which workflows get a binding built
# and placed on the `ctx.exports` object
struct Workflow {
# Minimal definition of a Workflow in the context of building a binding for it in `ctx.exports.*`
className @0 :Text;
# The name of the class extending `WorkflowEntrypoint`
name @1 :Text;
# The name of the workflow
bindingService @2 :ServiceDesignator;
# Reference to the service implementing the Workflows public API.
# This is used as the inner fetcher when building the Workflows binding
}
}
struct Worker {
union {
modules @0 :List(Module);
# The Worker is composed of ES modules that may import each other. The first module in the list
# is the main module, which exports event handlers.
serviceWorkerScript @1 :Text;
# The Worker is composed of one big script that uses global `addEventListener()` to register
# event handlers.
#
# The value of this field is the raw source code. When using Cap'n Proto text format, use the
# `embed` directive to read the code from an external file:
#
# serviceWorkerScript = embed "worker.js"
inherit @2 :Text;
# Inherit the configuration of some other Worker by its service name. This Worker is a clone
# of the other worker, but various settings can be modified:
# * `bindings`, if specified, overrides specific named bindings. (Each binding listed in the
# derived worker must match the name and type of some binding in the inherited worker.)
# * `globalOutbound`, if non-null, overrides the one specified in the inherited worker.
# * `compatibilityDate` and `compatibilityFlags` CANNOT be modified; they must be null.
# * If the inherited worker defines durable object namespaces, then the derived worker must
# specify `durableObjectStorage` to specify where its instances should be stored. Each
# devived worker receives its own namespace of objects. `durableObjectUniqueKeyModifier`
# must also be specified by derived workers.
#
# This can be useful when you want to run the same Worker in multiple configurations or hooked
# up to different back-ends. Note that all derived workers run in the same isolate as the
# base worker; they differ in the content of the `env` object passed to them, which contains
# the bindings. (When using service workers syntax, the global scope contains the bindings;
# in this case each derived worker runs in its own global scope, though still in the same
# isolate.)
}
struct Module {
name @0 :Text;
# Name (or path) used to import the module.
union {
esModule @1 :Text;
# An ES module file with imports and exports.
#
# As with `serviceWorkerScript`, above, the value is the raw source code.
commonJsModule @2 :Text;
# A common JS module, using require().
text @3 :Text;
# A raw text blob. Importing this will produce a string with the value.
data @4 :Data;
# A raw data blob. Importing this will produce an ArrayBuffer with the value.
wasm @5 :Data;
# A Wasm module. The value is a compiled binary Wasm module file. Importing this will produce
# a `WebAssembly.Module` object, which you can then instantiate.
json @6 :Text;
# Importing this will produce the result of parsing the given text as JSON.
obsolete @7 :Text;
# This position used to be the nodeJsCompatModule type that has now been
# obsoleted.
pythonModule @8 :Text;
# A Python module. All bundles containing this value type are converted into a JS/WASM Worker
# Bundle prior to execution.
obsoletePythonRequirement @9 :Text;
# This position used to be the pythonRequirement type that has now been deprecated.
}
namedExports @10 :List(Text);
# For commonJsModule modules, this is a list of named exports that the
# module expects to be exported once the evaluation is complete.
#
# (`commonJsModule` should have been a group containing the body and `namedExports`, but it's
# too late to change now.)
}
compatibilityDate @3 :Text;
compatibilityFlags @4 :List(Text);
# See: https://developers.cloudflare.com/workers/platform/compatibility-dates/
#
# `compatibilityDate` must be specified, unless the Worker inhits from another worker, in which
# case it must not be specified. `compatibilityFlags` can optionally be specified when
# `compatibilityDate` is specified.
bindings @5 :List(Binding);
# List of bindings, which give the Worker access to external resources and configuration
# settings.
#
# For Workers using ES modules syntax, the bindings are delivered via the `env` object. For
# service workers syntax, each binding shows up as a global variable.
struct Binding {
name @0 :Text;
union {
unspecified @1 :Void;
# (This catches when someone forgets to specify one of the union members. Do not set this.)
parameter :group {
# Indicates that the Worker requires a binding of the given type, but it won't be specified
# here. Another Worker can inherit this Worker and fill in this binding.
type @2 :Type;
# Expected type of this parameter.
optional @3 :Bool;
# If true, this binding is optional. Derived workers need not specify it, in which case
# the binding won't be present in the environment object passed to the worker.
#
# When a Worker has any non-optional parameters that haven't been filled in, then it can
# only be used for inheritance; it cannot be invoked directly.
}
text @4 :Text;
# A string.
data @5 :Data;
# An ArrayBuffer.
json @6 :Text;
# A value parsed from JSON.
wasmModule @7 :Data;
# A WebAssembly module. The binding will be an instance of `WebAssembly.Module`. Only
# supported when using Service Workers syntax.
#
# DEPRECATED: Please switch to ES modules syntax instead, and embed Wasm modules as modules.
cryptoKey @8 :CryptoKey;
# A CryptoKey instance, for use with the WebCrypto API.
#
# Note that by setting `extractable = false`, you can prevent the Worker code from accessing
# or leaking the raw key material; it will only be able to use the key to perform WebCrypto
# operations.
service @9 :ServiceDesignator;
# Binding to a named service (possibly, a worker).
durableObjectClass @26 :ServiceDesignator;
# A Durable Object class binding, without an actual storage namespace. This can be used to
# implement a facet.
durableObjectNamespace @10 :DurableObjectNamespaceDesignator;
# Binding to the durable object namespace implemented by the given class.
#
# In the common case that this refers to a class in the same Worker, you can specify just
# a string, like:
#
# durableObjectNamespace = "MyClass"
kvNamespace @11 :ServiceDesignator;
# A KV namespace, implemented by the named service. The Worker sees a KvNamespace-typed
# binding. Requests to the namespace will be converted into HTTP requests targeting the
# given service name.
r2Bucket @12 :ServiceDesignator;
# R2 bucket binding. Similar to KV namespaces, this turns operations into HTTP requests aimed
# at the named service.
obsolete0 @13 :ServiceDesignator;
wrapped @14 :WrappedBinding;
# Wraps a collection of inner bindings in a common api functionality.
queue @15 :ServiceDesignator;
# A Queue binding, implemented by the named service. Requests to the
# namespace will be converted into HTTP requests targeting the given
# service name.
fromEnvironment @16 :Text;
# Takes the value of an environment variable from the system. The value specified here is
# the name of a system environment variable. The value of the binding is obtained by invoking
# `getenv()` with that name. If the environment variable isn't set, the binding value is
# `null`.
analyticsEngine @17 :ServiceDesignator;
# A binding for Analytics Engine. Allows workers to store information through Analytics Engine Events.
# workerd will forward AnalyticsEngineEvents to designated service in the body of HTTP requests
# This binding is subject to change and requires the `--experimental` flag
hyperdrive :group {
designator @18 :ServiceDesignator;
database @19 :Text;
user @20 :Text;
password @21 :Text;
scheme @22 :Text;
}
# A binding for Hyperdrive. Allows workers to use Hyperdrive caching & pooling for Postgres
# databases.
unsafeEval @23 :Void;
# A simple binding that enables access to the UnsafeEval API.
memoryCache :group {
# A binding representing access to an in-memory cache.
id @24 :Text;
# The identifier associated with this cache. Any number of isolates
# can access the same in-memory cache (within the same process), and
# each worker may use any number of in-memory caches.
limits @25 :MemoryCacheLimits;
}
workerLoader :group {
# A binding representing the ability to dynamically load Workers from code presented at
# runtime.
#
# A Worker loader is not just a function that loads a Worker, but also serves as a
# cache of Workers, automatically unloading Workers that are not in use. To that end, each
# Worker must have a name, and if a Worker with that name already exists, it'll be reused.
id @27 :Text;
# Optional: The identifier associated with this Worker loader. Multiple Workers can bind to
# the same ID in order to access the same loader, so that if they request the same name
# from it, they'll end up sharing the same loaded Worker.
#
# (If omitted, the binding will not share a cache with any other binding.)
}
workerdDebugPort @28 :Void;
# A binding that provides a connect() method to dynamically connect to any workerd
# instance's debug port. This allows dynamic access to worker entrypoints via the
# WorkerdDebugPort RPC interface.
#
# Usage: const client = await env.DEBUG_PORT.connect("localhost:1234");
# const fetcher = await client.getEntrypoint("service", "entrypoint");
#
# This is a workerd-only API intended for local development and testing.
# TODO(someday): dispatch, other new features
}
struct Type {
# Specifies the type of a parameter binding.
union {
unspecified @0 :Void;
# (This catches when someone forgets to specify one of the union members. Do not set this.)
text @1 :Void;
data @2 :Void;
json @3 :Void;
wasm @4 :Void;
cryptoKey @5 :List(CryptoKey.Usage);
service @6 :Void;
durableObjectNamespace @7 :Void;
kvNamespace @8 :Void;
r2Bucket @9 :Void;
obsolete0 @10 :Void;
queue @11 :Void;
analyticsEngine @12 : Void;
hyperdrive @13: Void;
durableObjectClass @14: Void;
workerdDebugPort @15: Void;
}
}
struct DurableObjectNamespaceDesignator {
# The type of a Durable Object namespace binding.
className @0 :Text;
# Exported class name that implements the Durable Object.
serviceName @1 :Text;
# The service name of the worker that defines this class. If omitted, the current worker
# is assumed.
#
# Use of this field is discouraged. Instead, when accessing a different Worker's Durable
# Objects, specify a `service` binding to that worker, and have the worker implement an
# appropriate API.
#
# (This is intentionally not a ServiceDesignator because you cannot choose an alternate
# entrypoint here; the class name IS the entrypoint.)
retryPolicy @2 :RetryPolicy;
# Limits on how the runtime retries calls through stubs minted from this binding. When
# absent, the runtime's default retry behavior applies.
struct RetryPolicy {
maxAttempts @0 :UInt32 = 4;
# Maximum number of retries after the initial attempt. Zero disables retries, and one
# allows a single retry. The default matches the runtime's default of five attempts in
# total.
timeoutMs @1 :UInt32 = 10000;
# Time in milliseconds, measured from the start of the call, after which no retry may
# start. A retry still running when it expires is cancelled, and the caller gets the
# error that caused the first retry. The initial request, and the first request after each
# redirect, always run to completion. The clock starts after any output-gate wait, and a
# redirect shares the original call's timeout. Must be between 500 and 60,000. The default
# matches the runtime's default.
}
}
struct CryptoKey {
# Parameters to crypto.subtle.importKey().
union {
raw @0 :Data;
hex @1 :Text;
base64 @2 :Text;
# Raw key material, possibly hex or base64-encoded. Use this for symmetric keys.
#
# Hint: `raw` would typically be used with Cap'n Proto's `embed` syntax to embed an
# external binary key file. `hex` or `base64` could do that too but can also be specified
# inline.
pkcs8 @3 :Text;
# Private key in PEM-encoded PKCS#8 format.
spki @4 :Text;
# Public key in PEM-encoded SPKI format.
jwk @5 :Text;
# Key in JSON format.
}
algorithm :union {
# Value for the `algorithm` parameter.
name @6 :Text;
# Just a name, like `AES-GCM`.
json @7 :Text;
# An object, encoded here as JSON.
}
extractable @8 :Bool = false;
# Is the Worker allowed to export this key to obtain the underlying key material? Setting
# this false ensures that the key cannot be leaked by errant JavaScript code; the key can
# only be used in WebCrypto operations.
usages @9 :List(Usage);
# What operations is this key permitted to be used for?
enum Usage {
encrypt @0;
decrypt @1;
sign @2;
verify @3;
deriveKey @4;
deriveBits @5;
wrapKey @6;
unwrapKey @7;
}
}
struct MemoryCacheLimits {
maxKeys @0 :UInt32;
maxValueSize @1 :UInt32;
maxTotalValueSize @2 :UInt64;
}
struct WrappedBinding {
# A binding that wraps a group of (lower-level) bindings in a common API.
moduleName @0 :Text;
# Wrapper module name.
# The module must be an internal one (provided by extension or registered in the c++ code).
# Module will be instantitated during binding initialization phase.
entrypoint @1 :Text = "default";
# Module needs to export a function with a given name (default export gets "default" name).
# The function needs to accept a single `env` argument - a dictionary with inner bindings.
# Function will be invoked during initialization phase and its return value will be used as
# resulting binding value.
innerBindings @2 :List(Binding);
# Inner bindings that will be created and passed in the env dictionary.
# These bindings shall be used to implement end-user api, and are not available to the
# binding consumers unless "re-exported" in wrapBindings function.
}
}
globalOutbound @6 :ServiceDesignator = "internet";
# Where should the global "fetch" go to? The default is the service called "internet", which
# should usually be configured to talk to the public internet.
cacheApiOutbound @11 :ServiceDesignator;
# Where should cache API (i.e. caches.default and caches.open(...)) requests go?
durableObjectNamespaces @7 :List(DurableObjectNamespace);
# List of durable object namespaces in this Worker.
struct DurableObjectNamespace {
className @0 :Text;
# Exported class name that implements the Durable Object.
#
# Changing the class name will not break compatibility with existing storage, so long as
# `uniqueKey` stays the same.
union {
uniqueKey @1 :Text;
# A unique, stable ID associated with this namespace. This could be a GUID, or any other
# string which does not appear anywhere else in the world.
#
# This string is used to ensure that objects of this class have unique identifiers distinct
# from objects of any other class. Object IDs are cryptographically derived from `uniqueKey`
# and validated against it. It is impossible to guess or forge a valid object ID without
# knowing the `uniqueKey`. Hence, if you keep the key secret, you can prevent anyone from
# forging IDs. However, if you don't care if users can forge valid IDs, then it's not a big
# deal if the key leaks.
#
# DO NOT LOSE this key, otherwise it may be difficult or impossible to recover stored data.
ephemeralLocal @2 :Void;
# Instances of this class are ephemeral -- they have no durable storage at all. The
# `state.storage` API will not be present. Additionally, this namespace will allow arbitrary
# strings as IDs. There are no `idFromName()` nor `newUniqueId()` methods; `get()` takes any
# string as a parameter.
#
# Ephemeral objects are NOT globally unique, only "locally" unique, for some definition of
# "local". For example, on Cloudflare's network, these objects are unique per-colo.
#
# WARNING: Cloudflare Workers currently limits this feature to Cloudflare-internal users
# only, because using them correctly requires deep understanding of Cloudflare network
# topology. We're working on something better for public consuption. Until then for
# "ephemeral" use cases we recommend using regular durable objects and just not storing
# anything. An object that hasn't stored anything will not consume any storage space on
# disk.
}
preventEviction @3 :Bool;
# By default, Durable Objects are evicted after 10 seconds of inactivity, and expire 70 seconds
# after all clients have disconnected. Some applications may want to keep their Durable Objects
# pinned to memory forever, so we provide this flag to change the default behavior.
#
# Note that this is only supported in Workerd; production Durable Objects cannot toggle eviction.
enableSql @4 :Bool;
# Whether or not Durable Objects in this namespace can use the `storage.sql` API to execute SQL
# queries.
#
# workerd uses SQLite to back all Durable Objects, but the SQL API is hidden by default to
# emulate behavior of traditional DO namespaces on Cloudflare that aren't SQLite-backed. This
# flag should be enabled when testing code that will run on a SQLite-backed namespace.
container @5 :ContainerOptions;
# If present, Durable Objects in this namespace have attached containers.
# workerd will talk to the configured container engine to start containers for each Durable
# Object from a configured default, a runtime-selected image, or a full container snapshot. The
# Durable Object can access the container via the ctx.container API.
# TODO(CloudChamber): add link to docs.
struct ContainerOptions {
imageName @0 :Text;
# Optional default image used when start() does not specify an image or full container
# snapshot. An empty value means that no default image is configured.
# When imageName omits a tag, Docker uses the "latest" tag.
privileges @1 :ContainerPrivileges;
# Extra Docker HostConfig privileges applied when creating the container.
# These fields are passed through to Docker as-is and are empty by default.
# They are not validated or allow-listed. Depending on the values and Docker daemon mode,
# they can expose arbitrary host devices, disable security profiles, or grant capabilities
# such as CAP_SYS_ADMIN that may provide host-level access. Only use trusted configuration.
images @2 :List(NamedImage);
# Named image references exposed to the Durable Object through ctx.container.images.
# These are optional; Worker code can instead supply an image reference from another source.
# When imageName is empty, the local container backend requires start() to specify an image or
# full container snapshot.
struct NamedImage {
name @0 :Text;
image @1 :Text;
}
struct ContainerPrivileges {
capabilities @0 :List(Text);
# Docker HostConfig.CapAdd values.
devices @1 :List(Device);
# Docker HostConfig.Devices values.
securityOpt @2 :List(Text);
# Docker HostConfig.SecurityOpt values.
struct Device {
pathOnHost @0 :Text;
pathInContainer @1 :Text;
cgroupPermissions @2 :Text;
}
}
}
}
durableObjectUniqueKeyModifier @8 :Text;
# Additional text which is hashed together with `DurableObjectNamespace.uniqueKey`. When using
# worker inheritance, each derived worker must specify a unique modifier to ensure that its
# Durable Object instances have unique IDs from all other workers inheriting the same parent.
#
# DO NOT LOSE this value, otherwise it may be difficult or impossible to recover stored data.
durableObjectStorage :union {
# Specifies where this worker's Durable Objects are stored.
none @9 :Void;
# Default. The worker has no Durable Objects. `durableObjectNamespaces` must be empty, or
# define all namespaces as `ephemeralLocal`, or this must be an abstract worker (meant to be
# inherited by other workers, who will specify `durableObjectStorage`).
inMemory @10 :Void;
# The `state.storage` API stores in-memory only. All stored data will persist for the
# lifetime of the process, but will be lost upon process exit.
#
# Individual objects will still shut down when idle as normal -- only data stored with the
# `state.storage` interface is persistent for the lifetime of the process.
#
# This mode is intended for local testing purposes.
localDisk @12 :Text;
# ** EXPERIMENTAL; SUBJECT TO BACKWARDS-INCOMPATIBLE CHANGE **
#
# Durable Object data will be stored in a directory on local disk. This field is the name of
# a service, which must be a DiskDirectory service. For each Durable Object class, a
# subdirectory will be created using `uniqueKey` as the name. Within the directory, one or
# more files are created for each object, with names `<id>.<ext>`, where `.<ext>` may be any of
# a number of different extensions depending on the storage mode. (Currently, the main storage
# is a file with the extension `.sqlite`, and in certain situations extra files with the
# extensions `.sqlite-wal`, and `.sqlite-shm` may also be present.)
}
# TODO(someday): Support distributing objects across a cluster. At present, objects are always
# local to one instance of the runtime.
moduleFallback @13 :Text;
tails @14 :List(ServiceDesignator);
# List of tail worker services that should receive tail events for this worker.
# See: https://developers.cloudflare.com/workers/observability/logs/tail-workers/
streamingTails @15 :List(ServiceDesignator);
# List of streaming tail worker services that should receive tail events for this worker.
# NOTE: This will be deleted in a future refactor, do not depend on this.
containerEngine :union {
none @16 :Void;
# No container engine configured. Container operations will not be available.
localDocker @17 :DockerConfiguration;
# Use local Docker daemon for container operations.
# Only used for local development and testing purposes.
}
struct DockerConfiguration {
socketPath @0 :Text;
# Path to the Docker socket.
containerEgressInterceptorImage @1 :Text;
# Docker image name for the container egress interceptor sidecar.
# This sidecar intercepts outbound traffic from containers and routes it
# through workerd for egress mappings (setEgressHttp bindings).
# You can find this image in repositories like DockerHub: https://hub.docker.com/r/cloudflare/proxy-everything
}
accessBlobHeader @18 :Text;
# Name of the HTTP header carrying per-request Cloudflare Access metadata for local dev.
# When set, the worker reads this header from every incoming request to populate `ctx.access`.
# The header value is a JSON object matching the production Access struct:
# { "app_aud": "<audience>", "jwt_claims": { ... } }
# `app_aud` (string, required) populates `ctx.access.aud`.
# `jwt_claims` (object, optional) is passed as `ctx.props.jwtClaims` to the access binding
# worker (if configured via `accessBindingService`) when `ctx.access.getIdentity()` is called.
# Requests that carry the header get `ctx.access` populated; requests without it get
# `ctx.access === undefined`.
accessBindingService @19 :ServiceDesignator;
# Names a service that acts as the Cloudflare Access identity binding worker for local dev.
# When `ctx.access.getIdentity()` is called, workerd dispatches a `getIdentity` JS-RPC method
# on this service with per-request `props` set to `{ aud }` or `{ aud, jwtClaims }` (extracted
# from the `accessBlobHeader` HTTP header; `jwtClaims` is included only when the optional
# `jwt_claims` field is present in the header). This mimics the production path where an
# Access binding worker resolves the identity from JWT claims.
#
# If not set, `ctx.access.getIdentity()` resolves to `undefined` (even when `accessBlobHeader`
# is configured and `ctx.access.aud` is available).
workflowsEngine @20 :WorkflowsEngine;
# the externally-supplied service responsible for running Workflows defined in this worker
}
struct ExternalServer {
# Describes the ability to talk to a specific server, typically a back-end server available
# on the internal network.
#
# When a Worker contains a service binding that points to an ExternalServer, *all* fetch()
# calls on that binding will be delivered to that server, regardless of whether the hostname
# or protocol specified in the URL actually match the hostname or protocol used by the actual
# server. Typically, a Worker implementing a reverse proxy would use this to forward a request
# to a back-end application server. Such a back-end typically does not have a real public
# hostname, since it is only reachable through the proxy, but the requests forwarded to it will
# keep the hostname that was on the original request.
#
# Note that this also implies that regardless of whether the original URL was http: or https:,
# the request will be delivered to the target server using the protocol specified below. A
# header like `X-Forwarded-Proto` can be used to pass along the original protocol; see
# `HttpOptions`.
address @0 :Text;
# Address/port of the server. Optional; if not specified, then you will be required to specify
# the address on the command line with with `--external-addr <name>=<addr>`.
#
# Examples:
# - "1.2.3.4": Connect to the given IPv4 address on the protocol's default port.
# - "1.2.3.4:80": Connect to the given IPv4 address and port.
# - "1234:5678::abcd": Connect to the given IPv6 address on the protocol's default port.
# - "[1234:5678::abcd]:80": Connect to the given IPv6 address and port.
# - "unix:/path/to/socket": Connect to the given Unix Domain socket by path.
# - "unix-abstract:name": On Linux, connect to the given "abstract" Unix socket name.
# - "example.com:80": Perform a DNS lookup to determine the address, and then connect to it.
#
# (These are the formats supported by KJ's parseAddress().)
union {
http @1 :HttpOptions;
# Talk to the server over unencrypted HTTP.
https :group {
# Talk to the server over encrypted HTTPS.
options @2 :HttpOptions;
tlsOptions @3 :TlsOptions;
certificateHost @4 :Text;
# If present, expect the host to present a certificate authenticating it as this hostname.
# If `certificateHost` is not provided, then the certificate is checked against `address`.
}
tcp :group {
# Connect to the server over raw TCP. Bindings to this service will only support the
# `connect()` method; `fetch()` will throw an exception.
tlsOptions @5 :TlsOptions;
certificateHost @6 :Text;
}
# TODO(someday): Cap'n Proto RPC
}
}
struct Network {
# Describes the ability to talk to a network.
#
# This is commonly used to define the "internet" service which is the default `globalOutbound`
# for all Workers. To prevent SSRF, by default Workers will not be permitted to reach internal
# network addresses using global fetch(). It's recommended that you create ExternalServer
# bindings instead to grant access to specific servers. However, if you really want to, you
# can configure a service that grants arbitrary internal network access, like:
#
# ( name = "internalNetwork",
# network = (
# allow = ["public", "private"],
# )
# )
allow @0 :List(Text) = ["public"];
deny @1 :List(Text);
# Specifies which network addresses the Worker will be allowed to connect to, e.g. using fetch().
# The default allows publicly-routable IP addresses only, in order to prevent SSRF attacks.
#
# The allow and deny lists specify network blocks in CIDR notation (IPv4 and IPv6), such as
# "192.0.2.0/24" or "2001:db8::/32". Traffic will be permitted as long as the address
# matches at least one entry in the allow list and none in the deny list.
#
# In addition to IPv4 and IPv6 CIDR notation, several special strings may be specified:
# - "private": Matches network addresses that are reserved by standards for private networks,
# such as "10.0.0.0/8" or "192.168.0.0/16". This is a superset of "local".
# - "public": Opposite of "private".
# - "local": Matches network addresses that are defined by standards to only be accessible from
# the local machine, such as "127.0.0.0/8" or Unix domain addresses.
# - "network": Opposite of "local".
# - "unix": Matches all Unix domain socket addresses. (In the future, we may support specifying a
# glob to narrow this to specific paths.)
# - "unix-abstract": Matches Linux's "abstract unix domain" addresses. (In the future, we may
# support specifying a glob.)
#
# In the case that the Worker specifies a DNS hostname rather than a raw address, these rules are
# used to filter the addresses returned by the lookup. If none of the returned addresses turn
# out to be permitted, then the system will behave as if the DNS entry did not exist.
#
# (The above is exactly the format supported by kj::Network::restrictPeers().)
tlsOptions @2 :TlsOptions;
}
struct DiskDirectory {
# Configures access to a directory on disk. This is a type of service which will expose an HTTP
# interface to the directory content.
#
# This is very bare-bones, generally not suitable for serving a web site on its own. In
# particular, no attempt is made to guess the `Content-Type` header. You normally would wrap
# this in a Worker that fills in the metadata in the way you want.
#
# A GET request targeting a directory (rather than a file) will return a basic JSAN directory
# listing like:
#
# [{"name":"foo","type":"file"},{"name":"bar","type":"directory"}]
#
# Possible "type" values are "file", "directory", "symlink", "blockDevice", "characterDevice",
# "namedPipe", "socket", "other".
#
# `Content-Type` will be `application/octet-stream` for files or `application/json` for a