<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Wipe Platform Admin Documentation on Wipe Platform Admin Docs</title><link>https://docs.wipe.stack-plane.com/</link><description>Recent content in Wipe Platform Admin Documentation on Wipe Platform Admin Docs</description><generator>Hugo</generator><language>en-us</language><atom:link href="https://docs.wipe.stack-plane.com/index.xml" rel="self" type="application/rss+xml"/><item><title>Local Stack</title><link>https://docs.wipe.stack-plane.com/docs/cluster-bring-up/01-local-stack/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.wipe.stack-plane.com/docs/cluster-bring-up/01-local-stack/</guid><description>&lt;h1 id="local-stack"&gt;Local Stack &lt;a href="#local-stack" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;Run the full local stack from the repository root:&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="ef6156d" class="language-bash "&gt;
 &lt;code&gt;docker compose up --build&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;The root compose file builds the backend and both SvelteKit portals, then starts
PostgreSQL with PGMQ, Keycloak, MinIO, Mailpit, OpenTelemetry Collector,
Prometheus, Loki, Tempo, Grafana, API, workers, dashboard, and frontend.&lt;/p&gt;
&lt;h2 id="service-urls"&gt;Service URLs &lt;a href="#service-urls" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Service&lt;/th&gt;
					&lt;th&gt;URL&lt;/th&gt;
					&lt;th&gt;Notes&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;API&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;http://localhost:8080&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Backend API, &lt;code&gt;/healthz&lt;/code&gt;, &lt;code&gt;/readyz&lt;/code&gt;, Swagger.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Swagger UI&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;http://localhost:8080/swagger/index.html&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Generated from backend annotations.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Frontend BFF&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;http://localhost:5174&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;New SvelteKit portal; OIDC tokens stay server-side.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Admin docs&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;http://localhost:5175&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Static Hugo/LotusDocs administrator handbook.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Dashboard&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;http://localhost:5173&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Existing dashboard/test console.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Keycloak&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;http://localhost:8081&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;admin&lt;/code&gt; / &lt;code&gt;admin&lt;/code&gt;.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;PostgreSQL&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;localhost:5432&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;wipe&lt;/code&gt; / &lt;code&gt;wipe&lt;/code&gt;, database &lt;code&gt;wipe&lt;/code&gt;.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;MinIO console&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;http://localhost:9001&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;minioadmin&lt;/code&gt; / &lt;code&gt;minioadmin&lt;/code&gt;.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Mailpit&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;http://localhost:8025&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Captured SMTP messages.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Grafana&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;http://localhost:3000&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;admin&lt;/code&gt; / &lt;code&gt;admin&lt;/code&gt;.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Prometheus&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;http://localhost:9090&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Scrapes OTel Collector exporter.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Loki&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;http://localhost:3100&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Logs.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Tempo&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;http://localhost:3200&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Traces.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;OTLP gRPC/HTTP&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;localhost:4317&lt;/code&gt;, &lt;code&gt;localhost:4318&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Telemetry ingest.&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="seeded-accounts"&gt;Seeded Accounts &lt;a href="#seeded-accounts" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Realm&lt;/th&gt;
					&lt;th&gt;Username&lt;/th&gt;
					&lt;th&gt;Password&lt;/th&gt;
					&lt;th&gt;Role&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;master&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;platform-admin&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;admin&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;PLATFORM_ADMIN&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;master&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;billing-operator&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;admin&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;BILLING_OPERATOR&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;exawipe&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;client-admin&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;admin&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CLIENT_ADMIN&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;exawipe&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;client-tech&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;admin&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CLIENT_TECH&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;exawipe&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;auditor&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;admin&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;AUDITOR&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The seeded direct-access clients are &lt;code&gt;wipe-admin-cli&lt;/code&gt; for the &lt;code&gt;master&lt;/code&gt; realm and
&lt;code&gt;wipe-dev-cli&lt;/code&gt; for the &lt;code&gt;exawipe&lt;/code&gt; realm. The newer frontend BFF requires
standard-flow web clients with PKCE: &lt;code&gt;wipe-portal-admin&lt;/code&gt; in &lt;code&gt;master&lt;/code&gt; and
&lt;code&gt;wipe-portal&lt;/code&gt; in &lt;code&gt;exawipe&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Tenants And Organizations</title><link>https://docs.wipe.stack-plane.com/docs/administration/01-tenants-organizations/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.wipe.stack-plane.com/docs/administration/01-tenants-organizations/</guid><description>&lt;h1 id="tenants-and-organizations"&gt;Tenants And Organizations &lt;a href="#tenants-and-organizations" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;Use these routes with a &lt;code&gt;PLATFORM_ADMIN&lt;/code&gt; token.&lt;/p&gt;
&lt;h2 id="tenant-lifecycle"&gt;Tenant Lifecycle &lt;a href="#tenant-lifecycle" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Action&lt;/th&gt;
					&lt;th&gt;Route&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;List tenants&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;GET /admin/api/v1/tenants&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Create tenant&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;POST /admin/api/v1/tenants&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Read tenant&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;GET /admin/api/v1/tenants/{tenant_id}&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Update tenant&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;PATCH /admin/api/v1/tenants/{tenant_id}&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Delete tenant&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;DELETE /admin/api/v1/tenants/{tenant_id}&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Create tenants with a stable &lt;code&gt;slug&lt;/code&gt;, display &lt;code&gt;name&lt;/code&gt;, optional
