sluis

package module
v1.61.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 4, 2026 License: MIT Imports: 1 Imported by: 0

README

sluis

CI

Formerly access-roster (CLI accessctl, now sluisctl). What changed and what deliberately did not: ADR 0035.

The policy is the product. One file in git turns the groups your people already have in the corporate directory, and the identities your machines already hold — a GitHub Actions job, a Kubernetes ServiceAccount — into one vocabulary of internal groups, gated per audience at one small OpenID provider.

Everything that can read a claim gets that vocabulary minted into a token: Kubernetes, AWS, ArgoCD, Kargo and every console behind your gateway trust that one token, and so do CI jobs and workloads, from the identity they already hold. Everything that cannot read a claim — GitHub teams and Slack channels — gets it reconciled into a membership instead, by a controller reading the same file. A console shows you who holds what and why, and an audit installation of its own, rendered beside it, keeps who did what. A leaver disappears from the directory and, within a freshness window, from everything downstream: authoritative or held, never guessed.

Nothing here authenticates anyone. Sign-in, passwords, MFA and device policy stay with Google Workspace, and later Entra. This verifies the result, knows the directory, and applies the policy — configured from a Helm chart, with no database of record and no users of its own.

What ships

Every artifact is stamped by one tag, vX.Y.Z; pin one version of this repository.

Artifact Published at For
sluis chart and image oci://ghcr.io/truvity/charts/sluis, ghcr.io/truvity/sluis/sluis the installation, once. One binary with three jobs, one image, one chart: serve (the directory, the policy, the OpenID provider, the login page, the console and the audit trail), controller github (one loop that keeps every connected GitHub organisation's teams as the policy says, reporting to the console) and controller slack (the same for Slack channels; a dry run until a workspace is in controllerSlack.config.enabledWorkspaces). The chart runs each as its own Deployment. Replaces the access-issuer chart and the access-issuer, github-roster and slack-roster images: the migration shipped
access-proxy chart removed in v1.32.0 the chart was Envoy Gateway's external authorization backend; gateway-native OIDC replaces it there. For a gateway that is not Envoy Gateway, run upstream oauth2-proxy yourself — see docs/design/access-proxy.md, ADR 0003. Versions already published stay available. removed
Go module github.com/truvity/sluis services and consoles in Go: verify a bearer, read the caller's groups shipped
TypeScript package @truvity/sluis on GitHub Packages console UIs: useIdentity() over /.access/whoami; Node services: verify a bearer shipped
sluisctl the release's archives, and a Nix flake on every release people on laptops and CI jobs: one sign-in, then kubeconfigs, AWS credentials, a token for any audience, and short-lived certificates a secret manager mints shipped
GitHub Action truvity/sluis@<commit> workflows: one exchange, then a kubeconfig, AWS profiles, or a GitHub App token shipped
the policy one file, one schema the issuer and the controllers shipped
an Entra directory backend — a second corporate directory, behind the same workspace record planned

Who it is for

A platform team running Kubernetes, with the Gateway API, cert-manager, and a corporate directory in Google Workspace, that wants one issuer for its clusters, cloud accounts, consoles and CI instead of an identity product. Envoy Gateway gets you gateway-native OIDC, the default now for a console with no authorization model of its own. For a gateway that is not Envoy Gateway, run upstream oauth2-proxy yourself (removed from this repository in v1.32.0; see docs/design/access-proxy.md). A Valkey (for more than one replica), an audit installation (for a trail that is a record) and OpenBAO (for certificates) are optional. None of those is installed here: the charts point at them. Nor is the signing key minted here — cert-manager issues it, or the installation delivers it — and no password, MFA or device policy lives here: sign-in stays with the corporate directory.

The niche

Every mature identity provider can do this. None of them is built for it, and the difference is what you run to get it.

dex Keycloak, Zitadel, Authentik Okta, Auth0, Entra ID Teleport sluis
runs on a ConfigMap a database, an operator, a login UI you theme someone else's cloud its own Auth and Proxy services, plus an agent per resource a ConfigMap
users none, federates its own user store, plus federation its own user store its own local users, plus SSO connectors none, federates
groups in the token yes for Google Workspace, given a service account with domain-wide delegation; other IdPs only if they send them after you write a mapper or a login hook per IdP after you configure a sync not a token: short-lived certificates carry roles an SSO connector mapped once, at login read from the directory, always
several corporate IdPs, one issuer yes yes yes yes, several SSO connectors (OIDC, SAML, GitHub) yes
one policy file for people and machines no policy at all no; roles per client, in the UI or the database no; per-app assignments no; roles are Teleport's own resources, separate from the SSO mapping yes, in git — and GitHub teams in the same file
CI and workloads without a stored secret token exchange (RFC 8693), but the client still needs a stored secret machine users, with secrets machine users, with secrets yes — Machine ID's own join methods (cloud IAM, Kubernetes, CI OIDC) token exchange from GitHub's or the cluster's own token
audience gating for cloud roles no via custom mappers via app assignments not verified a requires list per client
who is in this group and why, at a glance no the admin UI, eventually the admin UI its own web UI the directory console
operational footprint tiny large, and you own it none, and you rent it large: an Auth Service, a Proxy Service and an agent per resource tiny

