PSA/ee/docs/extension-system/knative-app-domains.md
Hermes 284313f908
Some checks are pending
Bidi Control Character Guard / bidi-control-guard (push) Waiting to run
Circular Dependency Check / Check for new circular dependencies (push) Waiting to run
Citus Migration Smoke / Combined migrations on single-node Citus (push) Waiting to run
E2E Fresh Install Tests / fresh-install-e2e (push) Waiting to run
ext-v2 guardrails / Run ext-v2 guard and ESLint (push) Waiting to run
Integration Tests / Check for relevant changes (push) Waiting to run
Integration Tests / ${{ (github.event_name == 'schedule' || github.event.inputs.suite == 'full') && 'Full integration suite' || 'Tier-1 integration subset' }} (push) Blocked by required conditions
Mobile checks / Mobile lint + typecheck (push) Waiting to run
Mobile checks / Mobile unit tests (push) Waiting to run
Mobile checks / Mobile dependency audit (report) (push) Waiting to run
Mobile checks / Mobile reproducibility checks (push) Waiting to run
Secrets guard (env backups) / Ensure no tracked env backup files (push) Waiting to run
Temporal Readiness / fast-readiness (push) Waiting to run
Temporal Readiness / docker-parity (push) Waiting to run
TypeScript Type Check / Nx affected typecheck (push) Waiting to run
Unit Tests / Skipped-test budget (push) Waiting to run
Unit Tests / Nx affected unit tests (push) Waiting to run
Unit Tests / Server unit coverage (informational) (push) Waiting to run
Validate Tenant Management Schema / Check for relevant changes (push) Waiting to run
Validate Tenant Management Schema / Validate Tenant Management Schema (push) Blocked by required conditions
EE Workflows Build Guard / ee-workflows-build-guard (push) Waiting to run
Initial import of AlgaPSA codebase from PSA server
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz

Source: /opt/alga-psa on psa.joliet.tech
2026-06-22 16:12:17 -05:00

115 lines
5.4 KiB
Markdown