&lt;code&gt;instance_fingerprint&lt;/code&gt;, and optional &lt;code&gt;branding&lt;/code&gt;.&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="68dbe78" class="language-json "&gt;
 &lt;code&gt;{
 &amp;#34;name&amp;#34;: &amp;#34;Example Tenant&amp;#34;,
 &amp;#34;slug&amp;#34;: &amp;#34;example-tenant&amp;#34;,
 &amp;#34;instance_fingerprint&amp;#34;: &amp;#34;sha256:example&amp;#34;
}&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;Tenant deletion is a backend soft delete. Treat it as an operationally sensitive
action and keep the audit record attached to the change.&lt;/p&gt;</description></item><item><title>Host Deployment</title><link>https://docs.wipe.stack-plane.com/docs/cluster-bring-up/02-host-deployment/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.wipe.stack-plane.com/docs/cluster-bring-up/02-host-deployment/</guid><description>&lt;h1 id="host-deployment"&gt;Host Deployment &lt;a href="#host-deployment" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;The repository includes host deployment notes for &lt;code&gt;wipe.stack-plane.com&lt;/code&gt;. The
same pattern applies to a single VM or bare-metal host that runs Docker Compose
behind host Nginx.&lt;/p&gt;
&lt;h2 id="prepare-environment"&gt;Prepare Environment &lt;a href="#prepare-environment" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Copy the host environment template and replace every placeholder:&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="7e569da" class="language-bash "&gt;
 &lt;code&gt;cp deploy/host/wipe.stack-plane.com.env.example .env&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;Review at minimum:&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Group&lt;/th&gt;
					&lt;th&gt;Required values&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Public URLs&lt;/td&gt;
					&lt;td&gt;API, frontend, Keycloak, verification, invitation, callback URLs.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Secrets&lt;/td&gt;
					&lt;td&gt;PostgreSQL, Keycloak, MinIO/S3, SMTP, frontend session secret, OIDC client secrets.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Admin access&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;ADMIN_API_ALLOWED_CIDRS&lt;/code&gt;, &lt;code&gt;ADMIN_API_ALLOW_INTERNAL_NETWORKS&lt;/code&gt;, MFA window.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Storage&lt;/td&gt;
					&lt;td&gt;S3 endpoint, bucket names, credentials, optional filesystem fallback.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Signer&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;SIGNER_MODE&lt;/code&gt;, endpoint, bearer or mTLS material, key IDs, TSA settings.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Observability&lt;/td&gt;
					&lt;td&gt;OTel endpoint, environment name, logs/metrics/traces routing.&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Do not reuse local default passwords or seeded API keys outside local
development.&lt;/p&gt;</description></item><item><title>Users And Invitations</title><link>https://docs.wipe.stack-plane.com/docs/administration/02-users-invitations/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.wipe.stack-plane.com/docs/administration/02-users-invitations/</guid><description>&lt;h1 id="users-and-invitations"&gt;Users And Invitations &lt;a href="#users-and-invitations" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;Platform admins can create and maintain tenant users through the tenant API when
the target tenant and organization are supplied. Client admins can perform the
same workflow inside their own organization scope.&lt;/p&gt;
&lt;h2 id="routes"&gt;Routes &lt;a href="#routes" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Action&lt;/th&gt;
					&lt;th&gt;Route&lt;/th&gt;
					&lt;th&gt;Roles&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;List users&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;GET /api/v1/users&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CLIENT_ADMIN&lt;/code&gt;, &lt;code&gt;PLATFORM_ADMIN&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Create user and invitation&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;POST /api/v1/users&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CLIENT_ADMIN&lt;/code&gt;, &lt;code&gt;PLATFORM_ADMIN&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Update user profile&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;PUT /api/v1/users/{id}&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CLIENT_ADMIN&lt;/code&gt;, &lt;code&gt;PLATFORM_ADMIN&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Delete user by body alias&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;DELETE /api/v1/users&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CLIENT_ADMIN&lt;/code&gt;, &lt;code&gt;PLATFORM_ADMIN&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Delete user by path&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;DELETE /api/v1/users/{id}&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CLIENT_ADMIN&lt;/code&gt;, &lt;code&gt;PLATFORM_ADMIN&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Accept invitation&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;POST /api/v1/invitations/accept&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Public token route&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="create-user"&gt;Create User &lt;a href="#create-user" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Example request:&lt;/p&gt;</description></item><item><title>IdP Federation</title><link>https://docs.wipe.stack-plane.com/docs/administration/03-idp-federation/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.wipe.stack-plane.com/docs/administration/03-idp-federation/</guid><description>&lt;h1 id="idp-federation"&gt;IdP Federation &lt;a href="#idp-federation" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;Identity provider federation is configured by a &lt;code&gt;PLATFORM_ADMIN&lt;/code&gt; and must be
