Architectural correction. Replaces the previous "one Gitea repo per Environment with Apps as folders" rule with a single uniform shape that scales by configuration only: - Catalyst Application = one Gitea Repo (always, regardless of scale) - Branches develop/staging/main map to dev/stg/prod environments - 5 conventional Gitea Orgs per Sovereign: catalog (public mirror), catalog-sovereign (Sovereign-curated private Blueprints), one per Catalyst Organization (with shared-blueprints + N App repos), system (sovereign-admin scope) - EnvironmentPolicy CR lives in system/catalyst-config/policies/, same shape for SME and corporate; only field values differ Removes the SME-vs-corporate dual-shape design that violated the "Application is application" invariant. Teams primitive (proposed for corporate scale) is dropped — team boundaries emerge from CODEOWNERS at the App-repo level. RE-score thresholds and EnvironmentPolicy fields are universal defaults; only their values vary per Org's policy choice. Files updated line-by-line: GLOSSARY (Application + Environment definitions, new Gitea-Orgs section, 6 component-row updates), NAMING §11.2 (Realization 7-bullet rewrite), ARCHITECTURE (§1, §3 topology, §4 write-side ASCII, §7.1+§7.2+§7.3, §8 promotion, §9 multi-App linkage), PERSONAS-AND-JOURNEYS (§2 surfaces, §4.1 Ahmed, §4.2 Layla full rewrite), BLUEPRINT-AUTHORING §1 (catalog-sovereign source location), PLATFORM-TECH-STACK §2.2+§2.3, SECURITY §3, SOVEREIGN-PROVISIONING §5+§8+§10, IMPLEMENTATION-STATUS §5, SRE §14. VALIDATION-LOG entry "Pass 103 — UNIFIED REPO MODEL REFACTOR" captures the architectural correction and acknowledges the prior 102-pass audit anchored on the wrong shape (text-shape consistency was correct; the chosen text-shape was inadequate). Lesson #21 added: text-shape audits don't substitute for architectural review. Verification: zero remaining old-model assertions in canonical docs (grep clean for 'Environment Gitea repo', '/{org}/{org}-{env_type}', 'per-Environment Gitea repos', 'applications/<app>/values', etc.).
17 KiB
Personas and Journeys
Status: Authoritative target experience. Updated: 2026-04-27.
Implementation: The journeys described use Catalyst surfaces (console / Git / API) that are design-stage. See IMPLEMENTATION-STATUS.md.
How different people use Catalyst. Defer to GLOSSARY.md for terminology.
1. Personas
| # | Persona | Where they live | Tools they use |
|---|---|---|---|
| P1 | OpenOva Engineer | github.com/openova-io | Catalyst codebase, Blueprint repos |
| P2 | sovereign-admin |
Catalyst admin UI + Sovereign Gitea | Browser UI, Git, kubectl (debug) |
| P3 | Support Agent (within a Sovereign's operations team) | Catalyst admin UI in support mode | Browser UI |
| P4 | org-admin |
Org-scoped Catalyst console | Browser UI, occasional Git |
| P5 | SME End User (e.g. Ahmed, pharmacy owner on Omantel) | Marketplace + the App they installed | Browser only |
| P6 | SME Power User (e.g. Ahmed's tech-savvy nephew) | Console with Developer mode toggled on | Browser, occasionally Git |
| P7 | Corporate DevOps / SRE (e.g. Layla at Bank Dhofar) | Git + console in advanced view | Browser, Git, kubectl-on-own-vcluster, IDE |
| P8 | Corporate App Developer (e.g. Omar at Bank Dhofar) | Console + Git for own service repos | Browser, Git, IDE |
| P9 | Security/Compliance Officer (e.g. Khalid, CISO) | Audit dashboards + EnvironmentPolicy editor | Browser |
| P10 | Billing Admin | Billing console | Browser |
2. Surfaces
The three first-class surfaces (full list and rationale in ARCHITECTURE.md §7):
- UI — Catalyst console. Form / Advanced / IaC editor depths.
- Git — direct push or PR to the Application's Gitea repo (one repo per App; branches
develop/staging/mainmap to dev/stg/prod), or to private Blueprint repos (shared-blueprintsper-Org orcatalog-sovereignSovereign-wide). - API — REST + GraphQL, for portal integrations.
Plus one debug-only surface:
- kubectl — inside one's own vcluster. Read-mostly, never used to mutate Catalyst-managed resources.
There is no fourth surface. Terraform, Pulumi, "catalystctl install" are not part of this model.
3. Personas × Journeys matrix
Cells show which surface(s) the persona uses for that journey. Bold = primary. Italic = secondary. Empty = not applicable.
| P1 | P2 | P3 | P4 | P5 | P6 | P7 | P8 | P9 | P10 | |
|---|---|---|---|---|---|---|---|---|---|---|
| J1 Build & publish Blueprint to public catalog | Git + CI | |||||||||
| J2 Provision a Sovereign | UI+Git | |||||||||
| J3 Onboard an Organization | UI | UI | ||||||||
| J4 Create an Environment | UI | UI | auto on signup | UI | UI | view audit | ||||
| J5 Install Application from catalog | UI | UI form | UI | UI + Git | UI + Git | view audit | view cost | |||
| J6 Configure Application | UI | UI form | UI | UI + Git | UI + Git | view audit | ||||
| J7 Author private Blueprint | Git+CI | UI + Git | Git + CI | Git + CI | review + sign | |||||
| J8 Author Crossplane Composition (advanced) | Git + CI | Git+CI | Git + CI | review | ||||||
| J9 Promote between Environments | UI | UI + Git PR | UI + Git PR | UI approve | ||||||
| J10 Observe runtime / debug | UI dashboards | UI dashboards | UI dashboards | App's own UI | UI | UI + kubectl | UI + kubectl | UI audit | ||
| J11 Rotate credentials | UI + auto | UI + auto | auto | UI | UI + auto | UI + policy | ||||
| J12 Audit / compliance review | UI | UI | UI | UI (own changes) | UI (own changes) | UI export to SIEM | ||||
| J13 Billing & quotas | UI quotas | UI read | UI invoices | UI plan | UI | |||||
| J14 Off-board / migrate | UI export | UI | UI cancel | UI export | audit | UI final invoice |
4. Two journey narratives, end-to-end
4.1 SME journey — Ahmed at Muscat Pharmacy (on Omantel)
Cast. Ahmed owns 4 small pharmacies in Muscat. No IT staff. He has a laptop and a credit card.
Day 1 — 14:00
─────────────
1. Ahmed visits omantel.openova.io. Sees the marketplace. No login required.
2. Picks "Pharmacy Starter Bundle" — a composite Blueprint
(bp-bundle-pharmacy: ERPNext + WooCommerce + Stalwart-mail + Postgres + Redis).
3. Clicks "Get Started" → Omantel-branded signup. Phone OTP via Omantel mobile
bill verification (federated identity). Account created.
4. Catalyst auto-creates: Organization "muscatpharmacy", Environment
"muscatpharmacy-prod", vcluster "muscatpharmacy" on hz-fsn-rtz-prod.
Environment-controller spins up the vcluster in ~60 seconds.
5. Bundle install wizard: 3 simple steps —
Step 1: subdomain (muscatpharmacy.shop.omantel.com)
Step 2: business details (form generated from Blueprint configSchema)
Step 3: payment plan (BHD 49/month)
6. Click Install. Provisioning service creates 5 Application Gitea repos under
gitea.<location-code>.omantel.openova.io/muscatpharmacy/ (one repo per App:
erpnext, woocommerce, pharmacy-mail, shared-postgres, shared-redis), each
with `develop`/`staging`/`main` branches and initial manifests.
Webhook → projector → Flux in the muscatpharmacy vcluster picks up the
N new GitRepository sources and reconciles.
7. ~3 minutes later: Ahmed sees green checkmarks on his dashboard.
Each App card has an "Open" button.
Click ERPNext → SSO via Omantel federated identity → he's in.
─────────────
Day 1 — 14:08 — Ahmed is selling.
What he never saw: Git, kubectl, vcluster, Flux, Blueprint, YAML, JetStream. His mental model: "I have an Omantel account. I bought a bundle. It works."
4.2 Corporate journey — Layla at Bank Dhofar (running its own Sovereign)
Cast. Layla is an SRE on Bank Dhofar's 12-person Cloud Platform team. They run their own Sovereign on Hetzner. Their internal Organizations are core-banking, digital-channels, analytics, corporate-it. Their default tooling is Git + IDE.
09:00 Coffee. Opens VS Code. Branch: bp-bd-payment-rail
─────────────────────────────────────────────────────────────────────────
She's authoring a private Blueprint for a payment-rail microservice
with Postgres + Redis dependencies.
09:15 Pushes to gitea.<location-code>.bankdhofar.local/digital-channels/shared-blueprints/
bp-bd-payment-rail. CI in Bank Dhofar's GitHub Actions runner pool
(running inside the Sovereign) builds the image, signs the Blueprint
with cosign, publishes to the local OCI registry. blueprint-controller
picks it up — visible as a private card in the digital-channels Org.
10:00 Switches to her Application repo:
gitea.<location-code>.bankdhofar.local/digital-channels/payment-rail
Checks out branch `develop` (the dev environment branch).
Edits values.yaml (config tweak).
Catalyst console (Plan view) shows the diff: what will change,
dependency impact, drift, cost delta. Like terraform plan, but
served by the API on the Git diff.
10:15 Happy. Commits to develop. Webhook → projector → Flux in the
digital-channels vcluster (watching the develop branch on this
Application repo) reconciles in 30s. Audit log captures her as
committer at the App-repo level.
11:00 Need to debug the staging deployment of the same App.
Browser: console → digital-channels-stg → payment-rail card
→ Logs tab. Then Topology tab to see across regions.
Or, drops into kubectl scoped to her vcluster:
$ kubectl --context=hz-fsn-rtz-prod-digital-channels logs -n payment-rail
Direct kubectl, scoped strictly to her Org's vcluster (vcluster name
per NAMING §1.5 is the Org name, not the Sovereign name — Layla's Org
is `digital-channels`). Bank Dhofar's sovereign-admin grants this via
a JIT elevation flow.
14:00 Promotion stg → uat. From the payment-rail Application card,
clicks "Promote staging → uat". Catalyst opens a Gitea PR
within the same payment-rail repo: source branch `staging`,
target branch (a feature branch tracking uat config). The
EnvironmentPolicy CR for digital-channels-uat (in
system/catalyst-config/policies/) requires team-platform approver
and an RE score ≥ 80%. Reviewer approves via Gitea web UI (or
via the Catalyst console's PR view — same backend). Auto-merge.
Flux in the uat-bound vcluster reconciles.
15:00 New Environment needed for a fraud lab. From the console:
"New Environment in analytics" → fills name "fraud-lab-dev" →
picks "small" topology (1 region, single bb=rtz). Environment-controller
creates the vcluster and bootstraps Flux pointing at the develop
branch of every Application repo in the analytics Org. No new repos
are created (Application repos exist already, indexed by branch).
Ready in 60s. Layla now has a new sandbox.
16:00 Business asks for the bank's existing Backstage portal to show
Catalyst-managed services. Layla integrates: Backstage queries
Catalyst REST API at https://api.<location-code>.bankdhofar.local/v1/applications,
authenticated via SPIFFE SVID (workload identity — Backstage runs
inside the Sovereign and gets a SPIRE-issued SVID). Backstage's
service catalog now includes Catalyst Applications alongside other
systems. No code change in Catalyst — the API was already there.
What Layla DOES use: UI (for promotion approvals, observability, EnvironmentPolicy editing), Git (for Blueprint authoring in shared-blueprints and per-Application config in each App's repo with develop/staging/main branches), kubectl (for debugging her own vcluster), and the API (for integrating Backstage). She never writes Crossplane code unless she's contributing a new Composition upstream as a Blueprint — and even then it's via a Gitea PR.
What Layla doesn't use: Terraform, Pulumi, a "catalystctl" CLI, or any other tool that bypasses Git.
5. Application card (the user's primary handle)
The card is the user's view of an Application in their Environment. Anatomy below; full UX in the console docs.
┌────────────────────────────────────────────────────────────────┐
│ 🌐 marketing-site ⋮ │ ← name + menu
│ bp-wordpress @ 1.3.0 │ ← Blueprint + version
├────────────────────────────────────────────────────────────────┤
│ ● Running 🔗 acme.com ↗ │ ← status + endpoint
│ │
│ 📍 eu-central 5 / 5 pods │ ← placement + health
│ 💾 postgres → shared-postgres (own card) │ ← key dependency (linked)
│ │
│ Last deploy: 2h ago by Layla ⏵ View history │ ← provenance
│ │
│ [ Open app ↗ ] [ Settings ] [ Logs ] [ Topology ] │ ← primary actions
└────────────────────────────────────────────────────────────────┘
States via the status badge:
| State | Meaning |
|---|---|
| ● Running (green) | All replicas healthy, traffic flowing |
| ◐ Installing (blue) | Flux reconciling, progress shown inline |
| ◑ Updating (blue) | Config or version change rolling out |
| ◒ Degraded (amber) | Partial — 3/5 pods, 2 unhealthy |
| ◓ Failed (red) | Install or update failed, "View error" button |
| ○ Paused (grey) | Manually paused, scale-to-zero |
| ◔ Pending approval (purple) | Promotion PR open, awaiting reviewers |
Clicking the card opens the detail page with tabs: Overview, Settings, Topology, Secrets, Observability, History, Manifests.
The Topology tab is where Placement edits happen — single-region → active-active, region picker, failover policy. The Manifests tab is the Monaco IaC editor.
6. Catalog vs Applications-in-use view
6.1 Marketplace (catalog)
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 🌐 WordPress │ │ 💬 Rocket.Chat │ │ 🏪 ERPNext │
│ Self-hosted │ │ Team chat │ │ ERP suite │
│ CMS │ │ │ │ │
│ │ │ │ │ │
│ ⭐ Popular │ │ │ │ 💼 Business │
│ [ Install ] │ │ [ Install ] │ │ [ Install ] │
└─────────────────┘ └─────────────────┘ └─────────────────┘
Card here = Blueprint card (something to install). Visually distinct from Application cards.
6.2 Blueprint detail page (cross-Environment view of Applications using a Blueprint)
Blueprint: bp-wordpress @ available 1.4.0 [⋮]
─────────────────────────────────────────────────────────────────────
Self-hosted CMS. Owner: vendor (openova). Latest: 1.4.0
Applications using this Blueprint in your Org (4)
Application Environment Version Status
─────────────────────────────────────────────────────
marketing-site acme-dev 1.4.0 ● Running [Open]
marketing-site acme-stg 1.3.0 ● Running [Open]
marketing-site acme-prod 1.2.0 ● Running [Open]
blog acme-prod 1.2.0 ● Running [Open]
[ + Install in another Environment ] [ Compare versions ]
This is the "where is this Blueprint running in my Org" view — the simplest cross-Environment surface. No chain object; just a query.
6.3 Environment view (where the cards live)
Environment: core-banking-prod [+ Install] [⋮ View modes ▼]
Group by: ( Status ▼ ) Filter: [_______] [List | Grid]
─── Running (12) ───────────────────────────────────────────
[ marketing-site card ] [ blog card ] [ payment-rail card ] …
─── Updating (1) ───────────────────────────────────────────
[ analytics-api ◑ updating to 2.3.0 ]
─── Degraded (1) ───────────────────────────────────────────
[ notification-bus ◒ 2/3 pods, restart pending ]
─── Backing services (4) ──────────────────────────────────
[ shared-postgres ] [ shared-redis ] [ kafka-cluster ] [ object-store ]
Backing services (Postgres, Redis, etc.) get their own section so users see infrastructure-as-Applications principle (one of the architectural commitments). Clicking a card surfaces dependents (Used by: marketing-site, blog, analytics-api).
7. Differences in default UI mode by Sovereign type
| Setting | SME-style (Omantel) default | Corporate default (Bank Dhofar) |
|---|---|---|
| Console default depth | Form view | Advanced view + IaC editor toggle on |
| Developer mode (Blueprint Studio) | Hidden, off | Visible by role |
| Multi-Environment promotion features | Hidden when only 1 Env | Visible always |
| EnvironmentPolicy editor | Hidden by default | Visible by role |
kubectl access for users |
Off | On for org-developer and above |
| Git access for users | Off (sovereign-admin can flip per-Org) | On |
| Marketplace features (search, bundles, ratings) | All on | All on but de-emphasized |
| Specter / AIOps Blueprint included by default | Optional | Recommended (Cortex + Specter on top) |
Each Sovereign sets its defaults at provisioning time; users within can override via per-user preferences within the role permissions allowed.
Cross-reference GLOSSARY.md and ARCHITECTURE.md for the underlying model.