Build your own
An integration is one Go value that imports github.com/outis-auth/outis-sdk, implements Integration (a Manifest()) and whichever capabilities it has. The core finds them by type assertion, so there’s no method to stub. The module has no dependencies.
The capabilities
Section titled “The capabilities”| Interface | Implement it to |
|---|---|
Renderer, with Manifest.Actions |
Provide actions. Each is an ActionSpec: an id, a label, and the policy envelope a new organization starts from. The renderer draws each request for the panel. |
Responder |
Tell the system that asked what was decided, with one idempotent call on every outcome. |
Proposer |
Turn an outside event into a request, for your own actions or another integration’s. A SelfVerifying proposer names routes the platform signs itself, mounted outside the API key guard. |
Notifier |
Carry the arming code to an operator. A LastResort notifier reaches no person and sorts behind every channel that does. |
Configurable |
Declare the settings you read from the environment, so the dashboard can say which are unset without showing their values. |
IdentityFlow |
Prove which account on your platform an operator holds, through the platform’s own OAuth sign in. |
Validate checks the combination: actions need a renderer, a renderer or responder needs actions, and an integration does at least one thing.
The rules
Section titled “The rules”A proposer proposes within the envelope policy allows and never sets a quorum. An inbound call belongs to an organization only through a connection the core proved or an id the platform signed; otherwise the proposal leaves Org empty and the core fills it from the API key. Nothing Outis holds, like a webhook secret, is handed to a customer.
A Responder makes at most one call, bound to what the operators saw: merge this pull request at this sha, submit this review, answer this pending deployment. It never retries and never acts on a head that moved. A refusal from that system lands the request in failed.
Conformance
Section titled “Conformance”Every integration runs sdktest.Run as its test, supplying a constructor with faked transports, representative params per action, and how to build a request its proposer accepts. The suite checks that an arming code never reaches the log, that one notify is one send, and that the same decision handed over twice is delivered once.
func TestConformance(t *testing.T) {
sdktest.Run(t, sdktest.Suite{
New: func(t *testing.T, log *slog.Logger) sdk.Integration {
return New(fakeTransport(t), log)
},
Params: map[string]map[string]string{
"example.release": {"service": "api", "version": "2.4.0"},
},
})
}
A rule every integration should follow belongs in sdktest, so every integration gets it.
Shipping it
Section titled “Shipping it”Each integration ships a README on the shared template, opening with what it provides: actions, proposes, notifies, responds. The server reads its settings from the environment, so its routes exist from the first boot and answer with what’s missing until the variables are set.