approved by a second &lt;code&gt;PLATFORM_ADMIN&lt;/code&gt; before it becomes public discovery
metadata.&lt;/p&gt;
&lt;h2 id="routes"&gt;Routes &lt;a href="#routes" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Action&lt;/th&gt;
					&lt;th&gt;Route&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Read organization IdP metadata&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;GET /admin/api/v1/organizations/{id}/idp&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Configure IdP metadata&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;POST /admin/api/v1/organizations/{id}/idp&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Approve IdP metadata&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;POST /admin/api/v1/organizations/{id}/idp/approve&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Home realm discovery&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;POST /api/v1/auth/discover&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="configure-idp"&gt;Configure IdP &lt;a href="#configure-idp" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Example request:&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="b3893a8" class="language-json "&gt;
 &lt;code&gt;{
 &amp;#34;tenant_id&amp;#34;: &amp;#34;11111111-1111-4111-8111-111111111111&amp;#34;,
 &amp;#34;provider&amp;#34;: &amp;#34;saml&amp;#34;,
 &amp;#34;metadata_url&amp;#34;: &amp;#34;https://idp.example/metadata&amp;#34;,
 &amp;#34;idp_url&amp;#34;: &amp;#34;https://idp.example/login&amp;#34;,
 &amp;#34;entity_id&amp;#34;: &amp;#34;https://idp.example/entity&amp;#34;,
 &amp;#34;display_name&amp;#34;: &amp;#34;Example IdP&amp;#34;
}&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;The backend stores the metadata with &lt;code&gt;status=PENDING_APPROVAL&lt;/code&gt;, &lt;code&gt;requested_by&lt;/code&gt;,
and &lt;code&gt;requested_at&lt;/code&gt;. Pending metadata is not exposed by auth discovery.&lt;/p&gt;</description></item><item><title>Runtime Services</title><link>https://docs.wipe.stack-plane.com/docs/cluster-bring-up/03-runtime-services/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.wipe.stack-plane.com/docs/cluster-bring-up/03-runtime-services/</guid><description>&lt;h1 id="runtime-services"&gt;Runtime Services &lt;a href="#runtime-services" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;The platform is a modular Go backend plus SvelteKit frontends. Runtime state is
externalized to PostgreSQL and object storage.&lt;/p&gt;
&lt;h2 id="backend-binaries"&gt;Backend Binaries &lt;a href="#backend-binaries" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Binary&lt;/th&gt;
					&lt;th&gt;Compose service&lt;/th&gt;
					&lt;th&gt;Command&lt;/th&gt;
					&lt;th&gt;Purpose&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;api&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;api&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;/app/api&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Main HTTP API, admin API, public verification, embedded ingest in dev.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;ingest&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Optional standalone&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;/app/ingest&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Agent-only &lt;code&gt;/ingest/v1&lt;/code&gt; gateway with dedicated least-privilege DB role.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;worker-proof&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;proof-worker&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;/app/worker-proof&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Consumes &lt;code&gt;proofs.validated&lt;/code&gt;; validates &lt;code&gt;.der&lt;/code&gt;, decrypts, signs, creates certificates.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;worker&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;anchor-worker&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;/app/worker anchor&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Consumes &lt;code&gt;certificates.to_anchor&lt;/code&gt;; submits/updates anchors and regenerates PDFs after anchoring.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;worker&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;notification-worker&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;/app/worker notifications&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Consumes &lt;code&gt;notifications.to_send&lt;/code&gt;; sends SMTP/webhook deliveries and records retries/DLQ.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;worker&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;report-worker&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;/app/worker reports&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Schedules and creates monthly billing reports and billing export artifacts.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;worker&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;retry-worker&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;/app/worker retry&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Enqueues due proof retries and re-tests recoverable proof states.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;worker&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;maintenance-worker&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;/app/worker maintenance&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Applies retention/anonymization and verifies audit/receipt chains.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;migrator&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;db-migrate&lt;/code&gt; profile&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;/app/migrator&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Runs embedded SQL migrations.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;verifier&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;CLI image target&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;/app/verifier&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Offline verification CLI foundation.&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code&gt;worker&lt;/code&gt; binary chooses its kind from the first argument or &lt;code&gt;WORKER_KIND&lt;/code&gt;.
&lt;code&gt;WORKER_ONCE=true&lt;/code&gt; runs one claim pass and exits, which is useful for controlled
maintenance or release validation.&lt;/p&gt;</description></item><item><title>Branding And Email Templates</title><link>https://docs.wipe.stack-plane.com/docs/administration/04-branding-email/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.wipe.stack-plane.com/docs/administration/04-branding-email/</guid><description>&lt;h1 id="branding-and-email-templates"&gt;Branding And Email Templates &lt;a href="#branding-and-email-templates" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;Branding is organization-scoped JSON. It controls organization display metadata
and the invitation email template used for new users.&lt;/p&gt;
&lt;h2 id="routes"&gt;Routes &lt;a href="#routes" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Action&lt;/th&gt;
					&lt;th&gt;Route&lt;/th&gt;
					&lt;th&gt;Roles&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Read branding&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;GET /api/v1/organizations/{id}/branding&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CLIENT_ADMIN&lt;/code&gt;, &lt;code&gt;PLATFORM_ADMIN&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Update branding&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;PUT /api/v1/organizations/{id}/branding&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CLIENT_ADMIN&lt;/code&gt;, &lt;code&gt;PLATFORM_ADMIN&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Platform admins must pass the target organization ID and tenant scope because a