# Per-Extension App Domains (Knative) — Ops & RBAC
This document captures the operational pieces needed to support per-install application domains using Knative DomainMapping, provisioned by the Temporal worker.
Scope: We track changes here; the actual Helm/Kubernetes wiring is handled in the infra repo.
## Environment Variables
- Temporal worker
- `EXT_DOMAIN_ROOT`: Root wildcard domain for extension apps (e.g., `ext.example.com`).
- `RUNNER_NAMESPACE`: Kubernetes namespace where the Runner KService lives (defaults to `default`).
- `RUNNER_KSERVICE`: Name of the Knative Service for the Runner (defaults to `runner`).
- Standard Temporal env: `TEMPORAL_ADDRESS`, `TEMPORAL_NAMESPACE`, `TEMPORAL_TASK_QUEUE`.
- Runner KService
- `BUNDLE_STORE_BASE`: Base URL for bundle objects (e.g., `http://minio:9000/alga-ext/`).
- `REGISTRY_BASE_URL`: Base URL of the EE server (used for host lookup + validation).
- `EXT_CACHE_MAX_BYTES`: Optional cache/file size limit for static assets.
- `EXT_STATIC_STRICT_VALIDATION`: `true|false` to enforce strict tenant/contentHash validation.
- `EXT_EGRESS_ALLOWLIST`: Optional comma-separated host allowlist for guest HTTP egress.
- S3/MinIO creds if needed by origin access (typically not needed if using HTTP gateway with public read): `S3_ENDPOINT`, `S3_ACCESS_KEY`, `S3_SECRET_KEY`, `S3_BUCKET`.
## DNS / Ingress
- Configure wildcard DNS: `*.${EXT_DOMAIN_ROOT}` to Knative Ingress.
- If not using wildcard, automate DNS records for each provisioned domain.
## RBAC (Temporal Worker ServiceAccount)
Grant the Temporal worker permission to manage DomainMappings in the target namespace:
```
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: temporal-worker-knative
namespace: ${RUNNER_NAMESPACE}
rules:
- apiGroups: ["serving.knative.dev"]
resources: ["domainmappings"]
verbs: ["get", "list", "watch", "create", "patch", "update"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: temporal-worker-knative
namespace: ${RUNNER_NAMESPACE}
subjects:
- kind: ServiceAccount
name: temporal-worker
namespace: ${TEMPORAL_WORKER_NAMESPACE}
roleRef:
kind: Role
apiGroup: rbac.authorization.k8s.io
name: temporal-worker-knative
```
Ensure the Temporal worker Deployment/Pod uses `serviceAccountName: temporal-worker` and set environment variables `RUNNER_NAMESPACE`, `RUNNER_KSERVICE`, `EXT_DOMAIN_ROOT`.
## Temporal Activity Behavior
- `computeDomain(tenantId, extensionId, EXT_DOMAIN_ROOT)` returns `${t8}--${e8}.${EXT_DOMAIN_ROOT}` where:
- `t8` is the first 8 hex chars if `tenantId` looks like a UUID, otherwise first 12 slug chars
- `e8` is calculated similarly for `extensionId`
- Rationale: keep `metadata.name` within Kubernetes 63-char limit for DomainMapping resources.
- `ensureDomainMapping({ domain, namespace, kservice })`:
- Preflight checks:
- Verifies Knative Service exists: `serving.knative.dev/v1`, resource `services`, name `${kservice}` in `${namespace}`
- Ensures ClusterDomainClaim exists for `${domain}` (`networking.internal.knative.dev/v1alpha1`).
- If env `KNATIVE_AUTO_CREATE_CDC=true`, the worker attempts to create the CDC.
- Otherwise, it fails with a clear message including a ready-to-apply CDC manifest.
- Creates or patches `DomainMapping`:
- `apiVersion: serving.knative.dev/v1beta1`, `kind: DomainMapping`, `metadata.name: ${domain}`
- `spec.ref: { apiVersion: 'serving.knative.dev/v1', kind: 'Service', name: ${kservice} }`
- On success, status in DB is updated to `{ state: 'ready' }` and `runner_ref` stores a small reference object.
## Runner
- Exposes `GET /` which reads Host → calls `REGISTRY_BASE_URL/api/installs/lookup-by-host` (API wrapper around the `installs.lookupByHost` server action) → redirects to `/ext-ui/{extensionId}/{content_hash}/index.html`.
- Continues to enforce strict validation in `/ext-ui` route via `/api/installs/validate`.
## Next.js (EE Server)
- Server actions-first (business logic):
- `installs.lookupByHost(host: string)``{ tenant_id, extension_id, content_hash }`.
- `installs.validate(tenant: string, extension: string, hash: string)``{ valid: boolean }`.
- `installs.provisionDomain(installId: string)` / `installs.reprovision(installId: string)` → triggers Temporal workflow.
- Thin API wrappers for external consumers (delegate to actions only):
- `GET /api/installs/lookup-by-host?host=...`
- `GET /api/installs/validate?tenant=...&extension=...&hash=...`
- `POST /api/installs/:id/reprovision`
### Lookup and Validate Contracts
- LookupByHost response: `{ tenant_id: string, extension_id: string, content_hash: string }`.
- Validate response: `{ valid: boolean }`.
## Helm Values Hints (Infra Repo)
- temporal-worker chart:
- `serviceAccount.name: temporal-worker`
- env:
- `RUNNER_NAMESPACE: <ns>`
- `RUNNER_KSERVICE: runner`
- `EXT_DOMAIN_ROOT: ext.example.com`
- `KNATIVE_AUTO_CREATE_CDC: "true"` (optional; requires ClusterRole to manage ClusterDomainClaims)
- RBAC templates include Role/RoleBinding above when enabled.
## RBAC for ClusterDomainClaim (optional)
To auto-create ClusterDomainClaims, grant the Temporal worker a ClusterRole with read/create/patch on `clusterdomainclaims.networking.internal.knative.dev` and bind it via ClusterRoleBinding to the worker ServiceAccount.
---
Change history: Introduced with per-install app domains (Plan 1.f).