Cloud Governance
The company-wide standard for tracking Azure resources, costs, and access across the three Wasteology-owned subscriptions. Live state is queried on demand; this page holds the durable policy — ownership, intent, and process.

Resource lists, role assignments, and costs live in Azure Resource Graph and Cost Management. Query them with the ops azure CLI. This document records only what Azure cannot: ownership, intent, and process.
Scope is the three Wasteology-managed subscriptions below. The Pathfinder Dev/Prod subscriptions are deliberately out of scope for this standard.
Subscription Map
The three subscriptions this standard governs, all in tenant 094ceb6c-a94d-47ad-a049-1cb1edca9e45. Each maps to a short alias used by the ops azure CLI (--sub dev|prod|orbit).
| Alias | Subscription | ID | Role |
|---|---|---|---|
dev | Wasteology Development | 669a4356-6871-4f9b-9256-ba98d5a6eb4c | All dev/CI resources: dev DBs, CieTrade ACI execution, source ACRs, BINS dev |
prod | Wasteology Production | a5a6818e-a0c0-4c6a-8b5c-21e91d75caa8 | Always-on platform apps, prod DBs, non-CieTrade ACI, palantiri, CieTrade SQL source |
orbit | Wasteology-Orbit | 60e2b27e-fc5d-4b4b-81a9-ae650e8f2adf | Dedicated Orbit work-order platform (Mars pilot) |
Tracking Model
Three layers, each with a distinct home and refresh cadence. The point of separation is that live state goes stale the moment it is written down, so only policy and decisions are version-controlled. The overview infographic at the top of this page shows how the three layers relate.
| Layer | Answers | Home | Refresh |
|---|---|---|---|
| Live state | What exists, who has RBAC, what it costs right now | Azure Resource Graph + Cost Management via ops azure | On demand — never stale |
| Durable policy | Who owns it, why it exists, how to request/provision | This page | Git-reviewed edits |
| Change trail | Who granted what, when | DB grants → wg_digests.dbaccess_audit_log; RBAC/provisioning decisions → git history | Automatic |
Live state — ops azure
On-demand queries against live Azure, scoped to the three subscriptions above. No data is stored; every run reflects current state. Full command reference: ops azure.
| Command | Purpose |
|---|---|
ops azure inventory [--sub] [--type] | Resource Graph listing of all resources (filter by subscription or type substring) |
ops azure costs [--sub] [--by resourcegroup|service] | Month-to-date actual cost from Cost Management, grouped and totalled |
ops azure access [--sub] [--resource] [--principal] | RBAC role assignments at subscription or resource scope, filterable by principal |
ops azure identities | Service principals (owned app registrations) + user-assigned managed identities we run |
ops azure costs requires the costmanagement az extension (az extension add --name costmanagement) — the command prints this hint if it is missing.
Database Servers
The seven database servers within the three governed subscriptions. Data-plane access differs sharply by auth mode — see the note after the table.
| Server | Engine | Sub | Resource Group | Auth mode |
|---|---|---|---|---|
pg-wasteology | PostgreSQL Flex | dev | wasteology_pg_dev | AAD + password |
billing-modernization-dev | PostgreSQL Flex | dev | bins-dev | password only (AAD off) |
pathfinder-dev | Azure SQL | dev | pathfinder_data_dev | SQL/AAD |
app-wasteology-prod | PostgreSQL Flex | prod | wasteology_pg_prod | AAD + password |
billing-modernization-prd | PostgreSQL Flex | prod | bins-prod | password only (AAD off) |
wasteology | Azure SQL | prod | invoice-automation | AAD + SQL (CieTrade source) |
wg-pg-orbit-prod | PostgreSQL Flex | orbit | orbit-rg-prod | AAD only (password off) — strongest posture |
AAD-admin servers are governed by roles managed through ops db; password-only servers (BINS) are governed entirely by native Postgres roles that are invisible to Azure RBAC. Auditing "who has access" therefore requires checking both layers.
Access Model
Azure access has two independent layers. A principal can hold one without the other, so both must be checked when auditing "who has access."
Control-plane (Azure RBAC)
Governs who can manage or read the Azure resource itself. Inherited from subscription/RG scope down to the resource. Query with ops azure access.
Standing grants across all three subscriptions:
ABS,CGreco,CGreco-ahold User Access Administrator (they can grant any role)ashullholds Ownerkgrayis User Access Administrator only on the Prodprefect-resourcesRG
Data-plane (database)
Governs who can actually connect and read/write rows. For AAD-enabled Postgres this is the server's Azure AD administrator(s) plus native Postgres role membership, managed through the DB Access Manager page and the ops db CLI.
Access-Request Runbook
The sanctioned paths to grant access. Prefer the tooling below over hand-editing in the Azure portal so every change is auditable and repeatable.
Grant database access
Use the ops db CLI (or the DB Access Manager page's edit mode, gated by DBACCESS_MUTATION_ALLOWLIST). Both target WASTE_PG_DEV (dev) by default; pass --conn WASTE_PG for prod.
ops db grant-schema <user> --schema <schema> --access read|readwrite # schema access
ops db add-to-role <user> --role wasteology_admin # role membership
ops db add-to-role <user> --role azure_pg_admin --conn WASTE_PG_DEV # DB admin (dev)
azure_pg_admin is a privilege escalationazure_pg_admin is Azure's managed-Postgres substitute for superuser — members manage roles, extensions, and all non-system objects. Grant it deliberately and reverse with remove-from-role.
Grant Azure RBAC
RBAC role assignments must be made by a User Access Administrator (ABS, CGreco) or an Owner (ashull).
kgray can grant only within the Prod prefect-resources RG without escalation. For anything else, request the grant from a UAA holder specifying:
- Principal — the user or service principal
- Role — the specific role definition
- Scope — the narrowest that works (resource > RG > subscription)
Provisioning New Resources
New Azure infrastructure is defined as code, not clicked together in the portal. The /infra Bicep path is the sanctioned route for compute; new projects follow the Claude Project Standard.
- Container Apps and supporting resources deploy via the
/infraBicep templates (infra/) intowdp-palantiri-rg. Always runwhat-ifbefore a prod deploy. - New projects follow the bootstrap: ADO repo →
CLAUDE.md→ skills → manifest registration. - Register every project in
manifests/builtin/<project>.tomlso digest and standup pick it up.
Service Principals & Managed Identities
The non-human identities that operate Wasteology infrastructure. List them live with ops azure identities; the entries below are the durable ownership notes and cleanup flags.
Managed identities (no secrets — preferred): wg-azure-infra-identity (ADO CI/CD), enevo-etl-identity, enevo-managed-identity, orbit-identity-{dev,prod,sandbox}, orbit-migrator-prod, bins-{dev,prd}-{mi,deployer}, deck-builder-identity, pathfinder-mi.
App-registration service principals (credential-based):
| SP | Purpose | Governance note |
|---|---|---|
prefect-workpool-sp | Spins ACI containers, ACR pull, KV secrets | Active |
CieTrade Pipeline Dev | CieTrade ETL DB auth; secret fetched at runtime from Key Vault | Valid to 2028-05; expired 2026-05 credential should be cleaned up |
DBTCloudServicePrincipal | dbt Cloud → pg-pathfinder | Active |
orbit-github-actions | Orbit CI/CD deploys (OIDC/federated, no secret) | Active |
PowerBI-MCP-Integration | Power BI integration | ⚠️ holds Contributor across the entire Dev subscription — scope down |
ach-remittance-sender | ACH remittance email flow | Valid to 2028-05 |
Two stale azure-cli-* / GUID-named SPs hold Contributor on the Prod invoice-automation RG (leftover ad-hoc az logins); pathfinder-ext-tables secrets expired 2024-11 (likely dead). Verify no dependencies, then remove.
Team Rollout & Ownership
How this model reaches the team and stays maintained: it is delivered through the four channels the team already uses, monitored by push rather than pull, and owned with a fixed review cadence.
The proliferation principle mirrors the rest of the platform — the team does not clone the operator hub or install the ops CLI. Governance surfaces where they already work: the published docs site, the wdp-palantiri dashboard, and Claude Code from any repo via a global agent.
Delivery channels
The four team-facing surfaces this reaches, and the phase each lands in. None require the team to run the ops azure CLI directly.
| Channel | Surface | Phase |
|---|---|---|
| Published docs page | Internal docs site — this Cloud Governance page + azure CLI page, auto-synced | 1 |
| Onboarding guide | ShareOnboardingGuide link opened in Claude Code — "how to run & manage" playbook | 1 |
| Global agent | azure-governance-auditor in wg-agent-infra — any teammate audits/grants/reports from any repo | 2 |
| Dashboard page | wdp-palantiri "Azure Governance" page (live inventory/cost/access) | 2 |
Monitoring
Monitoring must arrive uninvited, so it is push-based, not a dashboard someone must remember to open. Two mechanisms, both phase 2.
- Digest / Morning Brief — a weekly Azure cost + access section in
ops digest/standup, so totals and deltas land in the brief everyone reads. - Drift detection — a scheduled check that flags the risky changes: new service principals, credentials expiring within 30 days, and new User Access Administrator / Owner grants.
- Optional backstop — native Azure Cost Management budgets with email alerts per subscription catch spend spikes with zero code; not yet enabled.
Ownership & cadence
Governance decays without an owner and a schedule. The owner runs the cadence below and is the approver for the access-request runbook above.
| Item | Cadence | Owner |
|---|---|---|
| Cost review (via digest) | Weekly | Platform owner (kgray) |
| Access review (RBAC + DB roles) | Monthly | Platform owner |
| Service-principal & credential cleanup | Quarterly | Platform owner |
Rollout phases
Sequenced so visible value ships first and the heavier build follows.
- Phase 1 (fast wins): publish the docs page; ship the onboarding-guide link. Governance becomes readable and discoverable company-wide.
- Phase 2 (self-service + monitoring): build the
azure-governance-auditorglobal agent; add the digest cost/access section and drift detection; build the wdp-palantiri dashboard page.