master realm token is not naturally tenant-scoped.&lt;/p&gt;
&lt;h2 id="branding-payload"&gt;Branding Payload &lt;a href="#branding-payload" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Example:&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="5f727b3" class="language-json "&gt;
 &lt;code&gt;{
 &amp;#34;branding&amp;#34;: {
 &amp;#34;app_name&amp;#34;: &amp;#34;Example Wipe&amp;#34;,
 &amp;#34;logo_url&amp;#34;: &amp;#34;https://static.example.com/logo.png&amp;#34;,
 &amp;#34;email_templates&amp;#34;: {
 &amp;#34;user_invited_subject&amp;#34;: &amp;#34;Welcome to {{app_name}}&amp;#34;,
 &amp;#34;user_invited_text&amp;#34;: &amp;#34;You have been invited to {{organization_name}} as {{role}}. Accept: {{accept_url}}&amp;#34;,
 &amp;#34;user_invited_html&amp;#34;: &amp;#34;&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&amp;lt;img src=\&amp;#34;{{logo_url}}\&amp;#34; alt=\&amp;#34;{{app_name}} logo\&amp;#34;&amp;gt;&amp;lt;p&amp;gt;You have been invited to {{organization_name}} as &amp;lt;strong&amp;gt;{{role}}&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;&amp;lt;a href=\&amp;#34;{{accept_url}}\&amp;#34;&amp;gt;Accept invitation&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&amp;#34;
 }
 }
}&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;The admin platform can edit &lt;code&gt;logo_url&lt;/code&gt;, &lt;code&gt;app_name&lt;/code&gt;, and the
&lt;code&gt;email_templates.*&lt;/code&gt; fields. The backend renders the email body from these
templates rather than sending raw JSON.&lt;/p&gt;</description></item><item><title>Configuration Reference</title><link>https://docs.wipe.stack-plane.com/docs/cluster-bring-up/04-configuration-reference/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.wipe.stack-plane.com/docs/cluster-bring-up/04-configuration-reference/</guid><description>&lt;h1 id="configuration-reference"&gt;Configuration Reference &lt;a href="#configuration-reference" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;The backend is configured from environment variables. The canonical local list
is &lt;code&gt;backend/.env.example&lt;/code&gt;; the root compose file supplies defaults for the
reference stack.&lt;/p&gt;
&lt;h2 id="core-http-and-public-urls"&gt;Core HTTP And Public URLs &lt;a href="#core-http-and-public-urls" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Variable&lt;/th&gt;
					&lt;th&gt;Use&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;DEPLOYMENT_MODE&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;cloud&lt;/code&gt;, &lt;code&gt;onprem&lt;/code&gt;, or &lt;code&gt;airgapped&lt;/code&gt;; do not rely on it alone for network policy.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;HTTP_ADDRESS&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;API bind address, usually &lt;code&gt;:8080&lt;/code&gt;.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;HTTP_SHUTDOWN_TIMEOUT&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Graceful shutdown window.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;HTTP_CORS_ALLOW_ORIGINS&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Browser origins allowed to call the API directly.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;HTTP_HSTS_ENABLED&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Enables HSTS when TLS terminates at the API or trusted proxy chain.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;PUBLIC_VERIFY_BASE_URL&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Base URL used in certificate QR and public verification links.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;PUBLIC_INVITATION_BASE_URL&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Base URL used in invitation acceptance links.&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="security-controls"&gt;Security Controls &lt;a href="#security-controls" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Variable&lt;/th&gt;
					&lt;th&gt;Use&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;ADMIN_API_ALLOWED_CIDRS&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Explicit IP/CIDR allowlist for &lt;code&gt;/admin/api/v1&lt;/code&gt;.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;ADMIN_API_ALLOW_INTERNAL_NETWORKS&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Allows loopback/private/link-local admin clients for internal deployments.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;SENSITIVE_ACTION_MFA_MAX_AGE&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Recent-MFA window for sensitive writes; &lt;code&gt;0&lt;/code&gt; disables local-only checks.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;SECURITY_OUTBOUND_ALLOWED_HOSTS&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Host allowlist for IdP metadata, branding URLs, and webhooks.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;SECURITY_OUTBOUND_ALLOWED_CIDRS&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Explicit IP ranges allowed by outbound URL policy.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;SECURITY_OUTBOUND_ALLOW_PRIVATE_NETWORKS&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Only enable for controlled internal deployments.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;VERIFY_RATE_LIMIT_PER_MINUTE&lt;/code&gt; / &lt;code&gt;VERIFY_RATE_LIMIT_PER_HOUR&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Public verification rate limits.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;VERIFY_CAPTCHA_SECRET&lt;/code&gt; / &lt;code&gt;VERIFY_CAPTCHA_VERIFY_URL&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Optional Turnstile/hCaptcha-style siteverify integration.&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="identity-and-keycloak"&gt;Identity And Keycloak &lt;a href="#identity-and-keycloak" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Variable&lt;/th&gt;
					&lt;th&gt;Use&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;KEYCLOAK_MASTER_ISSUER&lt;/code&gt; / &lt;code&gt;KEYCLOAK_EXAWIPE_ISSUER&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Public issuer URLs that must match JWT &lt;code&gt;iss&lt;/code&gt;.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;KEYCLOAK_MASTER_AUDIENCE&lt;/code&gt; / &lt;code&gt;KEYCLOAK_EXAWIPE_AUDIENCE&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Expected JWT audiences.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;KEYCLOAK_MASTER_JWKS_URL&lt;/code&gt; / &lt;code&gt;KEYCLOAK_EXAWIPE_JWKS_URL&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;JWKS endpoints used by the API.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;KEYCLOAK_JWKS_CACHE_TTL&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;JWKS cache duration.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;KEYCLOAK_ADMIN_*&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Optional Admin API service-account configuration for provisioning users and IdPs.&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For the new frontend BFF, configure &lt;code&gt;APP_BASE_URL&lt;/code&gt;, &lt;code&gt;API_INTERNAL_URL&lt;/code&gt;,