dex comes closest to this shape: its Google connector reads Workspace groups given a service account with domain-wide delegation, and it can exchange a machine's own token for one of its own (RFC 8693). What it does not have is a policy — no file mapping those groups to audiences, no per-client gate, and no GitHub-teams reconciliation, so each of those is a mapper, a hook or a sync written and run per relying party. The heavy providers can be made to do all of it, at the cost of running an identity product to use about a fifth of one. Teleport issues its own SSH, database and Kubernetes certificates and runs its own access proxy in front of your infrastructure; sluis does not try to be that. sluis is dex's shape, with the directory read built in and one policy file doing the rest: minted into tokens where a relying party can read a claim, reconciled into memberships where it cannot.

What you get

As a person. Sign in once, at one page, with your corporate account. Every console behind the gateway opens without another login. One sluisctl login on your laptop, and kubectl works on every cluster you are granted, AWS credentials come with no long-lived key, and a token for any other audience is one command away. Link your GitHub account once and the teams the policy puts you in follow. Sign out once: it ends immediately at every client wired for Back-Channel Logout; for a gateway-fronted console it ends within that token's own lifetime or ttl_cap, since the gateway learns only at its next refresh; and an application that minted its own session after signing in is reached only through Back-Channel Logout, or whatever limit it put on that session itself (how each kind finds out).

As a machine. A GitHub Actions job presents the identity token it already has and receives one for AWS or a cluster, under a rule that names the repository, the ref and, if you want, the repository's visibility. The same sluisctl, kubeconfig and AWS profile a person uses on a laptop work unchanged inside the job. A workload in any cluster does the same with its ServiceAccount token. No secret is stored anywhere, and the rule sits in the same file as the human ones.

As the operator. One chart. The policy is values. The console shows every person, every directory group, every internal group, every rule that grants one, every open session, every GitHub organisation with what the controller would change and why, and every Slack workspace and channel, with its people and why each is held. A leaver disappears from the directory and, within the freshness window, from everything downstream, GitHub teams included. Every sign-in, refusal, exchange, revoke and console action is one record in an S3 bucket you own. What the console adds at runtime lives in a handful of Secrets that a copy of restores.

The model

The directory says who a person is and which directory groups they are in. The policy maps directory groups, CI jobs and workloads into internal groups, named <scope>:<thing>:<role>. A client is everything that trusts the issuer — a cluster, a cloud role, a console — and names the internal groups it requires; it is usually a row in the policy, but a client the installation does not deploy may instead describe itself by an allow-listed URL. A resource is what a token is for, when that is not the client asking — a client names one (RFC 8707) and it becomes the token's audience, with its own requires. A token is minted for a client or a resource, carries the internal groups, and is refused before it exists when neither gate is satisfied.

The shape
flowchart LR
  idp["Corporate directory<br/>Google Workspace, Entra later"]
  gh["GitHub Actions"]
  k8s["Any cluster's<br/>ServiceAccount tokens"]

  subgraph ar["sluis"]
    iss["the issuer<br/>reads the directory · applies the policy · mints tokens<br/>serves the login page and the console"]
    ctl["the GitHub controller<br/>keeps each organisation's teams as the policy says"]
    sctl["the Slack controller<br/>keeps each workspace's channels as the policy says"]
  end

  gg["Envoy Gateway OIDC<br/>gateway-native, per console with no OIDC of its own"]
  apps["Kubernetes · AWS · ArgoCD · Kargo · consoles"]
  orgs["GitHub organisations"]
  slack["Slack workspaces"]
  aud[("audit installation<br/>the audit trail, in this service's namespace")]

  idp -- "sign-in, and directory reads" --> iss
  gh -- "token exchange" --> iss
  k8s -- "token exchange" --> iss
  iss --> gg --> apps
  iss -- "trusted by" --> apps
  iss -. "who holds which group" .-> ctl
  ctl -- "invites, teams, removals" --> orgs
  iss -. "who holds which group" .-> sctl
  sctl -- "invites, channels, removals" --> slack
  iss -- "every record" --> aud
  ctl -- "what it did" --> aud
  sctl -- "what it did" --> aud

One chart, one Valkey, one bucket. A login makes no network call except to the corporate directory — and, for a client that identifies itself by a URL instead of a policy row, one bounded, cached HTTPS fetch of that client's own document, from an allow-listed host only (reference/policy.md). An application that needs identity inside itself — per-user authorization from groups, per-user audit, tokens of its own to call something else, the way ArgoCD and Kargo do — signs in as its own client of the issuer directly: native OIDC. A console with no authorization model of its own, that only needs may this person reach it at all, defaults instead to gateway-native OIDC: an Envoy Gateway SecurityPolicy with oidc: against a declared client, gated by that client's requires, with no OIDC code in the console (which door). access-proxy — upstream oauth2-proxy in a chart, and Envoy Gateway's external authorization backend, so it worked nowhere else — was removed in v1.32.0: gateway-native OIDC replaces it on Envoy Gateway. On any other gateway, run upstream oauth2-proxy yourself, with a declared confidential client row of this issuer; it is not a chart of ours. Its server-side session store was never a reason to prefer it either way — oauth2-proxy encrypts each session with a key only the browser's cookie holds, so nothing server-side, Back-Channel Logout included, can end one (why, ADR 0003). The GitHub controller and the Slack controller are second processes from the same chart, asking the issuer who holds which group and acting on GitHub with an App, or on Slack with a bot, that an owner created from the console; each acts only in the organisations or workspaces listed in its enabledOrgs / enabledWorkspaces, and a removal rests on a vouched directory answer and never exceeds half a target without an operator's confirmation.

