package wasmcloud:component-go@0.1.0;

package wasmcloud:hello {
	world hello {
		import wasi:config/runtime@0.2.0-draft;
		import wasmcloud:messaging/types@0.2.0;
		import wasmcloud:messaging/consumer@0.2.0;
		import wasi:logging/logging@0.1.0-draft;
		import wasi:io/poll@0.2.0;
		import wasi:clocks/monotonic-clock@0.2.0;
		import wasi:io/error@0.2.0;
		import wasi:io/streams@0.2.0;
		import wasi:http/types@0.2.0;
		import wasi:http/outgoing-handler@0.2.0;
		import wasmcloud:bus/lattice@1.0.0;
		import wasmcloud:secrets/store@0.1.0-draft;
		import wasmcloud:secrets/reveal@0.1.0-draft;
		import wasi:cli/environment@0.2.0;
		import wasi:cli/exit@0.2.0;
		import wasi:cli/stdin@0.2.0;
		import wasi:cli/stdout@0.2.0;
		import wasi:cli/stderr@0.2.0;
		import wasi:cli/terminal-input@0.2.0;
		import wasi:cli/terminal-output@0.2.0;
		import wasi:cli/terminal-stdin@0.2.0;
		import wasi:cli/terminal-stdout@0.2.0;
		import wasi:cli/terminal-stderr@0.2.0;
		import wasi:clocks/wall-clock@0.2.0;
		import wasi:filesystem/types@0.2.0;
		import wasi:filesystem/preopens@0.2.0;
		import wasi:sockets/network@0.2.0;
		import wasi:sockets/instance-network@0.2.0;
		import wasi:sockets/udp@0.2.0;
		import wasi:sockets/udp-create-socket@0.2.0;
		import wasi:sockets/tcp@0.2.0;
		import wasi:sockets/tcp-create-socket@0.2.0;
		import wasi:sockets/ip-name-lookup@0.2.0;
		import wasi:random/random@0.2.0;
		import wasi:random/insecure@0.2.0;
		import wasi:random/insecure-seed@0.2.0;
		export wasi:http/incoming-handler@0.2.0;
		export wasmcloud:messaging/handler@0.2.0;
	}
}

package wasi:config@0.2.0-draft {
	interface runtime {
		/// An error type that encapsulates the different errors that can occur fetching config
		variant config-error {
			/// This indicates an error from an "upstream" config source.
			/// As this could be almost _anything_ (such as Vault, Kubernetes ConfigMaps, KeyValue
			/// buckets, etc),
			/// the error message is a string.
			upstream(string),
			/// This indicates an error from an I/O operation.
			/// As this could be almost _anything_ (such as a file read, network connection, etc),
			/// the error message is a string.
			/// Depending on how this ends up being consumed,
			/// we may consider moving this to use the `wasi:io/error` type instead.
			/// For simplicity right now in supporting multiple implementations, it is being left
			/// as a string.
			io(string),
		}

		/// Gets a single opaque config value set at the given key if it exists
		get: func(key: string) -> result<option<string>, config-error>;

		/// Gets a list of all set config data
		get-all: func() -> result<list<tuple<string, string>>, config-error>;
	}
}

package wasi:filesystem@0.2.0 {
	interface types {
		use wasi:io/streams@0.2.0.{input-stream};
		use wasi:io/streams@0.2.0.{output-stream};
		use wasi:io/streams@0.2.0.{error};
		use wasi:clocks/wall-clock@0.2.0.{datetime};
		type filesize = u64;
		enum descriptor-type {
			unknown,
			block-device,
			character-device,
			directory,
			fifo,
			symbolic-link,
			regular-file,
			socket
		}
		flags descriptor-flags {
			read,
			write,
			file-integrity-sync,
			data-integrity-sync,
			requested-write-sync,
			mutate-directory,
		}
		flags path-flags { symlink-follow }
		flags open-flags {
			create,
			directory,
			exclusive,
			truncate,
		}
		type link-count = u64;
		record descriptor-stat {
			%type: descriptor-type,
			link-count: link-count,
			size: filesize,
			data-access-timestamp: option<datetime>,
			data-modification-timestamp: option<datetime>,
			status-change-timestamp: option<datetime>,
		}
		variant new-timestamp {
			no-change,
			now,
			timestamp(datetime),
		}
		record directory-entry {
			%type: descriptor-type,
			name: string,
		}
		enum error-code {
			access,
			would-block,
			already,
			bad-descriptor,
			busy,
			deadlock,
			quota,
			exist,
			file-too-large,
			illegal-byte-sequence,
			in-progress,
			interrupted,
			invalid,
			io,
			is-directory,
			loop,
			too-many-links,
			message-size,
			name-too-long,
			no-device,
			no-entry,
			no-lock,
			insufficient-memory,
			insufficient-space,
			not-directory,
			not-empty,
			not-recoverable,
			unsupported,
			no-tty,
			no-such-device,
			overflow,
			not-permitted,
			pipe,
			read-only,
			invalid-seek,
			text-file-busy,
			cross-device
		}
		enum advice {
			normal,
			sequential,
			random,
			will-need,
			dont-need,
			no-reuse
		}
		record metadata-hash-value {
			lower: u64,
			upper: u64,
		}
		resource descriptor {
			advise: func(offset: filesize, length: filesize, advice: advice) -> result<_, error-code>;
			append-via-stream: func() -> result<output-stream, error-code>;
			create-directory-at: func(path: string) -> result<_, error-code>;
			get-flags: func() -> result<descriptor-flags, error-code>;
			get-type: func() -> result<descriptor-type, error-code>;
			is-same-object: func(other: borrow<descriptor>) -> bool;
			link-at: func(old-path-flags: path-flags, old-path: string, new-descriptor: borrow<descriptor>, new-path: string) -> result<_, error-code>;
			metadata-hash: func() -> result<metadata-hash-value, error-code>;
			metadata-hash-at: func(path-flags: path-flags, path: string) -> result<metadata-hash-value, error-code>;
			open-at: func(path-flags: path-flags, path: string, open-flags: open-flags, %flags: descriptor-flags) -> result<descriptor, error-code>;
			read: func(length: filesize, offset: filesize) -> result<tuple<list<u8>, bool>, error-code>;
			read-directory: func() -> result<directory-entry-stream, error-code>;
			read-via-stream: func(offset: filesize) -> result<input-stream, error-code>;
			readlink-at: func(path: string) -> result<string, error-code>;
			remove-directory-at: func(path: string) -> result<_, error-code>;
			rename-at: func(old-path: string, new-descriptor: borrow<descriptor>, new-path: string) -> result<_, error-code>;
			set-size: func(size: filesize) -> result<_, error-code>;
			set-times: func(data-access-timestamp: new-timestamp, data-modification-timestamp: new-timestamp) -> result<_, error-code>;
			set-times-at: func(path-flags: path-flags, path: string, data-access-timestamp: new-timestamp, data-modification-timestamp: new-timestamp) -> result<_, error-code>;
			stat: func() -> result<descriptor-stat, error-code>;
			stat-at: func(path-flags: path-flags, path: string) -> result<descriptor-stat, error-code>;
			symlink-at: func(old-path: string, new-path: string) -> result<_, error-code>;
			sync: func() -> result<_, error-code>;
			sync-data: func() -> result<_, error-code>;
			unlink-file-at: func(path: string) -> result<_, error-code>;
			write: func(buffer: list<u8>, offset: filesize) -> result<filesize, error-code>;
			write-via-stream: func(offset: filesize) -> result<output-stream, error-code>;
		}
		resource directory-entry-stream {
			read-directory-entry: func() -> result<option<directory-entry>, error-code>;
		}
		filesystem-error-code: func(err: borrow<error>) -> option<error-code>;
	}

	interface preopens {
		use types.{descriptor};
		get-directories: func() -> list<tuple<descriptor, string>>;
	}
}