&lt;code&gt;KEYCLOAK_ISSUER_MASTER&lt;/code&gt;, &lt;code&gt;KEYCLOAK_ISSUER_EXAWIPE&lt;/code&gt;, &lt;code&gt;KEYCLOAK_INTERNAL_URL&lt;/code&gt;,
web client IDs/secrets, and a 32-byte or longer &lt;code&gt;SESSION_SECRET&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>API Keys And Agents</title><link>https://docs.wipe.stack-plane.com/docs/administration/05-api-keys-agents/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.wipe.stack-plane.com/docs/administration/05-api-keys-agents/</guid><description>&lt;h1 id="api-keys-and-agents"&gt;API Keys And Agents &lt;a href="#api-keys-and-agents" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;API keys are organization-scoped automation credentials. They are managed by
&lt;code&gt;CLIENT_ADMIN&lt;/code&gt; today, not by &lt;code&gt;PLATFORM_ADMIN&lt;/code&gt; admin routes.&lt;/p&gt;
&lt;h2 id="api-key-routes"&gt;API Key Routes &lt;a href="#api-key-routes" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Action&lt;/th&gt;
					&lt;th&gt;Route&lt;/th&gt;
					&lt;th&gt;Role&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;List keys&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;GET /api/v1/api-keys&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CLIENT_ADMIN&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Create key&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;POST /api/v1/api-keys&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CLIENT_ADMIN&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Rotate key&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;POST /api/v1/api-keys/{id}/rotate&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CLIENT_ADMIN&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Revoke key&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;POST /api/v1/api-keys/{id}/revoke&lt;/code&gt; or &lt;code&gt;DELETE /api/v1/api-keys/{id}&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CLIENT_ADMIN&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Create request:&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="a9d3786" class="language-json "&gt;
 &lt;code&gt;{
 &amp;#34;name&amp;#34;: &amp;#34;CI proof uploader&amp;#34;,
 &amp;#34;organization_id&amp;#34;: &amp;#34;22222222-2222-4222-8222-222222222222&amp;#34;,
 &amp;#34;scopes&amp;#34;: [&amp;#34;proofs:write&amp;#34;, &amp;#34;proofs:read&amp;#34;]
}&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;The generated secret is returned once. Store it immediately. Later list calls
show metadata and prefix only.&lt;/p&gt;</description></item><item><title>Migrations And Release</title><link>https://docs.wipe.stack-plane.com/docs/cluster-bring-up/05-migrations-release/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.wipe.stack-plane.com/docs/cluster-bring-up/05-migrations-release/</guid><description>&lt;h1 id="migrations-and-release"&gt;Migrations And Release &lt;a href="#migrations-and-release" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;Use migrations and generated-contract checks as release gates. Do not depend on
runtime AutoMigrate outside local development.&lt;/p&gt;
&lt;h2 id="build-images"&gt;Build Images &lt;a href="#build-images" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;The backend Dockerfile builds these runtime targets from one Go build stage:&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Target&lt;/th&gt;
					&lt;th&gt;Contains&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;api-runtime&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;/app/api&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;proof-worker-runtime&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;/app/worker-proof&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;worker-runtime&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;/app/worker&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;verifier-cli-runtime&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;/app/verifier&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;migrator-runtime&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;/app/migrator&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;runtime&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;API plus worker binaries for the compose reference image.&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Reference build:&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="d26d3fa" class="language-bash "&gt;
 &lt;code&gt;docker compose build api proof-worker anchor-worker notification-worker report-worker retry-worker maintenance-worker&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;h2 id="run-migrations"&gt;Run Migrations &lt;a href="#run-migrations" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;The root compose file exposes a migrator profile:&lt;/p&gt;</description></item><item><title>Licenses And Billing</title><link>https://docs.wipe.stack-plane.com/docs/administration/06-licenses-billing/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.wipe.stack-plane.com/docs/administration/06-licenses-billing/</guid><description>&lt;h1 id="licenses-and-billing"&gt;Licenses And Billing &lt;a href="#licenses-and-billing" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;License grants are platform-admin managed. Tenant billing exports are available
to tenant admins, and restricted tenant-selected billing views are available to
platform admins and billing operators.&lt;/p&gt;
&lt;h2 id="license-grants"&gt;License Grants &lt;a href="#license-grants" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Action&lt;/th&gt;
					&lt;th&gt;Route&lt;/th&gt;
					&lt;th&gt;Roles&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;List license grants&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;GET /admin/api/v1/license-grants&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;PLATFORM_ADMIN&lt;/code&gt;, &lt;code&gt;BILLING_OPERATOR&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Import license grant&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;POST /admin/api/v1/license-grants&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;PLATFORM_ADMIN&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Import license grant alias&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;POST /admin/api/v1/license-grants/import&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;PLATFORM_ADMIN&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Example import:&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="7af702e" class="language-json "&gt;
 &lt;code&gt;{
 &amp;#34;tenant_id&amp;#34;: &amp;#34;11111111-1111-4111-8111-111111111111&amp;#34;,
 &amp;#34;grant_id&amp;#34;: &amp;#34;55555555-5555-4555-8555-555555555555&amp;#34;,
 &amp;#34;grant_type&amp;#34;: &amp;#34;QUANTITY&amp;#34;,
 &amp;#34;instance_fingerprint&amp;#34;: &amp;#34;sha256:example&amp;#34;,
 &amp;#34;license_type&amp;#34;: &amp;#34;desktop&amp;#34;,
 &amp;#34;quantity&amp;#34;: 100,
 &amp;#34;valid_from&amp;#34;: &amp;#34;2026-01-01&amp;#34;,
 &amp;#34;valid_until&amp;#34;: &amp;#34;2026-12-31&amp;#34;,
 &amp;#34;commercial_chain&amp;#34;: [&amp;#34;Exaion&amp;#34;, &amp;#34;Example Operator&amp;#34;],
 &amp;#34;signature&amp;#34;: &amp;#34;dev-signature&amp;#34;
}&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;Imports validate the signed instance fingerprint against the tenant, reject
duplicate grants globally, validate addendum and revocation chains, and require
the commercial chain to start with Exaion and end with the current operator.
The final production Exaion keyring/rotation policy remains part of the signer
readiness backlog.&lt;/p&gt;</description></item><item><title>Proofs And Certificates</title><link>https://docs.wipe.stack-plane.com/docs/administration/07-proofs-certificates/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.wipe.stack-plane.com/docs/administration/07-proofs-certificates/</guid><description>&lt;h1 id="proofs-and-certificates"&gt;Proofs And Certificates &lt;a href="#proofs-and-certificates" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;Proofs are &lt;code&gt;.der&lt;/code&gt; files produced by the wipe agent. The backend stores the raw
proof object before processing and uses asynchronous workers to validate,
decrypt, sign, certify, and optionally anchor the result.&lt;/p&gt;
&lt;h2 id="submission-routes"&gt;Submission Routes &lt;a href="#submission-routes" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Route&lt;/th&gt;
					&lt;th&gt;Auth&lt;/th&gt;
					&lt;th&gt;Use&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;POST /api/v1/proofs&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CLIENT_ADMIN&lt;/code&gt;, &lt;code&gt;CLIENT_TECH&lt;/code&gt;, or generic &lt;code&gt;proofs:write&lt;/code&gt; API key&lt;/td&gt;
					&lt;td&gt;Submit one multipart &lt;code&gt;.der&lt;/code&gt; proof.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;POST /api/v1/proofs/bulk&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CLIENT_ADMIN&lt;/code&gt;, &lt;code&gt;CLIENT_TECH&lt;/code&gt;, or generic &lt;code&gt;proofs:write&lt;/code&gt; API key&lt;/td&gt;
					&lt;td&gt;Submit up to 100 files or a ZIP archive, max 500 MB.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;POST /ingest/v1/proofs&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Enrolled-agent API key with &lt;code&gt;proofs:write&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Submit one raw &lt;code&gt;.der&lt;/code&gt; body from an enrolled agent.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;GET /ingest/v1/proofs/{id}&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Enrolled-agent API key with &lt;code&gt;proofs:read&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Poll the status of an agent-owned proof.&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Protected writes require &lt;code&gt;Idempotency-Key&lt;/code&gt;. The unit proof size limit is 5 MB.