Many in, many out, one point in the middle

Every row is a guide of its own: follow it and add one more without asking anyone.

Fans in Fans out
corporate directories: several Google Workspaces, Entra next — each a workspace with its own credential and its own served domains Kubernetes clusters, for people: each trusts the one issuer as its identity provider
CI platforms — GitHub Actions today: one federated issuer, an owner allow-list AWS accounts: each trusts the one issuer as an OIDC provider
every cluster's own ServiceAccount tokens, for workloads: one row per cluster naming its key set; AWS IAM roles' outbound-federation tokens, one row per account GitHub organisations: one controller App each, bindings in the same policy, and a runner App per tier for self-hosted runners
Slack workspaces: one bot each, channels bound in the same policy, console channels fed by directory groups, and Slack Connect channels between your own workspaces; Slack Apps declared as data
consoles and applications: one client row each

Adding one of anything is one row and one trust registration. The issuer URL, the policy file and the console never multiply.

Everything in both columns is built and in use, with one exception: the second directory backend (Entra) is designed behind the same workspace record and not written yet. architecture.md says how each row is expressed in configuration.

Install and a worked example

helm install sluis oci://ghcr.io/truvity/charts/sluis \
  --version X.Y.Z --namespace sluis --create-namespace \
  --values issuer-values.yaml
config:                                    # `sluis serve`'s configuration file, as it stands
  issuerURL: https://access.example.com    # stable for the life of the installation
  release: sluis                   # the release's full name
  publicRootURL: https://access.example.com
  publicURL: https://access.example.com/console
  valkey:
    address: valkey.sluis.svc:6379
  oauthClient:                             # keys client-id and client-secret
    secretName: access-issuer-google-client
    idFile: /var/run/access-issuer/oauth-client/client-id
    secretFile: /var/run/access-issuer/oauth-client/client-secret
  console:
    client: access-console
secretMounts:
  - { secretName: access-issuer-google-client, mountPath: /var/run/access-issuer/oauth-client }
# signingKey.certificate is left at its default: a P-384 key, so every token is ES384.
# A relying party that accepts only RS256 (Kargo; kube-apiserver flags left at their
# default) needs {algorithm: RSA, size: 2048, encoding: PKCS1} there instead.
route:
  host: access.example.com
  rootRedirect: /console/
  gatewayClassName: example-gateway-class
  certificate: { issuerName: example-ca, issuerKind: ClusterIssuer }