package wasi:http@0.2.0 {
	/// This interface defines all of the types and methods for implementing
	/// HTTP Requests and Responses, both incoming and outgoing, as well as
	/// their headers, trailers, and bodies.
	interface types {
		use wasi:clocks/monotonic-clock@0.2.0.{duration};
		use wasi:io/streams@0.2.0.{input-stream};
		use wasi:io/streams@0.2.0.{output-stream};
		use wasi:io/error@0.2.0.{error as io-error};
		use wasi:io/poll@0.2.0.{pollable};

		/// This type corresponds to HTTP standard Methods.
		variant method {
			get,
			head,
			post,
			put,
			delete,
			connect,
			options,
			trace,
			patch,
			other(string),
		}

		/// This type corresponds to HTTP standard Related Schemes.
		variant scheme { HTTP, HTTPS, other(string) }

		/// Defines the case payload type for `DNS-error` above:
		record DNS-error-payload {
			rcode: option<string>,
			info-code: option<u16>,
		}

		/// Defines the case payload type for `TLS-alert-received` above:
		record TLS-alert-received-payload {
			alert-id: option<u8>,
			alert-message: option<string>,
		}

		/// Defines the case payload type for `HTTP-response-{header,trailer}-size` above:
		record field-size-payload {
			field-name: option<string>,
			field-size: option<u32>,
		}

		/// These cases are inspired by the IANA HTTP Proxy Error Types:
		/// https://www.iana.org/assignments/http-proxy-status/http-proxy-status.xhtml#table-http-proxy-error-types
		variant error-code {
			DNS-timeout,
			DNS-error(DNS-error-payload),
			destination-not-found,
			destination-unavailable,
			destination-IP-prohibited,
			destination-IP-unroutable,
			connection-refused,
			connection-terminated,
			connection-timeout,
			connection-read-timeout,
			connection-write-timeout,
			connection-limit-reached,
			TLS-protocol-error,
			TLS-certificate-error,
			TLS-alert-received(TLS-alert-received-payload),
			HTTP-request-denied,
			HTTP-request-length-required,
			HTTP-request-body-size(option<u64>),
			HTTP-request-method-invalid,
			HTTP-request-URI-invalid,
			HTTP-request-URI-too-long,
			HTTP-request-header-section-size(option<u32>),
			HTTP-request-header-size(option<field-size-payload>),
			HTTP-request-trailer-section-size(option<u32>),
			HTTP-request-trailer-size(field-size-payload),
			HTTP-response-incomplete,
			HTTP-response-header-section-size(option<u32>),
			HTTP-response-header-size(field-size-payload),
			HTTP-response-body-size(option<u64>),
			HTTP-response-trailer-section-size(option<u32>),
			HTTP-response-trailer-size(field-size-payload),
			HTTP-response-transfer-coding(option<string>),
			HTTP-response-content-coding(option<string>),
			HTTP-response-timeout,
			HTTP-upgrade-failed,
			HTTP-protocol-error,
			loop-detected,
			configuration-error,
			/// This is a catch-all error for anything that doesn't fit cleanly into a
			/// more specific case. It also includes an optional string for an
			/// unstructured description of the error. Users should not depend on the
			/// string for diagnosing errors, as it's not required to be consistent
			/// between implementations.
			internal-error(option<string>),
		}

		/// This type enumerates the different kinds of errors that may occur when
		/// setting or appending to a `fields` resource.
		variant header-error {
			/// This error indicates that a `field-key` or `field-value` was
			/// syntactically invalid when used with an operation that sets headers in a
			/// `fields`.
			invalid-syntax,
			/// This error indicates that a forbidden `field-key` was used when trying
			/// to set a header in a `fields`.
			forbidden,
			/// This error indicates that the operation on the `fields` was not
			/// permitted because the fields are immutable.
			immutable,
		}

		/// Field keys are always strings.
		type field-key = string;

		/// Field values should always be ASCII strings. However, in
		/// reality, HTTP implementations often have to interpret malformed values,
		/// so they are provided as a list of bytes.
		type field-value = list<u8>;

		/// This following block defines the `fields` resource which corresponds to
		/// HTTP standard Fields. Fields are a common representation used for both
		/// Headers and Trailers.
		///
		/// A `fields` may be mutable or immutable. A `fields` created using the
		/// constructor, `from-list`, or `clone` will be mutable, but a `fields`
		/// resource given by other means (including, but not limited to,
		/// `incoming-request.headers`, `outgoing-request.headers`) might be be
		/// immutable. In an immutable fields, the `set`, `append`, and `delete`
		/// operations will fail with `header-error.immutable`.
		resource fields {
			/// Construct an empty HTTP Fields.
			///
			/// The resulting `fields` is mutable.
			constructor();

			/// Append a value for a key. Does not change or delete any existing
			/// values for that key.
			///
			/// Fails with `header-error.immutable` if the `fields` are immutable.
			append: func(name: field-key, value: field-value) -> result<_, header-error>;

			/// Make a deep copy of the Fields. Equivelant in behavior to calling the
			/// `fields` constructor on the return value of `entries`. The resulting
			/// `fields` is mutable.
			clone: func() -> fields;

			/// Delete all values for a key. Does nothing if no values for the key
			/// exist.
			///
			/// Fails with `header-error.immutable` if the `fields` are immutable.
			delete: func(name: field-key) -> result<_, header-error>;

			/// Retrieve the full set of keys and values in the Fields. Like the
			/// constructor, the list represents each key-value pair.
			///
			/// The outer list represents each key-value pair in the Fields. Keys
			/// which have multiple values are represented by multiple entries in this
			/// list with the same key.
			entries: func() -> list<tuple<field-key, field-value>>;

			/// Get all of the values corresponding to a key. If the key is not present
			/// in this `fields`, an empty list is returned. However, if the key is
			/// present but empty, this is represented by a list with one or more
			/// empty field-values present.
			get: func(name: field-key) -> list<field-value>;

			/// Returns `true` when the key is present in this `fields`. If the key is
			/// syntactically invalid, `false` is returned.
			has: func(name: field-key) -> bool;

			/// Set all of the values for a key. Clears any existing values for that
			/// key, if they have been set.
			///
			/// Fails with `header-error.immutable` if the `fields` are immutable.
			set: func(name: field-key, value: list<field-value>) -> result<_, header-error>;

			/// Construct an HTTP Fields.
			///
			/// The resulting `fields` is mutable.
			///
			/// The list represents each key-value pair in the Fields. Keys
			/// which have multiple values are represented by multiple entries in this
			/// list with the same key.
			///
			/// The tuple is a pair of the field key, represented as a string, and
			/// Value, represented as a list of bytes. In a valid Fields, all keys
			/// and values are valid UTF-8 strings. However, values are not always
			/// well-formed, so they are represented as a raw list of bytes.
			///
			/// An error result will be returned if any header or value was
			/// syntactically invalid, or if a header was forbidden.
			from-list: static func(entries: list<tuple<field-key, field-value>>) -> result<fields, header-error>;
		}

		/// Headers is an alias for Fields.
		type headers = fields;

		/// Trailers is an alias for Fields.
		type trailers = fields;

		/// Represents an incoming HTTP Request.
		resource incoming-request {

			/// Returns the authority from the request, if it was present.
			authority: func() -> option<string>;

			/// Gives the `incoming-body` associated with this request. Will only
			/// return success at most once, and subsequent calls will return error.
			consume: func() -> result<incoming-body>;

			/// Get the `headers` associated with the request.
			///
			/// The returned `headers` resource is immutable: `set`, `append`, and
			/// `delete` operations will fail with `header-error.immutable`.
			///
			/// The `headers` returned are a child resource: it must be dropped before
			/// the parent `incoming-request` is dropped. Dropping this
			/// `incoming-request` before all children are dropped will trap.
			headers: func() -> headers;

			/// Returns the method of the incoming request.
			method: func() -> method;

			/// Returns the path with query parameters from the request, as a string.
			path-with-query: func() -> option<string>;

			/// Returns the protocol scheme from the request.
			scheme: func() -> option<scheme>;
		}

		/// Represents an outgoing HTTP Request.
		resource outgoing-request {
			/// Construct a new `outgoing-request` with a default `method` of `GET`, and
			/// `none` values for `path-with-query`, `scheme`, and `authority`.
			///
			/// * `headers` is the HTTP Headers for the Request.
			///
			/// It is possible to construct, or manipulate with the accessor functions
			/// below, an `outgoing-request` with an invalid combination of `scheme`
			/// and `authority`, or `headers` which are not permitted to be sent.
			/// It is the obligation of the `outgoing-handler.handle` implementation
			/// to reject invalid constructions of `outgoing-request`.
			constructor(headers: headers);

			/// Get the HTTP Authority for the Request. A value of `none` may be used
			/// with Related Schemes which do not require an Authority. The HTTP and
			/// HTTPS schemes always require an authority.
			authority: func() -> option<string>;

			/// Returns the resource corresponding to the outgoing Body for this
			/// Request.
			///
			/// Returns success on the first call: the `outgoing-body` resource for
			/// this `outgoing-request` can be retrieved at most once. Subsequent
			/// calls will return error.
			body: func() -> result<outgoing-body>;

			/// Get the headers associated with the Request.
			///
			/// The returned `headers` resource is immutable: `set`, `append`, and
			/// `delete` operations will fail with `header-error.immutable`.
			///
			/// This headers resource is a child: it must be dropped before the parent
			/// `outgoing-request` is dropped, or its ownership is transfered to
			/// another component by e.g. `outgoing-handler.handle`.
			headers: func() -> headers;

			/// Get the Method for the Request.
			method: func() -> method;

			/// Get the combination of the HTTP Path and Query for the Request.
			/// When `none`, this represents an empty Path and empty Query.
			path-with-query: func() -> option<string>;

			/// Get the HTTP Related Scheme for the Request. When `none`, the
			/// implementation may choose an appropriate default scheme.
			scheme: func() -> option<scheme>;

			/// Set the HTTP Authority for the Request. A value of `none` may be used
			/// with Related Schemes which do not require an Authority. The HTTP and
			/// HTTPS schemes always require an authority. Fails if the string given is
			/// not a syntactically valid uri authority.
			set-authority: func(authority: option<string>) -> result;

			/// Set the Method for the Request. Fails if the string present in a
			/// `method.other` argument is not a syntactically valid method.
			set-method: func(method: method) -> result;

			/// Set the combination of the HTTP Path and Query for the Request.
			/// When `none`, this represents an empty Path and empty Query. Fails is the
			/// string given is not a syntactically valid path and query uri component.
			set-path-with-query: func(path-with-query: option<string>) -> result;

			/// Set the HTTP Related Scheme for the Request. When `none`, the
			/// implementation may choose an appropriate default scheme. Fails if the
			/// string given is not a syntactically valid uri scheme.
			set-scheme: func(scheme: option<scheme>) -> result;
		}

		/// Parameters for making an HTTP Request. Each of these parameters is
		/// currently an optional timeout applicable to the transport layer of the
		/// HTTP protocol.
		///
		/// These timeouts are separate from any the user may use to bound a
		/// blocking call to `wasi:io/poll.poll`.
		resource request-options {
			/// Construct a default `request-options` value.
			constructor();

			/// The timeout for receiving subsequent chunks of bytes in the Response
			/// body stream.
			between-bytes-timeout: func() -> option<duration>;

			/// The timeout for the initial connect to the HTTP Server.
			connect-timeout: func() -> option<duration>;

			/// The timeout for receiving the first byte of the Response body.
			first-byte-timeout: func() -> option<duration>;

			/// Set the timeout for receiving subsequent chunks of bytes in the Response
			/// body stream. An error return value indicates that this timeout is not
			/// supported.
			set-between-bytes-timeout: func(duration: option<duration>) -> result;

			/// Set the timeout for the initial connect to the HTTP Server. An error
			/// return value indicates that this timeout is not supported.
			set-connect-timeout: func(duration: option<duration>) -> result;

			/// Set the timeout for receiving the first byte of the Response body. An
			/// error return value indicates that this timeout is not supported.
			set-first-byte-timeout: func(duration: option<duration>) -> result;
		}

		/// Represents the ability to send an HTTP Response.
		///
		/// This resource is used by the `wasi:http/incoming-handler` interface to
		/// allow a Response to be sent corresponding to the Request provided as the
		/// other argument to `incoming-handler.handle`.
		resource response-outparam {

			/// Set the value of the `response-outparam` to either send a response,
			/// or indicate an error.
			///
			/// This method consumes the `response-outparam` to ensure that it is
			/// called at most once. If it is never called, the implementation
			/// will respond with an error.
			///
			/// The user may provide an `error` to `response` to allow the
			/// implementation determine how to respond with an HTTP error response.
			set: static func(param: response-outparam, response: result<outgoing-response, error-code>);
		}

		/// This type corresponds to the HTTP standard Status Code.
		type status-code = u16;

		/// Represents an incoming HTTP Response.
		resource incoming-response {

			/// Returns the incoming body. May be called at most once. Returns error
			/// if called additional times.
			consume: func() -> result<incoming-body>;

			/// Returns the headers from the incoming response.
			///
			/// The returned `headers` resource is immutable: `set`, `append`, and
			/// `delete` operations will fail with `header-error.immutable`.
			///
			/// This headers resource is a child: it must be dropped before the parent
			/// `incoming-response` is dropped.
			headers: func() -> headers;

			/// Returns the status code from the incoming response.
			status: func() -> status-code;
		}

		/// Represents an incoming HTTP Request or Response's Body.
		///
		/// A body has both its contents - a stream of bytes - and a (possibly
		/// empty) set of trailers, indicating that the full contents of the
		/// body have been received. This resource represents the contents as
		/// an `input-stream` and the delivery of trailers as a `future-trailers`,
		/// and ensures that the user of this interface may only be consuming either
		/// the body contents or waiting on trailers at any given time.
		resource incoming-body {

			/// Returns the contents of the body, as a stream of bytes.
			///
			/// Returns success on first call: the stream representing the contents
			/// can be retrieved at most once. Subsequent calls will return error.
			///
			/// The returned `input-stream` resource is a child: it must be dropped
			/// before the parent `incoming-body` is dropped, or consumed by
			/// `incoming-body.finish`.
			///
			/// This invariant ensures that the implementation can determine whether
			/// the user is consuming the contents of the body, waiting on the
			/// `future-trailers` to be ready, or neither. This allows for network
			/// backpressure is to be applied when the user is consuming the body,
			/// and for that backpressure to not inhibit delivery of the trailers if
			/// the user does not read the entire body.
			%stream: func() -> result<input-stream>;

			/// Takes ownership of `incoming-body`, and returns a `future-trailers`.
			/// This function will trap if the `input-stream` child is still alive.
			finish: static func(this: incoming-body) -> future-trailers;
		}

		/// Represents a future which may eventaully return trailers, or an error.
		///
		/// In the case that the incoming HTTP Request or Response did not have any
		/// trailers, this future will resolve to the empty set of trailers once the
		/// complete Request or Response body has been received.
		resource future-trailers {

			/// Returns the contents of the trailers, or an error which occured,
			/// once the future is ready.
			///
			/// The outer `option` represents future readiness. Users can wait on this
			/// `option` to become `some` using the `subscribe` method.
			///
			/// The outer `result` is used to retrieve the trailers or error at most
			/// once. It will be success on the first call in which the outer option
			/// is `some`, and error on subsequent calls.
			///
			/// The inner `result` represents that either the HTTP Request or Response
			/// body, as well as any trailers, were received successfully, or that an
			/// error occured receiving them. The optional `trailers` indicates whether
			/// or not trailers were present in the body.
			///
			/// When some `trailers` are returned by this method, the `trailers`
			/// resource is immutable, and a child. Use of the `set`, `append`, or
			/// `delete` methods will return an error, and the resource must be
			/// dropped before the parent `future-trailers` is dropped.
			get: func() -> option<result<result<option<trailers>, error-code>>>;

			/// Returns a pollable which becomes ready when either the trailers have
			/// been received, or an error has occured. When this pollable is ready,
			/// the `get` method will return `some`.
			subscribe: func() -> pollable;
		}

		/// Represents an outgoing HTTP Response.
		resource outgoing-response {
			/// Construct an `outgoing-response`, with a default `status-code` of `200`.
			/// If a different `status-code` is needed, it must be set via the
			/// `set-status-code` method.
			///
			/// * `headers` is the HTTP Headers for the Response.
			constructor(headers: headers);

			/// Returns the resource corresponding to the outgoing Body for this Response.
			///
			/// Returns success on the first call: the `outgoing-body` resource for
			/// this `outgoing-response` can be retrieved at most once. Subsequent
			/// calls will return error.
			body: func() -> result<outgoing-body>;

			/// Get the headers associated with the Request.
			///
			/// The returned `headers` resource is immutable: `set`, `append`, and
			/// `delete` operations will fail with `header-error.immutable`.
			///
			/// This headers resource is a child: it must be dropped before the parent
			/// `outgoing-request` is dropped, or its ownership is transfered to
			/// another component by e.g. `outgoing-handler.handle`.
			headers: func() -> headers;

			/// Set the HTTP Status Code for the Response. Fails if the status-code
			/// given is not a valid http status code.
			set-status-code: func(status-code: status-code) -> result;

			/// Get the HTTP Status Code for the Response.
			status-code: func() -> status-code;
		}

		/// Represents an outgoing HTTP Request or Response's Body.
		///
		/// A body has both its contents - a stream of bytes - and a (possibly
		/// empty) set of trailers, inducating the full contents of the body
		/// have been sent. This resource represents the contents as an
		/// `output-stream` child resource, and the completion of the body (with
		/// optional trailers) with a static function that consumes the
		/// `outgoing-body` resource, and ensures that the user of this interface
		/// may not write to the body contents after the body has been finished.
		///
		/// If the user code drops this resource, as opposed to calling the static
		/// method `finish`, the implementation should treat the body as incomplete,
		/// and that an error has occured. The implementation should propogate this
		/// error to the HTTP protocol by whatever means it has available,
		/// including: corrupting the body on the wire, aborting the associated
		/// Request, or sending a late status code for the Response.
		resource outgoing-body {

			/// Returns a stream for writing the body contents.
			///
			/// The returned `output-stream` is a child resource: it must be dropped
			/// before the parent `outgoing-body` resource is dropped (or finished),
			/// otherwise the `outgoing-body` drop or `finish` will trap.
			///
			/// Returns success on the first call: the `output-stream` resource for
			/// this `outgoing-body` may be retrieved at most once. Subsequent calls
			/// will return error.
			write: func() -> result<output-stream>;

			/// Finalize an outgoing body, optionally providing trailers. This must be
			/// called to signal that the response is complete. If the `outgoing-body`
			/// is dropped without calling `outgoing-body.finalize`, the implementation
			/// should treat the body as corrupted.
			///
			/// Fails if the body's `outgoing-request` or `outgoing-response` was
			/// constructed with a Content-Length header, and the contents written
			/// to the body (via `write`) does not match the value given in the
			/// Content-Length.
			finish: static func(this: outgoing-body, trailers: option<trailers>) -> result<_, error-code>;
		}

		/// Represents a future which may eventaully return an incoming HTTP
		/// Response, or an error.
		///
		/// This resource is returned by the `wasi:http/outgoing-handler` interface to
		/// provide the HTTP Response corresponding to the sent Request.
		resource future-incoming-response {

			/// Returns the incoming HTTP Response, or an error, once one is ready.
			///
			/// The outer `option` represents future readiness. Users can wait on this
			/// `option` to become `some` using the `subscribe` method.
			///
			/// The outer `result` is used to retrieve the response or error at most
			/// once. It will be success on the first call in which the outer option
			/// is `some`, and error on subsequent calls.
			///
			/// The inner `result` represents that either the incoming HTTP Response
			/// status and headers have recieved successfully, or that an error
			/// occured. Errors may also occur while consuming the response body,
			/// but those will be reported by the `incoming-body` and its
			/// `output-stream` child.
			get: func() -> option<result<result<incoming-response, error-code>>>;

			/// Returns a pollable which becomes ready when either the Response has
			/// been received, or an error has occured. When this pollable is ready,
			/// the `get` method will return `some`.
			subscribe: func() -> pollable;
		}

		/// Attempts to extract a http-related `error` from the wasi:io `error`
		/// provided.
		///
		/// Stream operations which return
		/// `wasi:io/stream/stream-error::last-operation-failed` have a payload of
		/// type `wasi:io/error/error` with more information about the operation
		/// that failed. This payload can be passed through to this function to see
		/// if there's http-related information about the error to return.
		///
		/// Note that this function is fallible because not all io-errors are
		/// http-related errors.
		http-error-code: func(err: borrow<io-error>) -> option<error-code>;
	}

	/// This interface defines a handler of incoming HTTP Requests. It should
	/// be exported by components which can respond to HTTP Requests.
	interface incoming-handler {
		use types.{incoming-request};
		use types.{response-outparam};

		/// This function is invoked with an incoming HTTP Request, and a resource
		/// `response-outparam` which provides the capability to reply with an HTTP
		/// Response. The response is sent by calling the `response-outparam.set`
		/// method, which allows execution to continue after the response has been
		/// sent. This enables both streaming to the response body, and performing other
		/// work.
		///
		/// The implementor of this function must write a response to the
		/// `response-outparam` before returning, or else the caller will respond
		/// with an error on its behalf.
		handle: func(request: incoming-request, response-out: response-outparam);
	}

	/// This interface defines a handler of outgoing HTTP Requests. It should be
	/// imported by components which wish to make HTTP Requests.
	interface outgoing-handler {
		use types.{outgoing-request};
		use types.{request-options};
		use types.{future-incoming-response};
		use types.{error-code};

		/// This function is invoked with an outgoing HTTP Request, and it returns
		/// a resource `future-incoming-response` which represents an HTTP Response
		/// which may arrive in the future.
		///
		/// The `options` argument accepts optional parameters for the HTTP
		/// protocol's transport layer.
		///
		/// This function may return an error if the `outgoing-request` is invalid
		/// or not allowed to be made. Otherwise, protocol errors are reported
		/// through the `future-incoming-response`.
		handle: func(request: outgoing-request, options: option<request-options>) -> result<future-incoming-response, error-code>;
	}
}

