Naming conventions
The rules for naming things on the PLANA platform. Mostly automatic (scripts, Crossplane Compositions, CI workflows enforce them), but codified here so new code and new resources line up.
Resource prefixes
| Prefix | Used for |
|---|---|
plana_* | Odoo modules (e.g. plana_auth, plana_saas) |
pulse-* | Service repos (e.g. pulse-account-api, pulse-banking) |
PLANA_* | Environment variables |
PLANA:* | Redis key prefixes (e.g. PLANA:events, PLANA:executions:{workspace}) |
pa_live_* | Workspace API keys (the user-issued kind) |
Old-codebase prefixes you might see in legacy commits:
| Old prefix | Replacement |
|---|---|
tc_* | plana_* |
t_core_* | plana_* |
TC_* | PLANA_* |
Never use the old prefixes. Code under plana_* is the only allowed form going forward.
Tenant naming
For each customer tenant:
| Concept | Pattern | Example (acme, projectId=23) |
|---|---|---|
| Subdomain | [a-z0-9-]+, max 30 chars | acme |
| Hostname (default) | {subdomain}.planapulse.app | acme.planapulse.app |
| Production alias (optional) | {subdomain}.planapulse.online | acme.planapulse.online |
| Dev / preview | {subdomain}.planapulse.dev | acme-staging.planapulse.dev |
| Database name | Same as hostname | acme.planapulse.app |
| Filestore path | /var/lib/odoo/filestore/{db_name} | /var/lib/odoo/filestore/acme.planapulse.app |
| Namespace | plana-odoo[-{version}] | plana-odoo-18 |
| Crossplane CR name | {subdomain} | acme |
| Matrix support room | support-{subdomain}-{projectId:03d} | support-acme-023 |
The hostname is the database name. Odoo's dbfilter=^%h$ makes this work — the HTTP Host header maps to the DB exactly.
Image naming
git.planapulse.com/<org>/<image-name>[:<tag>]Conventions:
| Pattern | Use |
|---|---|
git.planapulse.com/plana-pulse/<service>:<sha> | Service builds, immutable |
git.planapulse.com/plana-pulse/<service>:latest | Always points at the most recent main |
git.planapulse.com/plana-pulse/odoo-modules/base-{N}:<sha> | Per-major Odoo base images |
git.planapulse.com/plana-pulse/odoo-modules/base-{N}-upgrade:<sha> | OpenUpgrade variants |
git.planapulse.com/plana-pulse/kaniko:debug | Kaniko builder for CI |
Tags use the short SHA (first 8 characters of the commit SHA), not branch names. latest is a convenience pointer; production should not deploy from latest.
Branch naming on odoo-modules
| Branch | Tracks |
|---|---|
17.0 | Odoo 17 |
18.0 | Odoo 18 |
19.0 | Odoo 19 |
main | Default — symlinks to the current major (currently 18.0) |
OCA-fork/<repo> branches | 17.0-planapulse, 18.0-planapulse, 19.0-planapulse for OCA modules we fork |
For non-Odoo repos, standard main + feat/<name> for feature branches.
Kubernetes resource naming
| Type | Pattern |
|---|---|
| Namespace | <product-family>[-<variant>] (e.g. plana-odoo-18, pulse-account) |
| Deployment | <service-name> (e.g. pulse-account-api) |
| Service | Same as deployment |
| HTTPRoute | <tenant-slug> or <service-name> |
| ConfigMap | <service-name>-config or <service-name>-<purpose> |
| Secret | <service-name>-secret or <purpose>-creds |
| PVC | <purpose> (e.g. pvc-filestore-basic) |
| CronJob | <task-name> (e.g. <tenant>-backup) |
Avoid embedding environment in the name — namespaces serve that purpose.
Crossplane XR names
PLANAClient → matches the tenant subdomain (e.g. acme).
TenantUpgrade → {slug}-{fromVersion}-to-{toVersion}-{timestamp} or similar — descriptive of the operation.
TemplateSnapshot → {templateCode}-{version} (e.g. basic-18).
SOPS secret paths
JSON-path-like in the encrypted YAML:
["category"]["subcategory"]["key"]Examples:
| Path | What |
|---|---|
["plana"]["oauth_client_secret"] | Tenant OIDC client secret |
["pulse_banking"]["revolut_client_secret"] | PSD2 |
["ai_agents"]["anthropic_api_key"] | LLM |
["forgejo"]["registry_pull_secret"] | CI image pull |
Categories follow the top-level YAML structure in infra/secrets/plana-pulse.enc.yaml.
Where to read more
- Glossary — what each name refers to
- Architecture → Domains
- Crossplane — how XR names map to emitted resources
- Multi-version Odoo