policy:
  groups:
    all:access-roster:operator:
      members: [platform-admins@example.com]
      matchers:                                   # the first way in: recovery
        - service_account: { namespace: sluis, name: access-issuer-recovery }
    all:access-roster:viewer:
      matchers: [{ email_domain: example.com }]
  clients:
    access-console:
      kind: public
      redirects: [https://access.example.com/console/]
      requires: [all:access-roster:operator, all:access-roster:viewer]

Then sign in once with a recovery token (kubectl -n sluis create token access-issuer-recovery --audience access-issuer-recovery), and the console's Overview walks the rest: connecting the directory, and the first operator who signs in as themselves. docs/operations/adoption-plain-helm.md is the whole walk-through, with the prerequisites and a gateway-native OIDC setup for consoles with no authorization model of their own.

Consumers

The sluis chart installs in truvity/gitops and a second, non-AWS estate. The Go module is imported by truvity/gitops (for policy, in its render tests) and by truvity/gemaal (for identity), and used by CI workflows via the sluisctl command. The sluis chart serves as a token audience for truvity/cloudflare (r2broker) and truvity/observability (vmauth). Developers use sluisctl to mint credentials locally; it is also used in CI jobs. The GitHub Action truvity/sluis is used in workflows for token exchange.

Neighbours

sluis is the issuer in a three-part system with two other repositories:

  • openbao: sluis mints tokens; openbao is a relying party that trusts them and issues certificates. See openbao's docs/integrations/sluis.md.
  • audit: every decision, sign-in, refusal, exchange and console action is one record in the audit trail, written by the issuer and by each controller for itself.
  • workstation: sluisctl (from this repository) and awsctl both mint AWS credentials on a developer machine; sluisctl is the estate path, awsctl the SSO fallback (when sluis is unreachable).

Conformance

sluis targets four OpenID Foundation profiles. A profile is claimed only once the suite says so, so this is the last run rather than an intention.

Last run 2026-09-12 against the deployed issuer at v1.0.0, from the suite running in the cluster.

Profile Passed Review Skipped Warning Failed
Config OP 1 0 0 0 0
Basic OP 21 4 4 6 0
RP-Initiated Logout OP 3 8 0 0 0
Back-Channel Logout OP 2 0 0 0 0

The Foundation's rule is that only FAILED or INTERRUPTED disqualify a profile. REVIEW is a screenshot the suite hands to a person; all twelve were looked at on this run and each shows the page its step demanded. WARNING is mostly personal data this issuer declines to hold — a birthdate, a gender, a locale — with one real defect among them found and fixed in v0.15.2. The logout pair the Foundation requires for a submission, RP-Initiated plus Back-Channel, is green for the first time; the first Back-Channel run found two defects, fixed in v0.17.1. Every column, and why, is in docs/conformance.md.

Documentation

docs/index.md is the one entry point: a map to every page, organised by what you are trying to do. Three starting points from there are worth naming here — docs/adoption.md for what taking this into use requires, docs/safety.md for what is refused and why, and CHANGELOG.md for what changed for a consumer, per version. To pick a deployment (and see which adapters exist), read docs/guides/choosing-a-deployment.md; to add an adapter in a fork, docs/guides/diy-adapter.md.

The rule that makes this repository public

Mechanism only. Nothing here names an account, a zone, a hostname, a cluster, an issuer or a secret path of any installation: every such thing is a value with a neutral example, and the installation supplies it from its own repository. Examples use example.com, *.example and the acme and globex organisations. The rule covers code, docs, the CHANGELOG, tests, commit messages and pull request text, because public history cannot be unpublished. It is enforced mechanically: hack/leak-canary.sh, vendored from the shared copy in ci-workflows, is a just check recipe and a CI job, and every exception it carries is written down in the script with its reason.

This repository follows the shared component contract.

Status

Used in production by its maintainers. CHANGELOG.md says what exists at each version, and releases are on the releases page.

Development

devbox shell        # or direnv: Go, buf, golangci-lint, helm, just, lefthook
just check          # build, test, lint, chart-lint, telemetry, archive-check, docs-check, leak-canary, audit-catalogue, ts
just vuln           # govulncheck; separate from check — a new CVE must not turn it red
just generate       # proto → gen/ after a contract change; the generated code is committed

CONTRIBUTING.md has the conventions and the console's build order.

Releasing

Push a tag vX.Y.Z: the release workflow publishes the images, the chart, sluisctl and its Nix flake, and the TypeScript package at that version, and the Go module and the Action are the same tag. Auto-release is armed and cuts patch tags when changes merge to master; a minor needs its ## vX.Y.0 CHANGELOG heading and is tagged by hand.

Licence

MIT — see LICENSE.

Documentation

Overview

Package sluis carries the files this repository publishes as data.

Index

Constants

This section is empty.

Variables

View Source
var ConfigSchemas embed.FS

ConfigSchemas are the schemas of each binary's configuration file, under schemas/config/. They are generated by `just config-schemas` from internal/config and committed, so that a deployment can validate its file without this repository's code, and so that the binary validates against the very file a chart's tests do.

Functions

This section is empty.

Types

This section is empty.

Directories

Path Synopsis
audit module
deploy/pulumi module
sdk module
Package backend is the contract a directory backend implements: read-only access to one tenant's accounts, groups and domains, plus the credential handling that gets there.
Package backend is the contract a directory backend implements: read-only access to one tenant's accounts, groups and domains, plus the credential handling that gets there.
fake
Package fake is a directory backend held in memory, with a scriptable failure for every operation.
Package fake is a directory backend held in memory, with a scriptable failure for every operation.
google
Package google reads a Google Workspace through the Admin SDK.
Package google reads a Google Workspace through the Admin SDK.
cmd
acceptance command
Command acceptance exercises access-issuer against a real Kubernetes API server.
Command acceptance exercises access-issuer against a real Kubernetes API server.
resource-proxy command
Command resource-proxy fronts a service that knows nothing about sluis with a sluis resource server's front door: it verifies the caller's token, serves the RFC 9728 metadata, writes an audit line per request, and proxies to the service -- and, optionally, gives the service an identity of its own for what it calls in turn.
Command resource-proxy fronts a service that knows nothing about sluis with a sluis resource server's front door: it verifies the caller's token, serves the RFC 9728 metadata, writes an audit line per request, and proxies to the service -- and, optionally, gives the service an identity of its own for what it calls in turn.
sluis command
Command sluis is the whole product in one binary, one image and one chart (docs/decisions/0032).
Command sluis is the whole product in one binary, one image and one chart (docs/decisions/0032).
sluis-lambda command
Command sluis-lambda is sluis as AWS Lambda functions: one arm64 `bootstrap` binary in one zip, deployed as three functions whose role is SLUIS_ROLE (http, github or slack).
Command sluis-lambda is sluis as AWS Lambda functions: one arm64 `bootstrap` binary in one zip, deployed as three functions whose role is SLUIS_ROLE (http, github or slack).
sluisctl command
Command sluisctl is what a person on a laptop runs.
Command sluisctl is what a person on a laptop runs.
deploy
pulumi module
Package frontend embeds the built console, so that the hub is one binary with no static-file deployment beside it and the SPA is same-origin with the API it calls.
Package frontend embeds the built console, so that the hub is one binary with no static-file deployment beside it and the SPA is same-origin with the API it calls.
gen
accessissuer/v1/accessissuerv1connect
Package accessissuer.v1 is what the issuer answers ABOUT itself, as opposed to the OpenID surface it answers protocol on.
Package accessissuer.v1 is what the issuer answers ABOUT itself, as opposed to the OpenID surface it answers protocol on.
directory/v1/directoryv1connect
Package directory.v1 is the directory contract: liveness and flat group membership for the corporate directories an installation owns.
Package directory.v1 is the directory contract: liveness and flat group membership for the corporate directories an installation owns.
directoryroster/v1/directoryrosterv1connect
Package directoryroster.v1 is the operator contract of the hub: the workspaces it holds credentials for, its settings, and access to the hub itself.
Package directoryroster.v1 is the operator contract of the hub: the workspaces it holds credentials for, its settings, and access to the hub itself.
Package identity turns a token somebody else issued into the caller a listener acts on.
Package identity turns a token somebody else issued into the caller a listener acts on.
resource
Package resource is the resource-server half of the Model Context Protocol's authorization spec, for one protected resource.
Package resource is the resource-server half of the Model Context Protocol's authorization spec, for one protected resource.
internal
access
Package access decides who is at the console and what they may do.
Package access decides who is at the console and what they may do.
app
Package app assembles the directory hub from its configuration: the stores, the snapshot cache, the backends, the policy, the connectors, the recovery path and the three listeners.
Package app assembles the directory hub from its configuration: the stores, the snapshot cache, the backends, the policy, the connectors, the recovery path and the three listeners.
audit
Package audit is what sluis tells the audit trail.
Package audit is what sluis tells the audit trail.
audit/audittest
Package audittest is a recorder a test can read back.
Package audittest is a recorder a test can read back.
config
Package config is what each binary of this repository is configured with: one typed configuration per binary, read from one file and validated against a JSON Schema before anything starts.
Package config is what each binary of this repository is configured with: one typed configuration per binary, read from one file and validated against a JSON Schema before anything starts.
config/gen command
Command gen writes the configuration schemas into schemas/config/, and embeds them in the chart's values schema.
Command gen writes the configuration schemas into schemas/config/, and embeds them in the chart's values schema.
config/schema
Package schema builds the JSON Schema of each binary's configuration file.
Package schema builds the JSON Schema of each binary's configuration file.
connector
Package connector turns a directory's own sign-in screen into a workspace the hub can read.
Package connector turns a directory's own sign-in screen into a workspace the hub can read.
consoleauth
Package consoleauth is how a controller proves itself to the console.
Package consoleauth is how a controller proves itself to the console.
demo
Package demo builds the demonstration tenants the prototype runs on: fixture accounts and groups held in memory, no credential and no network, so that every use-case can be walked through before a real directory is connected.
Package demo builds the demonstration tenants the prototype runs on: fixture accounts and groups held in memory, no credential and no network, so that every use-case can be walked through before a real directory is connected.
emailaddr
Package emailaddr splits addresses the way the hub routes them: by the domain after the last '@', lower-cased.
Package emailaddr splits addresses the way the hub routes them: by the domain after the last '@', lower-cased.
exports
Package exports copies secrets the console keeps OUT of the service, into the secret store a consumer reads (docs/decisions/0034).
Package exports copies secrets the console keeps OUT of the service, into the secret store a consumer reads (docs/decisions/0034).
githubapp
Package githubapp is the part of GitHub's App API that connecting an organisation needs — creating an App from a manifest, finding where it is installed, and uninstalling it — and the part linking a person's GitHub account needs: authorizing the link App as themselves, and reading back who they are and which addresses GitHub verified for them.
Package githubapp is the part of GitHub's App API that connecting an organisation needs — creating an App from a manifest, finding where it is installed, and uninstalling it — and the part linking a person's GitHub account needs: authorizing the link App as themselves, and reading back who they are and which addresses GitHub verified for them.
githubapp/catalogue
Package catalogue is GitHub Apps declared as data: what each App is called, which organisation owns it, what it may do, and — for a later exchange that mints installation tokens — which groups may ask for how much of it.
Package catalogue is GitHub Apps declared as data: what each App is called, which organisation owns it, what it may do, and — for a later exchange that mints installation tokens — which groups may ask for how much of it.
githubapp/githubfake
Package githubfake is one GitHub organisation, in memory, answering the calls the controller makes and changing as they change it.
Package githubfake is one GitHub organisation, in memory, answering the calls the controller makes and changing as they change it.
githubapp/mints
Package mints keeps the last installation tokens asked of each GitHub App, so that an App's page can show them.
Package mints keeps the last installation tokens asked of each GitHub App, so that an App's page can show them.
githubroster/app
Package app assembles the GitHub controller from its configuration: the policy's GitHub table, the console it reads with its own ServiceAccount token, the report it writes, and the credentials mounted beside it.
Package app assembles the GitHub controller from its configuration: the policy's GitHub table, the console it reads with its own ServiceAccount token, the report it writes, and the credentials mounted beside it.
githubroster/catalogueapp
Package catalogueapp is what creating a catalogue App leaves behind: the App's record, and its key.
Package catalogueapp is what creating a catalogue App leaves behind: the App's record, and its key.
githubroster/connection
Package connection is what connecting a GitHub organisation leaves behind, shared by the service that writes it and the controller that reads it.
Package connection is what connecting a GitHub organisation leaves behind, shared by the service that writes it and the controller that reads it.
githubroster/controller
Package controller is the GitHub controller's loop: every pass, for every organisation the policy binds, read what GitHub holds and who holds the bound groups, decide, act where the organisation is enabled, and report.
Package controller is the GitHub controller's loop: every pass, for every organisation the policy binds, read what GitHub holds and who holds the bound groups, decide, act where the organisation is enabled, and report.
githubroster/link
Package link is what a person linking their GitHub account leaves behind, shared by the service that writes a link and the controller that keeps checking it.
Package link is what a person linking their GitHub account leaves behind, shared by the service that writes a link and the controller that keeps checking it.
githubroster/reconcile
Package reconcile is what the GitHub controller decides, with no network in it: from the policy's bindings, the holders of the groups they name, and what GitHub holds, what one organisation should look like and what to change to get there.
Package reconcile is what the GitHub controller decides, with no network in it: from the policy's bindings, the holders of the groups they name, and what GitHub holds, what one organisation should look like and what to change to get there.
githubroster/runnerapp
Package runnerapp is what creating a runner App leaves behind: the App a self-hosted runner scale set in one tier registers with in one organisation.
Package runnerapp is what creating a runner App leaves behind: the App a self-hosted runner scale set in one tier registers with in one organisation.
githubroster/status
Package status is the contract between the GitHub controller and the console: what the controller last did to each organisation, and why, written where the console can read it.
Package status is the contract between the GitHub controller and the console: what the controller last did to each organisation, and why, written where the console can read it.
health
Package health serves the two probes, and keeps them different.
Package health serves the two probes, and keeps them different.
hub
Package hub is the directory hub: the workspaces it holds credentials for, the snapshots it keeps of them, the routing from an email address to the workspace that serves it, and the freshness policy that decides whether a read is answered from a snapshot or from the backend.
Package hub is the directory hub: the workspaces it holds credentials for, the snapshots it keeps of them, the routing from an email address to the workspace that serves it, and the freshness policy that decides whether a read is answered from a snapshot or from the backend.
hublocal
Package hublocal asks the directory about a person by CALLING it.
Package hublocal asks the directory about a person by CALLING it.
issuer
Package issuer is the token service: it verifies proofs produced elsewhere, applies the shared policy, and issues tokens.
Package issuer is the token service: it verifies proofs produced elsewhere, applies the shared policy, and issues tokens.
issuerapp
Package issuerapp assembles the token service from its configuration: the policy, the door to the hub, the signing key, the verifiers that turn somebody else's token into a proof, and the OpenID surface over all of it.
Package issuerapp assembles the token service from its configuration: the policy, the door to the hub, the signing key, the verifiers that turn somebody else's token into a proof, and the OpenID surface over all of it.
kmsfake
Package kmsfake is a KMS that wraps data key pairs, for tests of the `kms-wrapped` signing adapter.
Package kmsfake is a KMS that wraps data key pairs, for tests of the `kms-wrapped` signing adapter.
kube
Package kube keeps what a console changes in the hub's own namespace, as plain Kubernetes objects.
Package kube keeps what a console changes in the hub's own namespace, as plain Kubernetes objects.
lambdaapp
Package lambdaapp runs sluis as AWS Lambda functions: one binary, one zip, three functions, the role chosen by SLUIS_ROLE (docs/integrations/aws-lambda.md).
Package lambdaapp runs sluis as AWS Lambda functions: one binary, one zip, three functions, the role chosen by SLUIS_ROLE (docs/integrations/aws-lambda.md).
logsafe
Package logsafe makes a value safe to write into a log line.
Package logsafe makes a value safe to write into a log line.
migrate
Package migrate copies the service's State from any adapter to any other through the ports and the domain stores (ADR 0031), and is the whole of `sluis migrate`.
Package migrate copies the service's State from any adapter to any other through the ports and the domain stores (ADR 0031), and is the whole of `sluis migrate`.
port
Package port is the storage, signalling and identity edge of the service: small interfaces with the semantics in docs/design/ports.md, and nothing else.
Package port is the storage, signalling and identity edge of the service: small interfaces with the semantics in docs/design/ports.md, and nothing else.
port/dynamodb
Package dynamodb is the DynamoDB adapter of the State, Index and Trigger ports (docs/design/ports.md, ADR 0027): one table, shared by every replica and every process, so a lease is exclusive across pods and a notification crosses processes.
Package dynamodb is the DynamoDB adapter of the State, Index and Trigger ports (docs/design/ports.md, ADR 0027): one table, shared by every replica and every process, so a lease is exclusive across pods and a notification crosses processes.
port/invoke
Package invoke is the Trigger of a deployment that runs as AWS Lambda functions: "this target has work" is an asynchronous invoke of the function that runs the target's pass, with the payload {"kind":"run","target":"<id>"} (docs/integrations/aws-lambda.md).
Package invoke is the Trigger of a deployment that runs as AWS Lambda functions: "this target has work" is an asynchronous invoke of the function that runs the target's pass, with the payload {"kind":"run","target":"<id>"} (docs/integrations/aws-lambda.md).
port/legacy
Package legacy is the TEMPORARY adapter that implements the ports by wrapping today's storage exactly: the Kubernetes ConfigMaps and Secrets of internal/kube and the Valkey of internal/valkey.
Package legacy is the TEMPORARY adapter that implements the ports by wrapping today's storage exactly: the Kubernetes ConfigMaps and Secrets of internal/kube and the Valkey of internal/valkey.
port/matrixdoc
Package matrixdoc renders the adapter compatibility and implementation matrix, docs/reference/adapters.md, from the adapter registry and the preset table.
Package matrixdoc renders the adapter compatibility and implementation matrix, docs/reference/adapters.md, from the adapter registry and the preset table.
port/matrixdoc/gen command
Command gen writes docs/reference/adapters.md.
Command gen writes docs/reference/adapters.md.
port/memory
Package memory is the in-memory adapter: every port, in process memory, with the semantics of docs/design/ports.md and nothing more.
Package memory is the in-memory adapter: every port, in process memory, with the semantics of docs/design/ports.md and nothing more.
port/observe
Package observe wraps the storage ports so that each call is timed, counted by how it ended, and traced.
Package observe wraps the storage ports so that each call is timed, counted by how it ended, and traced.
port/openbao
Package openbao is the port.Export adapter over an OpenBao (or Vault) KV version 2 mount: a copy of a secret is one key under the mount, written with the HTTP API and nothing else.
Package openbao is the port.Export adapter over an OpenBao (or Vault) KV version 2 mount: a copy of a secret is one key under the mount, written with the HTTP API and nothing else.
port/porttest
Package porttest is the conformance suite of docs/design/ports.md.
Package porttest is the conformance suite of docs/design/ports.md.
port/s3blob
Package s3blob is the S3 adapter of port.Blob (docs/design/ports.md, "Blob"): whole objects under one bucket and one key prefix, for the status reports and the directory snapshots.
Package s3blob is the S3 adapter of port.Blob (docs/design/ports.md, "Blob"): whole objects under one bucket and one key prefix, for the status reports and the directory snapshots.
port/secretsexport
Package secretsexport is the port.Export over the Secrets port: a copy of a secret OUT of the service is the Secrets path `export/<path>`, which the ssm adapter keeps at `/sluis/export/<path>` (docs/reference/storage-layout.md).
Package secretsexport is the port.Export over the Secrets port: a copy of a secret OUT of the service is the Secrets path `export/<path>`, which the ssm adapter keeps at `/sluis/export/<path>` (docs/reference/storage-layout.md).
port/ssm
Package ssm is the AWS Systems Manager Parameter Store adapter of port.Secrets (docs/design/ports.md, "Secrets"): dynamic secrets and the exports as SecureString parameters.
Package ssm is the AWS Systems Manager Parameter Store adapter of port.Secrets (docs/design/ports.md, "Secrets"): dynamic secrets and the exports as SecureString parameters.
portstore
Package portstore keeps the domain stores (workspaces and their credentials, GitHub organisations and their Apps, a person's GitHub link, the Slack records) on the ports of internal/port: State for the records and Secrets for every credential.
Package portstore keeps the domain stores (workspaces and their credentials, GitHub organisations and their Apps, a person's GitHub link, the Slack records) on the ports of internal/port: State for the records and Secrets for every credential.
portstore/portstoretest
Package portstoretest is the harness every test of a domain store on the ports runs over: State and Secrets in memory, with a way to open another "process" onto the same State and Secrets.
Package portstoretest is the harness every test of a domain store on the ports runs over: State and Secrets in memory, with a way to open another "process" onto the same State and Secrets.
rails
Package rails is what reconcilers share.
Package rails is what reconcilers share.
resourceproxy
Package resourceproxy is the machinery of cmd/resource-proxy: a sidecar that puts a sluis resource server's front door on a stock MCP server (or any HTTP service) that knows nothing about sluis.
Package resourceproxy is the machinery of cmd/resource-proxy: a sidecar that puts a sluis resource server's front door on a stock MCP server (or any HTTP service) that knows nothing about sluis.
rosterapp
Package rosterapp assembles the whole of sluis as ONE process: the directory connectors, the snapshot and its refresher, the policy, the OpenID provider, the login page and the console.
Package rosterapp assembles the whole of sluis as ONE process: the directory connectors, the snapshot and its refresher, the policy, the OpenID provider, the login page and the console.
server
Package server maps the hub onto its two listeners: DirectoryService for consumers on the API port, and the operator services plus the console on the console port.
Package server maps the hub onto its two listeners: DirectoryService for consumers on the API port, and the operator services plus the console on the console port.
settings
Package settings keeps the two things an operator can change from the console: the OAuth client used for admin consent and for sign-in, and the memberships added there.
Package settings keeps the two things an operator can change from the console: the OAuth client used for admin consent and for sign-in, and the memberships added there.
slackapp
Package slackapp is the part of Slack's Web API the Slack controller needs to make a workspace's channels match who is entitled to be in them — and the part the console needs to connect a workspace in the first place.
Package slackapp is the part of Slack's Web API the Slack controller needs to make a workspace's channels match who is entitled to be in them — and the part the console needs to connect a workspace in the first place.
slackapp/catalogue
Package catalogue is Slack Apps declared as data: which workspace each belongs to, what it is called and which bot scopes it asks for.
Package catalogue is Slack Apps declared as data: which workspace each belongs to, what it is called and which bot scopes it asks for.
slackapp/catalogueapp
Package catalogueapp is what creating a catalogue Slack App leaves behind: the App's record, its client credentials and, once installed, its bot token.
Package catalogueapp is what creating a catalogue Slack App leaves behind: the App's record, its client credentials and, once installed, its bot token.
slackapp/slackfake
Package slackfake is Slack, in memory: several workspaces behind one server, answering the calls the Slack controller makes and changing as they change it.
Package slackfake is Slack, in memory: several workspaces behind one server, answering the calls the Slack controller makes and changing as they change it.
slackroster/app
Package app assembles the Slack controller from its configuration: the policy's slack table, the console it reads with its own ServiceAccount token, the report it writes, and the credentials and records mounted beside it.
Package app assembles the Slack controller from its configuration: the policy's slack table, the console it reads with its own ServiceAccount token, the report it writes, and the credentials and records mounted beside it.
slackroster/apply
Package apply is the part of the Slack reconciler that touches Slack: it reads a workspace whole (Observe) and carries out what reconcile.Decision decided (Apply).
Package apply is the part of the Slack reconciler that touches Slack: it reads a workspace whole (Observe) and carries out what reconcile.Decision decided (Apply).
slackroster/connection
Package connection is what connecting a Slack workspace leaves behind, shared by the service that writes it and the controller that reads it.
Package connection is what connecting a Slack workspace leaves behind, shared by the service that writes it and the controller that reads it.
slackroster/controller
Package controller is the Slack controller: for every workspace the policy declares, read what Slack holds and who holds the groups the channels are bound to, decide, act where the workspace is enabled, and report.
Package controller is the Slack controller: for every workspace the policy declares, read what Slack holds and who holds the groups the channels are bound to, decide, act where the workspace is enabled, and report.
slackroster/reconcile
Package reconcile is what the Slack controller decides, with no network in it: from the policy's bindings, the holders of the groups they name, and what one workspace holds, what its channels should contain and what to change to get there.
Package reconcile is what the Slack controller decides, with no network in it: from the policy's bindings, the holders of the groups they name, and what one workspace holds, what its channels should contain and what to change to get there.
slackroster/status
Package status is the contract between the Slack controller and the console: what the controller last did to each workspace, and why, written where the console can read it.
Package status is the contract between the Slack controller and the console: what the controller last did to each workspace, and why, written where the console can read it.
store
Package store builds the storage ports once, from configuration, for the apps to be handed: the one place that knows which adapter backs them.
Package store builds the storage ports once, from configuration, for the apps to be handed: the one place that knows which adapter backs them.
telemetry
Package telemetry is the OpenTelemetry metrics both processes publish.
Package telemetry is the OpenTelemetry metrics both processes publish.
testissuer
Package testissuer is an OpenID provider just real enough to verify a token against: a discovery document, a key set, and a signer.
Package testissuer is an OpenID provider just real enough to verify a token against: a discovery document, a key set, and a signer.
valkey
Package valkey is the Valkey driver of the legacy adapter (internal/port/legacy): the connection, its failover handling, and the one State that the issuer's logins in progress, the hub's snapshots and the refresh leases are all kept in.
Package valkey is the Valkey driver of the legacy adapter (internal/port/legacy): the connection, its failover handling, and the one State that the issuer's logins in progress, the hub's snapshots and the refresh leases are all kept in.
verify
Package verify turns a token somebody else issued into a proof this installation will act on.
Package verify turns a token somebody else issued into a proof this installation will act on.
version
Package version carries the build's identity, so that an operator looking at a console can say which build they are looking at without asking a cluster.
Package version carries the build's identity, so that an operator looking at a console can say which build they are looking at without asking a cluster.
Package policy is the schema both services load: seven tables that answer four questions and no others — who is in which internal group, what a group adds to a token, how long a token lives, and which client may be issued one — plus one OPTIONAL eighth, Vocabulary, that answers none of the four itself and instead constrains what a name used to answer them is allowed to mean.
Package policy is the schema both services load: seven tables that answer four questions and no others — who is in which internal group, what a group adds to a token, how long a token lives, and which client may be issued one — plus one OPTIONAL eighth, Vocabulary, that answers none of the four itself and instead constrains what a name used to answer them is allowed to mean.
storage module
Package tokens trades one token for another, and writes the two shapes a credential helper has to speak.
Package tokens trades one token for another, and writes the two shapes a credential helper has to speak.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL