# Func / Boson Extensibility
###### tags: `Functions`
## Architecture
There are two main workflows for the `func` tool:
### Initiation
This is the workflow for the start of a project:
```plantuml
|#lightgreen|Plugin|
|#lightblue|Func common|
start
:func create <path> $LANGUAGE;
|Plugin|
:$LANGUAGE template;
|Func common|
:Directory populated;
stop
```
### Development Loop
This is the workflow each time a developer wants to deploy their function:
```plantuml
|#lightgreen|Plugin|
|#lightblue|Func common|
start
:func deploy;
if (image built?) is (no) then
:stage code;
|Plugin|
:build image
(buildpack);
|Func common|
:upload image
via pack;
else (yes)
|Func common|
:reuse image;
endif
:create or update
knative service;
stop
```
## Plug-in surface
We're particularly interested in defining two things:
1. The interface between the "Plugin" and "Func common" code. Note that this _extends_ the https://buildpacks.io/ interface with the addition of a function template.
2. The mechanism by which plugins are registered with `func` so that it knows which plugin to invoke. For buildpacks, this is currently hard-coded at: https://github.com/boson-project/func/blob/main/buildpacks/builder.go#L31
## `func` Value-Add
Func provides scaffolding for common operations as well as common help and workflows. In some cases, `func` may wrap existing tooling such as `pack` or Tekton, and in other cases (`create`, parts of `deploy`), it may directly implement functionality.
:::info
Where possible, `func` should work seamlessly with the underlying tools to provide an introduction to the wider ecosystem and create transferable knowledge for users.
:::
For example, it may make sense to transition from a custom `func.yaml` to buildpacks' `project.toml`, to support building with either `func build` or the `pack` CLI. `func` will provide a common platform to experiment with improved workflows, which will benefit all languages.
## Plug-in Value-Add
The plug-in interface can roughly be described as a "language plugin", though it is possible for a CNCF buildpack to [build artifacts for more than one language through a meta-buildpack](https://buildpacks.io/docs/concepts/components/buildpack/#meta-buildpack), the initial design will focus on single-language extensions.
By making the `func` interface pluggable, this enables three outcomes:
1. Enables experimentation with function interfaces on a per-language level. Example: the most natural calling interface for JavaScript (object spreading) may be completely unnatural in Java (reflection) and vice-versa.
2. Enables vendors to ship opinions that align with their platform. Example: Red Hat may recommend UBI-based images, while Google recommends `distroless` base.
3. Enables end-users to customize both recommended function templates and buildpacks. Example: Bank A might require certain audit libraries, while contractor B might require FIPS crypto audit libraries.
I'm not suggesting a specific interface for either the `func`:plugin interface or how to configure the set of plugins considered by `func` in this document, but these seem like early areas of architecture to address and formalize. Once these contracts are formalized, teams on each side of the interface will be able to develop and experiment independently.
### Plug-in Interface
It's likely that the plug-in interface will need to specify something like the following:
* A template for new functions using this runtime
* In the initial design, this might require each plug-in to be language specific, but we should plan over time to support [meta-buildpacks](https://buildpacks.io/docs/concepts/components/buildpack/#meta-buildpack) which can build multiple languages at once
* A [builder image](https://buildpacks.io/docs/concepts/components/builder/)
:::info
**Design Goal**: It would be nice to be able to reference a plug-in via a single URL, in the same way that a builder image can be referenced by a single URL.
:::
(In the current `func` experience, it's possible to create new templates with a directory in `$HOME/.config/func/templates`, which can include a `.builders.yaml` file to specify the builder to use.)