---
name: omega-cloud-tenant
description: "Operate this organization's Omega Cloud tenancy correctly. Use this skill for ANY work against the Omega Cloud environment: creating or managing virtual machines, private networks, routers, security groups, public (floating) IPs, storage volumes, load balancers, Kubernetes clusters, application secrets and TLS certificates, CI/CD pipelines that talk to the cloud, quota questions, and team user management. Use it even for seemingly simple OpenStack commands: this platform has a three-account model and deliberate permission boundaries that make generic OpenStack advice wrong here."
---

# omega-cloud-tenant

You are operating a private, isolated environment (a "domain") on Omega
Cloud, a managed OpenStack platform. Everything inside the domain is
self-service; the platform around it is managed by the operator. This
skill tells you which account to use for which job, which permission
errors are correct behavior, and how to behave on a live environment.

TEMPLATE NOTE (removed before delivery): fields written as {{THIS}} are
filled in per client at handover. A delivered copy contains none.

Your identifiers (from the Handover Pack):

- Client short name (prefix on everything): `{{TENANT_SHORT_NAME}}`
- Identity endpoint (auth URL): `{{AUTH_URL}}`
- Web dashboard: `{{DASHBOARD_URL}}`
- Region: `{{REGION}}`
- Account contact (for anything the platform will not let you do):
  {{ACCOUNT_CONTACT}}

## Step 0 - pick the right account (the #1 source of failures)

Three accounts exist. Using the wrong one for a job is the most common
self-inflicted failure on this platform. Before running ANY command,
decide which account the job belongs to:

| Account | Signs in with | Use it for | Never for |
|---|---|---|---|
| `{{TENANT_SHORT_NAME}}-domain-admin` | password | team users, projects, role grants inside your domain | workloads, automation |
| `{{TENANT_SHORT_NAME}}-cluster` | password | Kubernetes cluster create/delete; it OWNS the SSH keypair `{{TENANT_SHORT_NAME}}-key` | general automation, team logins |
| `{{TENANT_SHORT_NAME}}-svc` | its application credential (`{{TENANT_SHORT_NAME}}-svc-cred`) | everything else: networks, VMs, volumes, floating IPs, load balancers, secrets, all scripted and day-2 work | Kubernetes cluster create/delete, identity work |

Three rules that prevent the three most common outages:

1. Kubernetes clusters are created and deleted ONLY by the `-cluster`
   account, signed in with its PASSWORD. The platform's cluster
   machinery cannot operate through an application credential; a
   cluster create attempted with the `-svc` credential fails every
   time. This is a platform constraint, not a setting.
2. The SSH keypair `{{TENANT_SHORT_NAME}}-key` belongs to the
   `-cluster` account. Never delete it or recreate it under another
   account; clusters refuse to build with a key owned by anyone else.
3. The `-domain-admin` account does identity work ONLY. Never run
   workloads or automation with it, and never hand out its password;
   create individual users for people instead.

## The boundary model - refusals that are BY DESIGN

The platform enforces hard boundaries. When one of these operations is
refused, the refusal is CORRECT BEHAVIOR: do not retry, do not switch
accounts to work around it, do not treat it as an outage, and never
try to "fix" it. Report the need to a human instead.

Expected refusals:

- Identity operations (create user, grant role) attempted with the
  application credential: denied. Identity work belongs to
  `-domain-admin` only.
- Kubernetes cluster create/delete attempted with the application
  credential: denied. Use the `-cluster` account with its password.
- Any quota change from any of your accounts: denied. Quotas are set
  by the operator; an authorized requester asks via {{ACCOUNT_CONTACT}}.
- Any grant of `admin` to any user: denied by design. If an `admin`
  grant ever SUCCEEDS or appears in your domain, stop and report it
  to {{ACCOUNT_CONTACT}} as urgent -- that is a platform incident.
- Changes to the shared substrate (the external network
  `provider-ext`, the public floating IP pool, shared base images,
  machine sizes): denied. Requests go through {{ACCOUNT_CONTACT}}.
- Anything touching another domain or the platform's own
  infrastructure: denied, always.

The full table, with triage order, is in
`references/troubleshooting.md`.

## Authenticating

Tools authenticate against the identity endpoint `{{AUTH_URL}}` and
discover every other service from the catalog. Two equivalent forms:

`clouds.yaml` (preferred for interactive work):

    clouds:
      {{TENANT_SHORT_NAME}}:
        auth_type: v3applicationcredential
        auth:
          auth_url: {{AUTH_URL}}
          application_credential_id: <id from the delivered credential file>
          application_credential_secret: <injected at runtime, never written to a repo>
        region_name: {{REGION}}
        identity_api_version: 3
        cacert: <path to the delivered CA bundle>

    export OS_CLOUD={{TENANT_SHORT_NAME}}
    openstack token issue        # smoke test: a token scoped to your project

