Reference
Fast lookups for this Project Loom instance: pinned versions, endpoints, namespaces, and secrets. Anything Penvoice-specific below is an example app, not the platform.
Pinned versions
Section titled “Pinned versions”| Chart / operator | Version |
|---|---|
| cert-manager | v1.20.2 |
| argo-cd | 9.5.21 |
| argo-rollouts | 2.41.0 |
| CloudNativePG | 0.28.3 (operator v1.29.1) |
| Keycloak operator | 26.6.3 |
| Infisical (server chart) | 1.10.0 |
| Infisical Secrets Operator | 0.11.8 |
Live endpoints
Section titled “Live endpoints”| Host | What |
|---|---|
loom.webbies.dev | This guide |
control.webbies.dev | Argo CD (apps portal) |
uat.auth.webbies.dev | Keycloak (UAT / staging overlay) |
auth.webbies.dev | Keycloak (prod) |
vault.webbies.dev | Infisical UI |
test.penvoice.app | Penvoice web (staging) |
penvoice.app | Penvoice web (prod) |
test.api.penvoice.app | Penvoice API (staging) |
api.penvoice.app | Penvoice API (prod) |
test.mytalon.co.zw | Talon web (staging) |
mytalon.co.zw | Talon web (prod) |
test.api.mytalon.co.zw | Talon API (staging) |
api.mytalon.co.zw | Talon API (prod) |
test.invoicer.visarend.systems | Invoicer (staging) |
invoicer.visarend.systems | Invoicer (prod) |
Every app follows the same host pattern: web is the plain domain (domain.tld), API is api.domain.tld, and staging
prefixes either with test. (test.domain.tld / test.api.domain.tld).
Run kubectl on the node, or locally once set up. See Access.
| Repo | Contents |
|---|---|
webb1es/loom | Manifests (app-of-apps). Private. Source of truth. |
webb1es/penvoice-api | Go REST API. CI → GHCR, public package. |
penvoice-web | Angular SPA. Deploys on Vercel (branch-based). |
webb1es/talon-api | Go BFF (session-based, not a stateless resource server; owns its own credentials). CI → GHCR, public package. |
talon-web | React SPA. Deploys on Vercel (branch-based). |
webb1es/invoicer | Go server-rendered app on SQLite. CI → GHCR, pushed straight to its staging branch. |
Images: ghcr.io/webb1es/penvoice-api:sha-<sha>, ghcr.io/webb1es/talon-api:sha-<sha>,
ghcr.io/webb1es/invoicer:sha-<sha>.
Namespaces
Section titled “Namespaces”| Namespace | Runs |
|---|---|
argocd | Argo CD / Rollouts |
cert-manager | cert-manager |
cnpg-system | CloudNativePG operator |
keycloak | Keycloak operator only |
keycloak-staging | Staging Keycloak + Postgres |
keycloak-prod | Prod Keycloak + Postgres |
infisical | Infisical server + secrets operator + its Postgres |
penvoice-staging | Penvoice API + Postgres + Redis (staging) |
penvoice-prod | Penvoice API + Postgres + Redis (prod) |
talon-staging | Talon API + Postgres + Redis (staging) |
talon-prod | Talon API + Postgres + Redis (prod) |
invoicer-staging | Invoicer + Gotenberg + SQLite volume (staging) |
invoicer-prod | Invoicer + Gotenberg + SQLite volume (prod) |
Out-of-band secrets (not in Git)
Section titled “Out-of-band secrets (not in Git)”Recreate these by hand. Provision. <app>-api-kc is not in this list: Infisical owns
it. See Secrets.
| Secret | Namespace(s) | What |
|---|---|---|
infisical-secrets | infisical | Infisical server’s own AUTH_SECRET/ENCRYPTION_KEY/DB_CONNECTION_URI/REDIS_URL |
infisical-pg-backup-creds | infisical | Oracle Object Storage S3 keys |
infisical-<app>-identity | <app>-staging, <app>-prod | Machine Identity per env |
keycloak-config-cli-sa | keycloak-staging, keycloak-prod | config-cli service-account (master realm, admin) |
<app>-pg-backup-creds | matching app/keycloak env ns | Oracle Object Storage S3 keys |
Oracle S3 keys: access key = clean hex; secret key has +/=. Don’t swap.
The Keycloak realm config also lives out-of-band (in its DB, which is backed up).
Backups
Section titled “Backups”| Setting | Value |
|---|---|
| Bucket | penvoice-pg-backups (per-cluster folders) |
| Schedule | Nightly ScheduledBackup + continuous WAL archiving |
| PITR window | Staging 3 days; prod and Infisical 7 days |
| Region | af-johannesburg-1 |
| Required S3 env | AWS_REQUEST_CHECKSUM_CALCULATION=when_required, AWS_RESPONSE_CHECKSUM_VALIDATION=when_required, AWS_DEFAULT_REGION=af-johannesburg-1 |
OCI Email Delivery, region af-johannesburg-1. Setup:
Provision § 9 once,
Onboard § Email per app. Model: Concepts § Email.
| Setting | Value |
|---|---|
| SMTP endpoint | smtp.email.af-johannesburg-1.oci.oraclecloud.com, port 587 (STARTTLS) |
| Email domain | mail.visarend.systems (compartment email), DKIM selector visarend-jnb-<yyyymm> |
| Policy | email-apps-send (root), one line per app |
| Notices mailbox | oci@visarend.systems (Zoho), one alias per app |
| Limits | 50,000 emails/day, ~2 MB per message including encoding, 18,000/min |
| App | Compartment | Approved sender (MAIL_FROM) | OCI user / email | Group | Settings live in |
|---|---|---|---|---|---|
| invoicer | email-invoicer | invoicer@mail.visarend.systems | SMTP Invoicer / oci-invoicer@visarend.systems | email-invoicer | Infisical invoicer |
| ayde | email-ayde | ayde@mail.visarend.systems | SMTP Ayde / oci-ayde@visarend.systems | email-ayde | Infisical ayde |
| talon | email-talon | talon@mail.visarend.systems | SMTP Talon / oci-talon@visarend.systems | email-talon | Infisical talon |
| sonke | email-sonke | sonke@mail.visarend.systems | SMTP Sonke / oci-sonke@visarend.systems | email-sonke | Infisical sonke |
| keycloak | email-keycloak | auth@mail.visarend.systems | SMTP Keycloak / oci-keycloak@visarend.systems | email-keycloak | Keycloak realm Email tab (DB) |
Infisical keys per app: SMTP_HOST, SMTP_PORT, SMTP_USERNAME, SMTP_PASSWORD, MAIL_FROM.
Canary
Section titled “Canary”No metrics stack. Prod overlays pause 60s at 25% / 50% / 75%. Staging is one replica and setWeight: 100.