The local rate limits are per authenticated principal or agent key: 100 unit
submissions per hour and 500 batch submissions per hour.&lt;/p&gt;</description></item><item><title>Webhooks And Notifications</title><link>https://docs.wipe.stack-plane.com/docs/administration/08-webhooks-notifications/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.wipe.stack-plane.com/docs/administration/08-webhooks-notifications/</guid><description>&lt;h1 id="webhooks-and-notifications"&gt;Webhooks And Notifications &lt;a href="#webhooks-and-notifications" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;The backend has a notification worker that sends SMTP messages and signed
webhook deliveries from the &lt;code&gt;notifications.to_send&lt;/code&gt; queue. Invitations and
billing export delivery metadata are currently the most visible email flows;
certificate webhooks are emitted for &lt;code&gt;certificate.issued&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="webhook-routes"&gt;Webhook Routes &lt;a href="#webhook-routes" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Action&lt;/th&gt;
					&lt;th&gt;Route&lt;/th&gt;
					&lt;th&gt;Role&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;List subscriptions&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;GET /api/v1/webhooks&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CLIENT_ADMIN&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Create subscription&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;POST /api/v1/webhooks&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CLIENT_ADMIN&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Delete subscription&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;DELETE /api/v1/webhooks/{id}&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CLIENT_ADMIN&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Example:&lt;/p&gt;



 
 
 

 
 
 
 

 

 &lt;div class="prism-codeblock "&gt;
 &lt;pre id="a8ad382" class="language-json "&gt;
 &lt;code&gt;{
 &amp;#34;url&amp;#34;: &amp;#34;https://hooks.example.com/wipe&amp;#34;,
 &amp;#34;events&amp;#34;: [&amp;#34;certificate.issued&amp;#34;]
}&lt;/code&gt;
 &lt;/pre&gt;
 &lt;/div&gt;
&lt;p&gt;The subscription secret is returned once on creation. Store it in the receiving
system immediately.&lt;/p&gt;</description></item><item><title>Backend Gap Register</title><link>https://docs.wipe.stack-plane.com/docs/operations/01-backend-gap-register/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.wipe.stack-plane.com/docs/operations/01-backend-gap-register/</guid><description>&lt;h1 id="backend-gap-register"&gt;Backend Gap Register &lt;a href="#backend-gap-register" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;This page summarizes the backend completion state that platform administrators
should track. Sources are &lt;code&gt;adr/0001-remaining-backend-gaps.md&lt;/code&gt;,
&lt;code&gt;matrix.md&lt;/code&gt;, and the current route contract under &lt;code&gt;backend/docs/&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="contract-status"&gt;Contract Status &lt;a href="#contract-status" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Area&lt;/th&gt;
					&lt;th&gt;Status&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Cahier route backlog&lt;/td&gt;
					&lt;td&gt;All expected backend routes are represented in Swagger.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Swagger wildcard&lt;/td&gt;
					&lt;td&gt;Not tracked as a product route; concrete Swagger routes are served.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Frontend&lt;/td&gt;
					&lt;td&gt;Owned separately, with both &lt;code&gt;frontend&lt;/code&gt; BFF and &lt;code&gt;dashboard&lt;/code&gt; in the repo.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Hedera&lt;/td&gt;
					&lt;td&gt;Real adapter, smart contracts, and deployment/test scripts still deferred.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;WORM/Object Lock&lt;/td&gt;
					&lt;td&gt;Deferred by product direction.&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="closed-backend-slices"&gt;Closed Backend Slices &lt;a href="#closed-backend-slices" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Slice&lt;/th&gt;
					&lt;th&gt;Current behavior&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Billing operator admin routes&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;BILLING_OPERATOR&lt;/code&gt; can use tenant-selected admin billing dashboard, usage, receipts, report list/download, and export routes with explicit &lt;code&gt;tenant_id&lt;/code&gt;. Responses exclude certificate PDFs, canonical proof JSON, and proof payload content.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;License grant import and quota rules&lt;/td&gt;
					&lt;td&gt;Imports validate &lt;code&gt;instance_fingerprint&lt;/code&gt;, duplicate grant IDs, commercial chain, dates, addendum/revocation references, org-tree allocation limits, and quotas where configured.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Notification delivery&lt;/td&gt;
					&lt;td&gt;SMTP/webhook delivery records status, retries with backoff, updates DLQ metadata, renders branded email templates, and updates billing export delivery metadata.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Production observability&lt;/td&gt;
					&lt;td&gt;API/worker telemetry heartbeats, queue depth/in-flight/DLQ metrics, proof pending/failed gauges, DB connection gauges, signer operation metrics, alert rules, dashboard panels, and runbooks are implemented for the Grafana/Loki/Tempo/Prometheus/OpenTelemetry stack.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;API contract polish&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;backend/docs/api-contract-status.md&lt;/code&gt; reports no missing cahier backlog endpoints.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Agent ingestion hardening&lt;/td&gt;
					&lt;td&gt;ISO one-time enrollment tokens are validated by prefix/hash, expiry, consumed state, and revocation state. Enrolled-agent API keys are write-only, linked to enrollment state, update &lt;code&gt;last_seen&lt;/code&gt;, and persist PKI/mTLS-ready identity metadata.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;CI/CD and delivery&lt;/td&gt;
					&lt;td&gt;The Gitea workflow includes migration discipline checks, parallel-safe compose E2E, generated Swagger/HeyAPI freshness, Go tests, security scans, SBOM/provenance, image build/scan/publish, and a dedicated migrator image.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Billing/reporting pass&lt;/td&gt;
					&lt;td&gt;Volume, success-rate, CO2 reporting, restricted SQL billing views, monthly report artifacts, and report/export endpoints are implemented.&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="active-backend-work"&gt;Active Backend Work &lt;a href="#active-backend-work" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;No active implementation branch is tracked in this docs site. Operators should
still treat the gaps below as open before production acceptance.&lt;/p&gt;</description></item><item><title>Workers And Queues</title><link>https://docs.wipe.stack-plane.com/docs/operations/02-workers-queues/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.wipe.stack-plane.com/docs/operations/02-workers-queues/</guid><description>&lt;h1 id="workers-and-queues"&gt;Workers And Queues &lt;a href="#workers-and-queues" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;The backend uses a PostgreSQL table-backed queue. Jobs are claimed with locking
semantics and dead-lettered after retry exhaustion. The operator source of truth
is the database plus structured worker logs and OpenTelemetry metrics.&lt;/p&gt;
&lt;h2 id="queues"&gt;Queues &lt;a href="#queues" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Queue&lt;/th&gt;
					&lt;th&gt;Producer&lt;/th&gt;
					&lt;th&gt;Consumer&lt;/th&gt;
					&lt;th&gt;Purpose&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;proofs.validated&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Proof submit routes&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;worker-proof&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Validate proof, decrypt payload, create certificate, consume license, sign PDF/receipt.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;certificates.to_anchor&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Certificate service&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;worker anchor&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Submit or update blockchain anchor metadata and regenerate certificate PDF.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;notifications.to_send&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;User, billing, webhook flows&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;worker notifications&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Send SMTP/webhook notifications, retry failures, write delivery metadata.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;billing.exports&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Billing export routes&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;worker reports&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Generate requested export artifacts.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;reports.monthly&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Report scheduler&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;worker reports&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Generate monthly billing report artifacts.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;proofs.retry&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Retry routes/scheduler&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;worker retry&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Re-enqueue due failed or awaiting-license proofs.&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The local PostgreSQL/PGMQ setup also seeds underscore queue names for local
compatibility: &lt;code&gt;proofs_validated&lt;/code&gt;, &lt;code&gt;certificates_to_anchor&lt;/code&gt;,
&lt;code&gt;notifications_to_send&lt;/code&gt;, &lt;code&gt;billing_exports&lt;/code&gt;, &lt;code&gt;reports_monthly&lt;/code&gt;, and
&lt;code&gt;proofs_retry&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Observability And Alerts</title><link>https://docs.wipe.stack-plane.com/docs/operations/03-observability-alerts/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.wipe.stack-plane.com/docs/operations/03-observability-alerts/</guid><description>&lt;h1 id="observability-and-alerts"&gt;Observability And Alerts &lt;a href="#observability-and-alerts" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;The current implementation emits OpenTelemetry signals to the collector. The
reference stack routes metrics to Prometheus, logs to Loki, traces to Tempo, and
dashboards/alerts to Grafana.&lt;/p&gt;
&lt;p&gt;The backend does not expose a Prometheus &lt;code&gt;/metrics&lt;/code&gt; endpoint by default.
Prometheus scrapes the OpenTelemetry Collector Prometheus exporter.&lt;/p&gt;
&lt;h2 id="local-urls"&gt;Local URLs &lt;a href="#local-urls" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Component&lt;/th&gt;
					&lt;th&gt;URL&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Grafana&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;http://localhost:3000&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Prometheus&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;http://localhost:9090&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Loki&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;http://localhost:3100&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Tempo&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;http://localhost:3200&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;OTLP gRPC&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;localhost:4317&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;OTLP HTTP&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;localhost:4318&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="signal-fields"&gt;Signal Fields &lt;a href="#signal-fields" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;HTTP logs include:&lt;/p&gt;</description></item><item><title>Audit, Verification, And Retention</title><link>https://docs.wipe.stack-plane.com/docs/operations/04-audit-verification-retention/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.wipe.stack-plane.com/docs/operations/04-audit-verification-retention/</guid><description>&lt;h1 id="audit-verification-and-retention"&gt;Audit, Verification, And Retention &lt;a href="#audit-verification-and-retention" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;The backend records admin/sensitive actions in the audit log and public
verification attempts in &lt;code&gt;verification_log&lt;/code&gt;. The maintenance worker handles
retention, verification metadata anonymization, and tamper-evident chain checks.&lt;/p&gt;
&lt;h2 id="audit-routes"&gt;Audit Routes &lt;a href="#audit-routes" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Route&lt;/th&gt;
					&lt;th&gt;Role&lt;/th&gt;
					&lt;th&gt;Scope&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;GET /admin/api/v1/audit&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;PLATFORM_ADMIN&lt;/code&gt;, &lt;code&gt;BILLING_OPERATOR&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Recent audit rows across the instance.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;GET /api/v1/audit&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;CLIENT_ADMIN&lt;/code&gt;, &lt;code&gt;AUDITOR&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Tenant-scoped audit rows.&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Audit entries are append-oriented and include hash-chain fields. The maintenance
worker verifies audit-chain continuity and records metrics/alerts on breaks.&lt;/p&gt;</description></item><item><title>Incident Response</title><link>https://docs.wipe.stack-plane.com/docs/operations/05-incident-response/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.wipe.stack-plane.com/docs/operations/05-incident-response/</guid><description>&lt;h1 id="incident-response"&gt;Incident Response &lt;a href="#incident-response" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;Use this page for first response. Record the incident, capture request IDs,
trace IDs, affected tenant/organization IDs where permitted, and the exact time
window before replaying or deleting anything.&lt;/p&gt;
&lt;h2 id="keycloak-outage"&gt;Keycloak Outage &lt;a href="#keycloak-outage" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Impact:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;New login/token requests fail.&lt;/li&gt;
&lt;li&gt;Existing API calls may continue briefly while tokens and JWKS cache remain valid.&lt;/li&gt;
&lt;li&gt;User, invitation, IdP, and provisioning operations should pause.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Triage:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Check Keycloak and Keycloak PostgreSQL health.&lt;/li&gt;
&lt;li&gt;Query realm metadata from the API network.&lt;/li&gt;
&lt;li&gt;Check API logs for JWT/JWKS errors and elevated &lt;code&gt;401&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Confirm public issuer URLs still match configured JWT &lt;code&gt;iss&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Recovery:&lt;/p&gt;</description></item><item><title>Backup And Restore</title><link>https://docs.wipe.stack-plane.com/docs/operations/06-backup-restore/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.wipe.stack-plane.com/docs/operations/06-backup-restore/</guid><description>&lt;h1 id="backup-and-restore"&gt;Backup And Restore &lt;a href="#backup-and-restore" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;Backups are an operations responsibility. The repository provides the data
layout and runtime services, but the final backup tooling depends on the target
host or Kubernetes platform.&lt;/p&gt;
&lt;h2 id="what-to-back-up"&gt;What To Back Up &lt;a href="#what-to-back-up" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Asset&lt;/th&gt;
					&lt;th&gt;Why it matters&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;PostgreSQL application database&lt;/td&gt;
					&lt;td&gt;Tenants, organizations, users, proofs, certificates, jobs, DLQ, audit, receipts, licenses, idempotency, verification logs.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Keycloak database/config&lt;/td&gt;
					&lt;td&gt;Realms, clients, users, roles, federation, credentials metadata.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Object storage buckets&lt;/td&gt;
					&lt;td&gt;Raw &lt;code&gt;.der&lt;/code&gt; proofs, PDFs, canonical JSON, binaries, exports, monthly reports.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Environment and secrets&lt;/td&gt;
					&lt;td&gt;Runtime config, DB/S3/SMTP/Keycloak credentials, signer mTLS material, frontend session secret.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Signer key custody records&lt;/td&gt;
					&lt;td&gt;Production signer owns cryptographic keys; back up according to signer/HSM policy, not application DB policy.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Nginx/TLS config&lt;/td&gt;
					&lt;td&gt;Public routing, certificates, redirects, callback behavior.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Generated release artifacts&lt;/td&gt;
					&lt;td&gt;Image tags/digests, SBOM/provenance, Swagger/client versions.&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Do not place API key raw secrets, JWTs, signer private keys, or production
license signing material in application backups.&lt;/p&gt;</description></item><item><title>API Contract And Release Checks</title><link>https://docs.wipe.stack-plane.com/docs/operations/07-api-contract-release/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://docs.wipe.stack-plane.com/docs/operations/07-api-contract-release/</guid><description>&lt;h1 id="api-contract-and-release-checks"&gt;API Contract And Release Checks &lt;a href="#api-contract-and-release-checks" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;The backend owns the API contract. Swagger is generated from Go annotations, and
the route-contract tool compares generated Swagger paths with the cahier-derived
route backlog.&lt;/p&gt;
&lt;h2 id="contract-files"&gt;Contract Files &lt;a href="#contract-files" class="anchor" aria-hidden="true"&gt;&lt;i class="material-icons align-middle"&gt;link&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;File&lt;/th&gt;
					&lt;th&gt;Purpose&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;backend/docs/api-routes.md&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Product route backlog extracted from the backend cahier.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;backend/docs/swagger/swagger.json&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Generated OpenAPI JSON.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;backend/docs/swagger/swagger.yaml&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Generated OpenAPI YAML.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;backend/docs/api-contract-status.md&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Human-readable implemented/missing route comparison.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;backend/docs/api-contract-status.json&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Machine-readable route comparison.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;frontend/src/lib/api/client&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Generated frontend HeyAPI client.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;dashboard/src/lib/api/client&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Generated dashboard HeyAPI client.&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Current status: all 54 expected cahier backlog operations are represented in
Swagger. Additional implemented routes include tenant admin CRUD, API keys,
webhooks, audit, public verification aliases, agent campaign revocation, and
ingest proof polling.&lt;/p&gt;</description></item></channel></rss>