package wasi:cli@0.2.0 {
	interface stdout {
		use wasi:io/streams@0.2.0.{output-stream};
		get-stdout: func() -> output-stream;
	}

	interface stderr {
		use wasi:io/streams@0.2.0.{output-stream};
		get-stderr: func() -> output-stream;
	}

	interface stdin {
		use wasi:io/streams@0.2.0.{input-stream};
		get-stdin: func() -> input-stream;
	}

	interface environment {
		get-environment: func() -> list<tuple<string, string>>;
		get-arguments: func() -> list<string>;
		initial-cwd: func() -> option<string>;
	}

	interface exit {
		exit: func(status: result);
	}

	interface terminal-input {
		resource terminal-input;
	}

	interface terminal-output {
		resource terminal-output;
	}

	interface terminal-stdin {
		use terminal-input.{terminal-input};
		get-terminal-stdin: func() -> option<terminal-input>;
	}

	interface terminal-stdout {
		use terminal-output.{terminal-output};
		get-terminal-stdout: func() -> option<terminal-output>;
	}

	interface terminal-stderr {
		use terminal-output.{terminal-output};
		get-terminal-stderr: func() -> option<terminal-output>;
	}
}

package wasi:io@0.2.0 {
	interface poll {
		resource pollable {
			block: func();
			ready: func() -> bool;
		}
		poll: func(in: list<borrow<pollable>>) -> list<u32>;
	}

	interface error {
		resource error {
			to-debug-string: func() -> string;
		}
	}

	interface streams {
		use error.{error};
		use poll.{pollable};
		variant stream-error {
			last-operation-failed(error),
			closed,
		}
		resource input-stream {
			blocking-read: func(len: u64) -> result<list<u8>, stream-error>;
			blocking-skip: func(len: u64) -> result<u64, stream-error>;
			read: func(len: u64) -> result<list<u8>, stream-error>;
			skip: func(len: u64) -> result<u64, stream-error>;
			subscribe: func() -> pollable;
		}
		resource output-stream {
			blocking-flush: func() -> result<_, stream-error>;
			blocking-splice: func(src: borrow<input-stream>, len: u64) -> result<u64, stream-error>;
			blocking-write-and-flush: func(contents: list<u8>) -> result<_, stream-error>;
			blocking-write-zeroes-and-flush: func(len: u64) -> result<_, stream-error>;
			check-write: func() -> result<u64, stream-error>;
			flush: func() -> result<_, stream-error>;
			splice: func(src: borrow<input-stream>, len: u64) -> result<u64, stream-error>;
			subscribe: func() -> pollable;
			write: func(contents: list<u8>) -> result<_, stream-error>;
			write-zeroes: func(len: u64) -> result<_, stream-error>;
		}
	}
}

package wasi:logging@0.1.0-draft {
	/// WASI Logging is a logging API intended to let users emit log messages with
	/// simple priority levels and context values.
	interface logging {
		/// A log level, describing a kind of message.
		enum level {
			/// Describes messages about the values of variables and the flow of
			/// control within a program.
			trace,
			/// Describes messages likely to be of interest to someone debugging a
			/// program.
			debug,
			/// Describes messages likely to be of interest to someone monitoring a
			/// program.
			info,
			/// Describes messages indicating hazardous situations.
			warn,
			/// Describes messages indicating serious errors.
			error,
			/// Describes messages indicating fatal errors.
			critical
		}

		/// Emit a log message.
		///
		/// A log message has a `level` describing what kind of message is being
		/// sent, a context, which is an uninterpreted string meant to help
		/// consumers group similar messages, and a string containing the message
		/// text.
		log: func(level: level, context: string, message: string);
	}
}

package wasi:random@0.2.0 {
	interface random {
		get-random-bytes: func(len: u64) -> list<u8>;
		get-random-u64: func() -> u64;
	}

	interface insecure {
		get-insecure-random-bytes: func(len: u64) -> list<u8>;
		get-insecure-random-u64: func() -> u64;
	}

	interface insecure-seed {
		insecure-seed: func() -> tuple<u64, u64>;
	}
}

package wasi:sockets@0.2.0 {
	interface network {
		resource network;
		enum error-code {
			unknown,
			access-denied,
			not-supported,
			invalid-argument,
			out-of-memory,
			timeout,
			concurrency-conflict,
			not-in-progress,
			would-block,
			invalid-state,
			new-socket-limit,
			address-not-bindable,
			address-in-use,
			remote-unreachable,
			connection-refused,
			connection-reset,
			connection-aborted,
			datagram-too-large,
			name-unresolvable,
			temporary-resolver-failure,
			permanent-resolver-failure
		}
		enum ip-address-family { ipv4, ipv6 }
		type ipv4-address = tuple<u8, u8, u8, u8>;
		type ipv6-address = tuple<u16, u16, u16, u16, u16, u16, u16, u16>;
		variant ip-address {
			ipv4(ipv4-address),
			ipv6(ipv6-address),
		}
		record ipv4-socket-address {
			port: u16,
			address: ipv4-address,
		}
		record ipv6-socket-address {
			port: u16,
			flow-info: u32,
			address: ipv6-address,
			scope-id: u32,
		}
		variant ip-socket-address {
			ipv4(ipv4-socket-address),
			ipv6(ipv6-socket-address),
		}
	}

	interface instance-network {
		use network.{network};
		instance-network: func() -> network;
	}

	interface udp {
		use wasi:io/poll@0.2.0.{pollable};
		use network.{network};
		use network.{error-code};
		use network.{ip-socket-address};
		use network.{ip-address-family};
		record incoming-datagram {
			data: list<u8>,
			remote-address: ip-socket-address,
		}
		record outgoing-datagram {
			data: list<u8>,
			remote-address: option<ip-socket-address>,
		}
		resource udp-socket {
			address-family: func() -> ip-address-family;
			finish-bind: func() -> result<_, error-code>;
			local-address: func() -> result<ip-socket-address, error-code>;
			receive-buffer-size: func() -> result<u64, error-code>;
			remote-address: func() -> result<ip-socket-address, error-code>;
			send-buffer-size: func() -> result<u64, error-code>;
			set-receive-buffer-size: func(value: u64) -> result<_, error-code>;
			set-send-buffer-size: func(value: u64) -> result<_, error-code>;
			set-unicast-hop-limit: func(value: u8) -> result<_, error-code>;
			start-bind: func(network: borrow<network>, local-address: ip-socket-address) -> result<_, error-code>;
			%stream: func(remote-address: option<ip-socket-address>) -> result<tuple<incoming-datagram-stream, outgoing-datagram-stream>, error-code>;
			subscribe: func() -> pollable;
			unicast-hop-limit: func() -> result<u8, error-code>;
		}
		resource incoming-datagram-stream {
			receive: func(max-results: u64) -> result<list<incoming-datagram>, error-code>;
			subscribe: func() -> pollable;
		}
		resource outgoing-datagram-stream {
			check-send: func() -> result<u64, error-code>;
			send: func(datagrams: list<outgoing-datagram>) -> result<u64, error-code>;
			subscribe: func() -> pollable;
		}
	}

	interface udp-create-socket {
		use network.{network};
		use network.{error-code};
		use network.{ip-address-family};
		use udp.{udp-socket};
		create-udp-socket: func(address-family: ip-address-family) -> result<udp-socket, error-code>;
	}

	interface tcp {
		use wasi:io/streams@0.2.0.{input-stream};
		use wasi:io/streams@0.2.0.{output-stream};
		use wasi:io/poll@0.2.0.{pollable};
		use wasi:clocks/monotonic-clock@0.2.0.{duration};
		use network.{network};
		use network.{error-code};
		use network.{ip-socket-address};
		use network.{ip-address-family};
		enum shutdown-type { receive, send, both }
		resource tcp-socket {
			accept: func() -> result<tuple<tcp-socket, input-stream, output-stream>, error-code>;
			address-family: func() -> ip-address-family;
			finish-bind: func() -> result<_, error-code>;
			finish-connect: func() -> result<tuple<input-stream, output-stream>, error-code>;
			finish-listen: func() -> result<_, error-code>;
			hop-limit: func() -> result<u8, error-code>;
			is-listening: func() -> bool;
			keep-alive-count: func() -> result<u32, error-code>;
			keep-alive-enabled: func() -> result<bool, error-code>;
			keep-alive-idle-time: func() -> result<duration, error-code>;
			keep-alive-interval: func() -> result<duration, error-code>;
			local-address: func() -> result<ip-socket-address, error-code>;
			receive-buffer-size: func() -> result<u64, error-code>;
			remote-address: func() -> result<ip-socket-address, error-code>;
			send-buffer-size: func() -> result<u64, error-code>;
			set-hop-limit: func(value: u8) -> result<_, error-code>;
			set-keep-alive-count: func(value: u32) -> result<_, error-code>;
			set-keep-alive-enabled: func(value: bool) -> result<_, error-code>;
			set-keep-alive-idle-time: func(value: duration) -> result<_, error-code>;
			set-keep-alive-interval: func(value: duration) -> result<_, error-code>;
			set-listen-backlog-size: func(value: u64) -> result<_, error-code>;
			set-receive-buffer-size: func(value: u64) -> result<_, error-code>;
			set-send-buffer-size: func(value: u64) -> result<_, error-code>;
			shutdown: func(shutdown-type: shutdown-type) -> result<_, error-code>;
			start-bind: func(network: borrow<network>, local-address: ip-socket-address) -> result<_, error-code>;
			start-connect: func(network: borrow<network>, remote-address: ip-socket-address) -> result<_, error-code>;
			start-listen: func() -> result<_, error-code>;
			subscribe: func() -> pollable;
		}
	}

	interface tcp-create-socket {
		use network.{network};
		use network.{error-code};
		use network.{ip-address-family};
		use tcp.{tcp-socket};
		create-tcp-socket: func(address-family: ip-address-family) -> result<tcp-socket, error-code>;
	}

	interface ip-name-lookup {
		use wasi:io/poll@0.2.0.{pollable};
		use network.{network};
		use network.{error-code};
		use network.{ip-address};
		resource resolve-address-stream {
			resolve-next-address: func() -> result<option<ip-address>, error-code>;
			subscribe: func() -> pollable;
		}
		resolve-addresses: func(network: borrow<network>, name: string) -> result<resolve-address-stream, error-code>;
	}
}

