{
  "description": "Auto-generated derived type for PostgresPolicyCandidateSpec via `CustomResource`",
  "properties": {
    "spec": {
      "description": "A one-shot, immutable proposal of policy content.\n\nThe operator plans a candidate in its parent policy's execution context and\npublishes a `PostgresPolicyPlan` for review; the active policy keeps\nenforcing throughout. A candidate never executes SQL in any state, and its\nspec cannot be edited — revising a proposal means creating a successor that\nnames the earlier one in `spec.replaces`.\n\nSee `docs/src/pages/docs/operator-candidates.md` for the behaviour and\n`docs/design/adr-001-candidate-api.md` for the API mechanics.",
      "properties": {
        "content": {
          "description": "The proposed policy content.",
          "properties": {
            "default_owner": {
              "description": "Default owner for ALTER DEFAULT PRIVILEGES (e.g. \"app_owner\").",
              "maxLength": 63,
              "minLength": 1,
              "nullable": true,
              "type": "string"
            },
            "default_privileges": {
              "description": "One-off default privileges.",
              "items": {
                "description": "Default privilege configuration.\n\nThe scope rules are also expressed as CEL so the API server rejects a bad\nentry at apply time. `resolved_scope` enforces the same rules for the CLI,\nwhich has no admission step.",
                "properties": {
                  "grant": {
                    "description": "Grantee, privileges, and future object kind to reconcile.",
                    "items": {
                      "description": "A single default privilege grant entry.",
                      "properties": {
                        "ensure": {
                          "description": "Desired privilege state: present grants it; absent explicitly revokes it.",
                          "enum": [
                            "present",
                            "absent"
                          ],
                          "type": "string"
                        },
                        "on_type": {
                          "description": "Kind of future object affected by the default privilege.",
                          "enum": [
                            "table",
                            "view",
                            "materialized_view",
                            "sequence",
                            "function",
                            "schema",
                            "database",
                            "type"
                          ],
                          "type": "string"
                        },
                        "privileges": {
                          "description": "PostgreSQL privileges to reconcile on the selected objects.",
                          "items": {
                            "description": "PostgreSQL privilege types.",
                            "enum": [
                              "SELECT",
                              "INSERT",
                              "UPDATE",
                              "DELETE",
                              "TRUNCATE",
                              "REFERENCES",
                              "TRIGGER",
                              "EXECUTE",
                              "USAGE",
                              "CREATE",
                              "CONNECT",
                              "TEMPORARY"
                            ],
                            "type": "string"
                          },
                          "maxItems": 16,
                          "minItems": 1,
                          "type": "array"
                        },
                        "role": {
                          "description": "The role receiving the default privilege. Only used in top-level default_privileges\n(in profiles, the role is determined by expansion). The exact-uppercase\nvalue `PUBLIC` means the PostgreSQL PUBLIC pseudo-role.",
                          "maxLength": 63,
                          "minLength": 1,
                          "nullable": true,
                          "type": "string"
                        }
                      },
                      "required": [
                        "on_type",
                        "privileges"
                      ],
                      "type": "object"
                    },
                    "maxItems": 64,
                    "type": "array"
                  },
                  "owner": {
                    "description": "The role that owns newly created objects. If omitted, uses manifest's default_owner.",
                    "maxLength": 63,
                    "minLength": 1,
                    "nullable": true,
                    "type": "string"
                  },
                  "schema": {
                    "description": "Schema shorthand, equivalent to `scope: {type: schema, schema: ...}`.\nExactly one of `schema` and `scope` must be set.",
                    "maxLength": 63,
                    "minLength": 1,
                    "nullable": true,
                    "type": "string"
                  },
                  "scope": {
                    "description": "Where the defaults apply: one schema, or owner-wide (global). Global\nscope renders `ALTER DEFAULT PRIVILEGES` without an `IN SCHEMA` clause.",
                    "nullable": true,
                    "properties": {
                      "schema": {
                        "description": "Schema name. Required for `type: schema`, forbidden for `type: global`.",
                        "maxLength": 63,
                        "minLength": 1,
                        "nullable": true,
                        "type": "string"
                      },
                      "type": {
                        "description": "Global or per-schema scope of the default privilege.",
                        "enum": [
                          "global",
                          "schema"
                        ],
                        "type": "string"
                      }
                    },
                    "required": [
                      "type"
                    ],
                    "type": "object",
                    "x-kubernetes-validations": [
                      {
                        "message": "`schema` is required when type is `schema` and forbidden when type is `global`",
                        "rule": "has(self.schema) == (self.type == 'schema')"
                      }
                    ]
                  }
                },
                "required": [
                  "grant"
                ],
                "type": "object",
                "x-kubernetes-validations": [
                  {
                    "message": "exactly one of `schema` and `scope` must be set",
                    "rule": "has(self.schema) != has(self.scope)"
                  }
                ]
              },
              "maxItems": 512,
              "type": "array"
            },
            "grants": {
              "description": "One-off grants.",
              "items": {
                "description": "A concrete grant on a specific object or wildcard.",
                "properties": {
                  "ensure": {
                    "description": "Desired object privilege state: present grants it; absent explicitly revokes it.",
                    "enum": [
                      "present",
                      "absent"
                    ],
                    "type": "string"
                  },
                  "object": {
                    "description": "Object kind and target to which the privileges apply.",
                    "properties": {
                      "name": {
                        "description": "Object name, or \"*\" for all objects. Omit for schema-level grants;\nrequired for database grants, where it names the connected database.",
                        "maxLength": 256,
                        "minLength": 1,
                        "nullable": true,
                        "type": "string"
                      },
                      "schema": {
                        "description": "Schema name. Required for most object types except database.",
                        "maxLength": 63,
                        "minLength": 1,
                        "nullable": true,
                        "type": "string"
                      },
                      "type": {
                        "description": "PostgreSQL object kind.",
                        "enum": [
                          "table",
                          "view",
                          "materialized_view",
                          "sequence",
                          "function",
                          "schema",
                          "database",
                          "type"
                        ],
                        "type": "string"
                      }
                    },
                    "required": [
                      "type"
                    ],
                    "type": "object",
                    "x-kubernetes-validations": [
                      {
                        "message": "database grant targets must set `name`",
                        "rule": "self.type != 'database' || has(self.name)"
                      }
                    ]
                  },
                  "privileges": {
                    "description": "PostgreSQL privileges to reconcile on the selected objects.",
                    "items": {
                      "description": "PostgreSQL privilege types.",
                      "enum": [
                        "SELECT",
                        "INSERT",
                        "UPDATE",
                        "DELETE",
                        "TRUNCATE",
                        "REFERENCES",
                        "TRIGGER",
                        "EXECUTE",
                        "USAGE",
                        "CREATE",
                        "CONNECT",
                        "TEMPORARY"
                      ],
                      "type": "string"
                    },
                    "maxItems": 16,
                    "minItems": 1,
                    "type": "array"
                  },
                  "role": {
                    "description": "The grantee. The exact-uppercase value `PUBLIC` means the PostgreSQL\nPUBLIC pseudo-role; any other value is an ordinary role name.",
                    "maxLength": 63,
                    "minLength": 1,
                    "type": "string"
                  }
                },
                "required": [
                  "object",
                  "privileges",
                  "role"
                ],
                "type": "object"
              },
              "maxItems": 4096,
              "type": "array"
            },
            "memberships": {
              "description": "Membership edges.",
              "items": {
                "description": "A membership declaration — which members belong to a role.",
                "properties": {
                  "exclusive": {
                    "description": "Assert that `members` is the complete membership of `role`: plan a\nREVOKE for any live member not listed here. Only meaningful for\npredefined (`pg_*`) and `external: true` roles, whose undeclared\nmembers are otherwise left untouched — memberships of ordinary managed\nroles are already reconciled exhaustively. Defaults to `false` so that\nadopting pgroles never strips provider-granted memberships (for\nexample `pg_monitor` grants made by a cloud platform) without an\nexplicit assertion.",
                    "type": "boolean"
                  },
                  "members": {
                    "description": "Roles that should receive this membership.",
                    "items": {
                      "description": "A single member of a role.\n\nBoth `inherit` and `admin` are optional. When omitted, they default to\n`inherit: true` and `admin: false` at resolution time (in `RoleGraph`\nconstruction). Keeping them optional in the CRD avoids Kubernetes\ninjecting default values into the stored resource, which causes\nperpetual diffs in GitOps tools like ArgoCD.",
                      "properties": {
                        "admin": {
                          "description": "Whether the member can administer the role. Defaults to `false`.",
                          "nullable": true,
                          "type": "boolean"
                        },
                        "inherit": {
                          "description": "Whether the member inherits the role's privileges. Defaults to `true`.",
                          "nullable": true,
                          "type": "boolean"
                        },
                        "name": {
                          "description": "PostgreSQL role receiving the membership.",
                          "maxLength": 63,
                          "minLength": 1,
                          "type": "string"
                        }
                      },
                      "required": [
                        "name"
                      ],
                      "type": "object"
                    },
                    "maxItems": 512,
                    "type": "array"
                  },
                  "role": {
                    "description": "PostgreSQL role granted to the listed members.",
                    "maxLength": 63,
                    "minLength": 1,
                    "type": "string"
                  }
                },
                "required": [
                  "members",
                  "role"
                ],
                "type": "object"
              },
              "maxItems": 2048,
              "type": "array"
            },
            "profiles": {
              "additionalProperties": {
                "description": "A reusable privilege profile.",
                "properties": {
                  "config": {
                    "additionalProperties": {
                      "description": "A role configuration parameter value.\n\nValues are always strings — quote numbers and booleans (e.g.\n`statement_timeout: \"30000\"`, `jit: \"off\"`). The Kubernetes CRD schema\ntypes config values as strings, and the CLI enforces the same rule so a\nmanifest means the same thing whether it is applied with `pgroles` or\n`kubectl`. PostgreSQL coerces the string to the parameter's type.",
                      "maxLength": 256,
                      "type": "string"
                    },
                    "description": "Role-level configuration parameter defaults for generated roles,\napplied via `ALTER ROLE ... SET parameter = value`. Values support the\n`{schema}` and `{profile}` placeholders, substituted per `schema x\nprofile` expansion (e.g. `search_path: \"{schema}\"`).",
                    "maxProperties": 32,
                    "type": "object"
                  },
                  "default_privileges": {
                    "description": "Privileges to grant on future objects created by the configured owner.",
                    "items": {
                      "description": "Default privilege grant within a profile.",
                      "properties": {
                        "ensure": {
                          "description": "Whether the privilege must be present or absent. Matches the\ntop-level `default_privileges` entries, which carry the same field.",
                          "enum": [
                            "present",
                            "absent"
                          ],
                          "type": "string"
                        },
                        "on_type": {
                          "description": "Kind of future object affected by the default privilege.",
                          "enum": [
                            "table",
                            "view",
                            "materialized_view",
                            "sequence",
                            "function",
                            "schema",
                            "database",
                            "type"
                          ],
                          "type": "string"
                        },
                        "privileges": {
                          "description": "PostgreSQL privileges to reconcile on the selected objects.",
                          "items": {
                            "description": "PostgreSQL privilege types.",
                            "enum": [
                              "SELECT",
                              "INSERT",
                              "UPDATE",
                              "DELETE",
                              "TRUNCATE",
                              "REFERENCES",
                              "TRIGGER",
                              "EXECUTE",
                              "USAGE",
                              "CREATE",
                              "CONNECT",
                              "TEMPORARY"
                            ],
                            "type": "string"
                          },
                          "maxItems": 16,
                          "minItems": 1,
                          "type": "array"
                        },
                        "role": {
                          "description": "Grantee role; omitted values use the generated profile role.",
                          "maxLength": 63,
                          "minLength": 1,
                          "nullable": true,
                          "type": "string"
                        }
                      },
                      "required": [
                        "on_type",
                        "privileges"
                      ],
                      "type": "object"
                    },
                    "maxItems": 32,
                    "type": "array"
                  },
                  "grants": {
                    "description": "Object privilege templates expanded for each bound schema.",
                    "items": {
                      "description": "Grant template within a profile.",
                      "properties": {
                        "ensure": {
                          "description": "Whether the privilege must be present or absent. Matches the top-level\n`grants` entries, which carry the same field. Profiles are additive\ntemplates, so validation rejects `absent`; the schema accepts it so the\nAPI server does not prune the value before that check can name it.",
                          "enum": [
                            "present",
                            "absent"
                          ],
                          "type": "string"
                        },
                        "object": {
                          "description": "Object kind and target to which the privileges apply.",
                          "properties": {
                            "name": {
                              "description": "Object name; omission selects the object-kind scope supported by the profile.",
                              "maxLength": 256,
                              "minLength": 1,
                              "nullable": true,
                              "type": "string"
                            },
                            "type": {
                              "description": "PostgreSQL object kind.",
                              "enum": [
                                "table",
                                "view",
                                "materialized_view",
                                "sequence",
                                "function",
                                "schema",
                                "database",
                                "type"
                              ],
                              "type": "string"
                            }
                          },
                          "required": [
                            "type"
                          ],
                          "type": "object"
                        },
                        "privileges": {
                          "description": "PostgreSQL privileges to reconcile on the selected objects.",
                          "items": {
                            "description": "PostgreSQL privilege types.",
                            "enum": [
                              "SELECT",
                              "INSERT",
                              "UPDATE",
                              "DELETE",
                              "TRUNCATE",
                              "REFERENCES",
                              "TRIGGER",
                              "EXECUTE",
                              "USAGE",
                              "CREATE",
                              "CONNECT",
                              "TEMPORARY"
                            ],
                            "type": "string"
                          },
                          "maxItems": 16,
                          "minItems": 1,
                          "type": "array"
                        }
                      },
                      "required": [
                        "object",
                        "privileges"
                      ],
                      "type": "object"
                    },
                    "maxItems": 64,
                    "type": "array"
                  },
                  "inherit": {
                    "description": "Whether privileges from role memberships are inherited automatically.",
                    "nullable": true,
                    "type": "boolean"
                  },
                  "login": {
                    "description": "Whether the role may initiate database sessions.",
                    "nullable": true,
                    "type": "boolean"
                  }
                },
                "type": "object"
              },
              "description": "Reusable privilege profiles.\n\nA `BTreeMap` rather than the policy's `HashMap`: the content digest is\ncomputed over a canonical serialization, and deterministic iteration\norder is one less thing that has to be normalised later.",
              "maxProperties": 128,
              "type": "object"
            },
            "reconciliation_mode": {
              "description": "Convergence strategy: how aggressively to converge the database.",
              "enum": [
                "authoritative",
                "additive",
                "adopt"
              ],
              "type": "string"
            },
            "retirements": {
              "description": "Explicit role-retirement workflows for roles that should be removed.",
              "items": {
                "description": "Declarative workflow for retiring an existing role.",
                "properties": {
                  "drop_owned": {
                    "description": "Whether to run `DROP OWNED BY` before dropping the role.",
                    "type": "boolean"
                  },
                  "reassign_owned_to": {
                    "description": "Optional successor role for `REASSIGN OWNED BY ... TO ...`.",
                    "maxLength": 63,
                    "minLength": 1,
                    "nullable": true,
                    "type": "string"
                  },
                  "role": {
                    "description": "The role to retire and ultimately drop.",
                    "maxLength": 63,
                    "minLength": 1,
                    "type": "string"
                  },
                  "terminate_sessions": {
                    "description": "Whether to terminate other active sessions for the role before drop.",
                    "type": "boolean"
                  }
                },
                "required": [
                  "role"
                ],
                "type": "object"
              },
              "maxItems": 512,
              "type": "array"
            },
            "role_pattern": {
              "description": "Default role naming pattern. Schema bindings can override it. Supports `{schema}` and requires `{profile}`; falls back to `{schema}-{profile}`.",
              "maxLength": 128,
              "minLength": 1,
              "nullable": true,
              "type": "string"
            },
            "roles": {
              "description": "One-off role definitions.",
              "items": {
                "description": "A concrete PostgreSQL role definition.",
                "properties": {
                  "bypassrls": {
                    "description": "Whether the role bypasses row-level security.",
                    "nullable": true,
                    "type": "boolean"
                  },
                  "comment": {
                    "description": "Descriptive PostgreSQL role comment.",
                    "maxLength": 256,
                    "nullable": true,
                    "type": "string"
                  },
                  "config": {
                    "additionalProperties": {
                      "description": "A role configuration parameter value.\n\nValues are always strings — quote numbers and booleans (e.g.\n`statement_timeout: \"30000\"`, `jit: \"off\"`). The Kubernetes CRD schema\ntypes config values as strings, and the CLI enforces the same rule so a\nmanifest means the same thing whether it is applied with `pgroles` or\n`kubectl`. PostgreSQL coerces the string to the parameter's type.",
                      "maxLength": 256,
                      "type": "string"
                    },
                    "description": "Role-level configuration parameter defaults, applied via\n`ALTER ROLE ... SET parameter = value` (e.g. `role: combined`,\n`search_path: app`). Settings present on the role in the database but\nabsent here are RESET in authoritative mode.",
                    "maxProperties": 32,
                    "type": "object"
                  },
                  "connection_limit": {
                    "description": "Maximum concurrent connections for the role; -1 means unlimited.",
                    "format": "int32",
                    "nullable": true,
                    "type": "integer"
                  },
                  "createdb": {
                    "description": "Whether the role may create databases.",
                    "nullable": true,
                    "type": "boolean"
                  },
                  "createrole": {
                    "description": "Whether the role may create and administer roles, subject to server-version rules.",
                    "nullable": true,
                    "type": "boolean"
                  },
                  "external": {
                    "description": "Treat this role as externally managed. The operator may reference it in\ngrants, ownership, and memberships, but will not create, alter, drop,\nor password-manage it. Declared membership edges remain managed.",
                    "type": "boolean"
                  },
                  "inherit": {
                    "description": "Whether privileges from role memberships are inherited automatically.",
                    "nullable": true,
                    "type": "boolean"
                  },
                  "login": {
                    "description": "Whether the role may initiate database sessions.",
                    "nullable": true,
                    "type": "boolean"
                  },
                  "name": {
                    "description": "PostgreSQL role name.",
                    "maxLength": 63,
                    "minLength": 1,
                    "type": "string"
                  },
                  "password": {
                    "description": "Password source for this role. Either a reference to an existing Secret\nor a request for the operator to generate one.",
                    "nullable": true,
                    "properties": {
                      "generate": {
                        "description": "Generate a random password and store it in a new Kubernetes Secret.\nMutually exclusive with `secretRef`.",
                        "nullable": true,
                        "properties": {
                          "length": {
                            "description": "Password length. Defaults to 32. Minimum 16, maximum 128.",
                            "format": "uint32",
                            "minimum": 0.0,
                            "nullable": true,
                            "type": "integer"
                          },
                          "secretKey": {
                            "description": "Key within the generated Secret. Defaults to `password`.",
                            "maxLength": 253,
                            "minLength": 1,
                            "nullable": true,
                            "type": "string"
                          },
                          "secretName": {
                            "description": "Override the generated Secret name. Defaults to `{policy}-pgr-{role}`.",
                            "maxLength": 253,
                            "minLength": 1,
                            "nullable": true,
                            "type": "string"
                          }
                        },
                        "type": "object"
                      },
                      "secretKey": {
                        "description": "Key within the referenced Secret. Defaults to the role name.\nOnly used with `secretRef`.",
                        "maxLength": 253,
                        "minLength": 1,
                        "nullable": true,
                        "type": "string"
                      },
                      "secretRef": {
                        "description": "Reference to an existing Kubernetes Secret containing the password.\nMutually exclusive with `generate`.",
                        "nullable": true,
                        "properties": {
                          "name": {
                            "description": "Name of the Secret.",
                            "maxLength": 253,
                            "minLength": 1,
                            "type": "string"
                          }
                        },
                        "required": [
                          "name"
                        ],
                        "type": "object"
                      }
                    },
                    "type": "object"
                  },
                  "password_valid_until": {
                    "description": "Password expiration timestamp (ISO 8601, e.g. \"2025-12-31T00:00:00Z\").",
                    "maxLength": 64,
                    "nullable": true,
                    "type": "string"
                  },
                  "preserve_undeclared_grants": {
                    "description": "Preserve this role's undeclared in-scope object grants during\nconvergence. Revokes against the role are skipped unless the revoked\nprivileges are explicitly asserted absent (`ensure: absent`).",
                    "type": "boolean"
                  },
                  "replication": {
                    "description": "Whether the role may initiate replication connections.",
                    "nullable": true,
                    "type": "boolean"
                  },
                  "superuser": {
                    "description": "Whether the role bypasses PostgreSQL permission checks as a superuser.",
                    "nullable": true,
                    "type": "boolean"
                  }
                },
                "required": [
                  "name"
                ],
                "type": "object"
              },
              "maxItems": 1024,
              "type": "array"
            },
            "schemas": {
              "description": "Schema bindings that expand profiles into concrete roles/grants.",
              "items": {
                "description": "Associates a PostgreSQL schema with one or more reusable privilege profiles.",
                "properties": {
                  "name": {
                    "description": "PostgreSQL schema name.",
                    "maxLength": 63,
                    "minLength": 1,
                    "type": "string"
                  },
                  "owner": {
                    "description": "Override default_owner for this schema's default privileges.",
                    "maxLength": 63,
                    "minLength": 1,
                    "nullable": true,
                    "type": "string"
                  },
                  "profiles": {
                    "description": "Profile names to expand for this schema.",
                    "items": {
                      "maxLength": 63,
                      "minLength": 1,
                      "type": "string"
                    },
                    "maxItems": 64,
                    "type": "array"
                  },
                  "role_pattern": {
                    "description": "Role naming pattern. Supports `{schema}` and `{profile}` placeholders.\nOverrides the policy pattern; otherwise inherits it, falling back to `\"{schema}-{profile}\"`.",
                    "maxLength": 128,
                    "minLength": 1,
                    "nullable": true,
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ],
                "type": "object"
              },
              "maxItems": 1024,
              "type": "array"
            }
          },
          "type": "object"
        },
        "policyRef": {
          "description": "The `PostgresPolicy` this candidate proposes content for. Resolved in\nthe candidate's own namespace: an owner reference cannot cross\nnamespaces, so neither can this.",
          "properties": {
            "name": {
              "description": "Name of the referenced resource in the same namespace.",
              "maxLength": 253,
              "minLength": 1,
              "type": "string"
            }
          },
          "required": [
            "name"
          ],
          "type": "object"
        },
        "replaces": {
          "description": "Name of an earlier candidate this one supersedes.\n\nSupersession is always explicit. The operator never infers it from\ncreator identity, because CI typically files every team's candidates\nunder one service account.",
          "maxLength": 253,
          "minLength": 1,
          "nullable": true,
          "type": "string"
        },
        "target": {
          "description": "Preview the content against a different connection than the parent\npolicy's. Credentials, locking and the plan's bound target identity all\nfollow the override, which is why such a plan is a preview and never a\nmigration step.",
          "nullable": true,
          "properties": {
            "connectionRef": {
              "description": "Connection information for the candidate evaluation target.",
              "properties": {
                "key": {
                  "description": "Key within the Secret holding the connection URL.",
                  "maxLength": 253,
                  "minLength": 1,
                  "type": "string"
                },
                "secretName": {
                  "description": "Name of the Secret in the candidate's namespace.",
                  "maxLength": 253,
                  "minLength": 1,
                  "type": "string"
                }
              },
              "required": [
                "key",
                "secretName"
              ],
              "type": "object"
            }
          },
          "required": [
            "connectionRef"
          ],
          "type": "object"
        }
      },
      "required": [
        "content",
        "policyRef"
      ],
      "type": "object",
      "x-kubernetes-validations": [
        {
          "message": "candidate spec is immutable",
          "rule": "self == oldSelf"
        }
      ]
    },
    "status": {
      "description": "Status of a `PostgresPolicyCandidate`.\n\n`phase` is a printable summary; conditions are the source of truth.",
      "nullable": true,
      "properties": {
        "conditions": {
          "default": [],
          "description": "Controller observations about candidate validity, planning, approval, and promotion.",
          "items": {
            "description": "A condition on the `PostgresPolicy` resource.",
            "properties": {
              "last_transition_time": {
                "description": "Last time the condition transitioned.",
                "nullable": true,
                "type": "string"
              },
              "message": {
                "description": "Human-readable message.",
                "nullable": true,
                "type": "string"
              },
              "reason": {
                "description": "Human-readable reason for the condition.",
                "nullable": true,
                "type": "string"
              },
              "status": {
                "description": "Status: \"True\", \"False\", or \"Unknown\".",
                "type": "string"
              },
              "type": {
                "description": "Controller-defined condition type, such as Ready, Reconciling, or Degraded.\nThis is an open vocabulary; consult status guidance for operational meanings.",
                "type": "string"
              }
            },
            "required": [
              "status",
              "type"
            ],
            "type": "object"
          },
          "maxItems": 16,
          "type": "array"
        },
        "contentDigest": {
          "description": "Canonical digest of `spec.content`, computed by\n`pgroles_core::candidate::compute_content_digest`. This is what\npromotion is verified against.",
          "maxLength": 128,
          "nullable": true,
          "type": "string"
        },
        "observedGeneration": {
          "description": "The `.metadata.generation` that was last observed. A candidate spec is\nimmutable, so this advances at most once.",
          "format": "int64",
          "nullable": true,
          "type": "integer"
        },
        "phase": {
          "default": "Pending",
          "description": "Current candidate evaluation and promotion phase.",
          "enum": [
            "Pending",
            "Planned",
            "Promoted",
            "Superseded",
            "Stale"
          ],
          "type": "string"
        },
        "planRef": {
          "description": "The `PostgresPolicyPlan` produced for this candidate.",
          "nullable": true,
          "properties": {
            "name": {
              "description": "Name of the PostgresPolicyPlan in the same namespace.",
              "type": "string"
            }
          },
          "required": [
            "name"
          ],
          "type": "object"
        }
      },
      "type": "object"
    }
  },
  "required": [
    "spec"
  ],
  "title": "PostgresPolicyCandidate",
  "type": "object"
}