Environment-variable form (no file needed): `OS_AUTH_TYPE`,
`OS_AUTH_URL`, `OS_IDENTITY_API_VERSION=3`, `OS_CACERT`,
`OS_APPLICATION_CREDENTIAL_ID`, `OS_APPLICATION_CREDENTIAL_SECRET`.
Password logins (for `-domain-admin` and `-cluster`) use
`OS_AUTH_TYPE=password` with `OS_USERNAME`, `OS_PASSWORD`,
`OS_USER_DOMAIN_NAME={{TENANT_SHORT_NAME}}`,
`OS_PROJECT_NAME={{TENANT_SHORT_NAME}}-prod`,
`OS_PROJECT_DOMAIN_NAME={{TENANT_SHORT_NAME}}` -- prompt the human for
the password; never read it from a file into your context.

Rules that always apply:

- Never hardcode a service endpoint. Authenticate against
  `{{AUTH_URL}}` and let the client discover the rest
  (`openstack catalog list` shows what it sees).
- Always point tools at the delivered CA bundle (`cacert` /
  `OS_CACERT`). Never disable TLS verification instead.
- The dashboard at {{DASHBOARD_URL}} is the human-facing path; your
  work goes through the CLI/API, which always has the full
  capability set.

## Routing - where to go for what

Load the reference file BEFORE doing work in its area; each carries
the runnable command sequences and the traps.

| Task | Read first |
|---|---|
| Networks, routers, security groups, VMs, volumes, floating IPs, load balancers, secrets/TLS | `references/day2-operations.md` |
| Anything Kubernetes: create/delete clusters, kubeconfig, deploying, Services of type LoadBalancer | `references/kubernetes.md` |
| CI pipelines, automation credentials, credential rotation, pipeline hygiene | `references/ci-automation.md` |
| Any failure, error message, or permission denial | `references/troubleshooting.md` |
| Team users and role grants | Step 0 above (as `-domain-admin`); user-create commands in `references/day2-operations.md` |
| Read-only audit, CI smoke test, leftover sweep | the delivered starter scripts (see "Starter scripts" below) |
| Quota raise, password reset, custodian change, shared substrate | not self-service -- an authorized requester contacts {{ACCOUNT_CONTACT}} |

## Starter scripts (delivered with your document pack)

Your document pack includes a `scripts/` directory of helpers; run
them with `bash` from wherever your team keeps the pack:

- `bash scripts/tenancy-audit.sh` -- full read-only snapshot of the
  tenancy plus the quota envelope. The recommended first command of
  any session, and the standard proof that authentication, the CA
  bundle, and endpoint discovery all work.
- `bash scripts/smoke-test.sh` -- CI smoke test (token, catalog,
  quota headroom); make it the first step of every pipeline.
- `bash scripts/ci-cleanup-sweep.sh --prefix ci-` -- reports
  pipeline-created leftovers and detached floating IPs (dry-run by
  default; deletes NOTHING without `--apply` -- deletion stays a
  deliberate, human-confirmed choice).
- `bash scripts/acceptance-run.sh` -- the automated acceptance
  checklist rows (self-service ones); also your recurring deep smoke
  test.

The audit, the smoke test, and the sweep's default dry-run change
nothing; the acceptance run creates only `ci-accept-*` resources and
tears them down again. If your copy of the pack does not include
them, the inline commands in the reference files cover the same
ground.

## Operating discipline (you are acting on a LIVE environment)

1. Read-only before mutate. Audit current state with `list`/`show`
   commands before any create, change, or delete.
2. Confirm before destroy. Never delete, detach, or replace a
   resource without explicit human confirmation naming the resource.
   Never batch destructive operations.
3. Never print credential material. No password, application
   credential secret, kubeconfig content, or private key ever goes to
   the screen, a log, or your output. Verify a credential file by
   length or format from a script, never by displaying it.
4. Quota errors are actionable, not retryable. A quota-exceeded error
   means: clean up leaked resources, or have an authorized requester
   ask {{ACCOUNT_CONTACT}} for a raise. Retrying will not help.
5. Expected refusals are not bugs (see the boundary model above).
   Never escalate privileges or switch accounts to bypass a denial.
6. Pace your polling. Waiting for a resource to build: poll at
   10-second intervals or slower, or use the CLI `--wait` flags.
   Load balancers take minutes and clusters take tens of minutes --
   that is normal, not a hang.
7. Name what you create. Tag or name resources with a purpose or job
   id so they can be found and cleaned up; delete what you no longer
   need (floating IPs count against quota even when detached).
8. On anything that looks like a platform fault, capture the exact
   command and the verbatim error text for {{ACCOUNT_CONTACT}}.
   Verbatim errors get fast answers; paraphrased ones do not.

## Companion documents

The Welcome letter, Self-Service Guide, Handover Pack, Acceptance
Checklist, and CI/Automation Integration Guide delivered at handover
are the authoritative long-form references; this skill is the
operating layer over them. If this skill and a delivered document
disagree, the delivered document wins -- flag the divergence to
{{ACCOUNT_CONTACT}}.