package wasi:clocks@0.2.0 {
	interface monotonic-clock {
		use wasi:io/poll@0.2.0.{pollable};
		type instant = u64;
		type duration = u64;
		now: func() -> instant;
		resolution: func() -> duration;
		subscribe-instant: func(when: instant) -> pollable;
		subscribe-duration: func(when: duration) -> pollable;
	}

	interface wall-clock {
		record datetime {
			seconds: u64,
			nanoseconds: u32,
		}
		now: func() -> datetime;
		resolution: func() -> datetime;
	}
}

package wasmcloud:bus@1.0.0 {
	interface lattice {
		resource call-target-interface {
			constructor(namespace: string, %package: string, %interface: string);
		}
		set-link-name: func(name: string, interfaces: list<call-target-interface>);
	}
}

package wasmcloud:messaging@0.2.0 {
	/// Types common to message broker interactions
	interface types {
		/// A message sent to or received from a broker
		record broker-message {
			subject: string,
			body: list<u8>,
			reply-to: option<string>,
		}
	}

	interface handler {
		use types.{broker-message};

		/// Callback handled to invoke a function when a message is received from a subscription
		handle-message: func(msg: broker-message) -> result<_, string>;
	}

	interface consumer {
		use types.{broker-message};

		/// Perform a request operation on a subject
		request: func(subject: string, body: list<u8>, timeout-ms: u32) -> result<broker-message, string>;

		/// Publish a message to a subject without awaiting a response
		publish: func(msg: broker-message) -> result<_, string>;
	}
}

package wasmcloud:secrets@0.1.0-draft {
	interface store {
		variant secrets-error {
			upstream(string),
			io(string),
			not-found,
		}
		variant secret-value {
			%string(string),
			bytes(list<u8>),
		}
		resource secret;
		get: func(key: string) -> result<secret, secrets-error>;
	}

	interface reveal {
		use store.{secret};
		use store.{secret-value};
		reveal: func(s: borrow<secret>) -> secret-value;
	}
}
