{
  "description": "GarageBucket is the Schema for the garagebuckets API",
  "properties": {
    "apiVersion": {
      "description": "APIVersion defines the versioned schema of this representation of an object.\nServers should convert recognized schemas to the latest internal value, and\nmay reject unrecognized values.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
      "type": "string"
    },
    "kind": {
      "description": "Kind is a string value representing the REST resource this object represents.\nServers may infer this from the endpoint the client submits requests to.\nCannot be updated.\nIn CamelCase.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
      "type": "string"
    },
    "metadata": {
      "type": "object"
    },
    "spec": {
      "description": "GarageBucketSpec defines the desired state of GarageBucket",
      "properties": {
        "clusterRef": {
          "description": "ClusterRef references the GarageCluster this bucket belongs to",
          "properties": {
            "kubeConfigSecretRef": {
              "description": "KubeConfigSecretRef references a secret containing kubeconfig for a remote cluster.\nOnly used for cross-cluster references in multi-cluster federation scenarios.",
              "properties": {
                "key": {
                  "description": "The key of the secret to select from.  Must be a valid secret key.",
                  "type": "string"
                },
                "name": {
                  "default": "",
                  "description": "Name of the referent.\nThis field is effectively required, but due to backwards compatibility is\nallowed to be empty. Instances of this type with an empty value here are\nalmost certainly wrong.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names",
                  "type": "string"
                },
                "optional": {
                  "description": "Specify whether the Secret or its key must be defined",
                  "type": "boolean"
                }
              },
              "required": [
                "key"
              ],
              "type": "object",
              "x-kubernetes-map-type": "atomic",
              "additionalProperties": false
            },
            "name": {
              "description": "Name of the GarageCluster",
              "type": "string"
            },
            "namespace": {
              "description": "Namespace of the GarageCluster (defaults to the same namespace as the referencing resource)",
              "type": "string"
            }
          },
          "required": [
            "name"
          ],
          "type": "object",
          "additionalProperties": false
        },
        "globalAlias": {
          "description": "GlobalAlias is the global alias for this bucket (optional)\nIf not set, the bucket name from metadata.name is used",
          "type": "string"
        },
        "keyPermissions": {
          "description": "KeyPermissions grants access to specific GarageKeys.\n\nNote: Permissions can be granted from either direction:\n- Here (GarageBucket.keyPermissions): Grant keys access to this bucket\n- On GarageKey (GarageKey.bucketPermissions): Grant the key access to buckets\n\nBoth approaches are equivalent and result in the same Garage API calls.\nUse whichever is more convenient for your workflow:\n- Bucket-centric: Define all key access on the bucket\n- Key-centric: Define all bucket access on the key\n\nIf the same permission is defined in both places, they are merged (not conflicting).",
          "items": {
            "description": "KeyPermission grants access to a key",
            "properties": {
              "keyRef": {
                "description": "KeyRef references the GarageKey by name",
                "type": "string"
              },
              "owner": {
                "description": "Owner allows bucket owner operations",
                "type": "boolean"
              },
              "read": {
                "description": "Read allows reading objects",
                "type": "boolean"
              },
              "write": {
                "description": "Write allows writing objects",
                "type": "boolean"
              }
            },
            "required": [
              "keyRef"
            ],
            "type": "object",
            "additionalProperties": false
          },
          "type": "array"
        },
        "localAliases": {
          "description": "LocalAliases are per-key local aliases for this bucket",
          "items": {
            "description": "LocalAlias represents a per-key local alias for a bucket",
            "properties": {
              "alias": {
                "description": "Alias is the local alias name",
                "type": "string"
              },
              "keyRef": {
                "description": "KeyRef references the GarageKey",
                "type": "string"
              }
            },
            "required": [
              "alias",
              "keyRef"
            ],
            "type": "object",
            "additionalProperties": false
          },
          "type": "array"
        },
        "quotas": {
          "description": "Quotas configures bucket quotas",
          "properties": {
            "maxObjects": {
              "description": "MaxObjects is the maximum number of objects",
              "format": "int64",
              "type": "integer"
            },
            "maxSize": {
              "anyOf": [
                {
                  "type": "integer"
                },
                {
                  "type": "string"
                }
              ],
              "description": "MaxSize is the maximum bucket size in bytes",
              "pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
              "x-kubernetes-int-or-string": true
            }
          },
          "type": "object",
          "additionalProperties": false
        },
        "website": {
          "description": "Website configures static website hosting for this bucket.\nNote: Only indexDocument and errorDocument are supported via the Admin API.\nFor advanced features (routing rules, redirectAll), use S3 PutBucketWebsite API directly.",
          "properties": {
            "enabled": {
              "description": "Enabled enables static website hosting",
              "type": "boolean"
            },
            "errorDocument": {
              "description": "ErrorDocument is the error document to serve for 404s",
              "type": "string"
            },
            "indexDocument": {
              "default": "index.html",
              "description": "IndexDocument is the default index document (default: index.html)",
              "type": "string"
            }
          },
          "type": "object",
          "additionalProperties": false
        }
      },
      "required": [
        "clusterRef"
      ],
      "type": "object",
      "additionalProperties": false
    },
    "status": {
      "description": "GarageBucketStatus defines the observed state of GarageBucket",
      "properties": {
        "bucketId": {
          "description": "BucketID is the internal Garage bucket ID",
          "type": "string"
        },
        "conditions": {
          "description": "Conditions represent the current state",
          "items": {
            "description": "Condition contains details for one aspect of the current state of this API Resource.",
            "properties": {
              "lastTransitionTime": {
                "description": "lastTransitionTime is the last time the condition transitioned from one status to another.\nThis should be when the underlying condition changed.  If that is not known, then using the time when the API field changed is acceptable.",
                "format": "date-time",
                "type": "string"
              },
              "message": {
                "description": "message is a human readable message indicating details about the transition.\nThis may be an empty string.",
                "maxLength": 32768,
                "type": "string"
              },
              "observedGeneration": {
                "description": "observedGeneration represents the .metadata.generation that the condition was set based upon.\nFor instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date\nwith respect to the current state of the instance.",
                "format": "int64",
                "minimum": 0,
                "type": "integer"
              },
              "reason": {
                "description": "reason contains a programmatic identifier indicating the reason for the condition's last transition.\nProducers of specific condition types may define expected values and meanings for this field,\nand whether the values are considered a guaranteed API.\nThe value should be a CamelCase string.\nThis field may not be empty.",
                "maxLength": 1024,
                "minLength": 1,
                "pattern": "^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$",
                "type": "string"
              },
              "status": {
                "description": "status of the condition, one of True, False, Unknown.",
                "enum": [
                  "True",
                  "False",
                  "Unknown"
                ],
                "type": "string"
              },
              "type": {
                "description": "type of condition in CamelCase or in foo.example.com/CamelCase.",
                "maxLength": 316,
                "pattern": "^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$",
                "type": "string"
              }
            },
            "required": [
              "lastTransitionTime",
              "message",
              "reason",
              "status",
              "type"
            ],
            "type": "object",
            "additionalProperties": false
          },
          "type": "array",
          "x-kubernetes-list-map-keys": [
            "type"
          ],
          "x-kubernetes-list-type": "map"
        },
        "createdAt": {
          "description": "CreatedAt is when the bucket was created in Garage",
          "format": "date-time",
          "type": "string"
        },
        "globalAlias": {
          "description": "GlobalAlias is the assigned global alias",
          "type": "string"
        },
        "incompleteUploadBytes": {
          "description": "IncompleteUploadBytes is the total bytes in incomplete multipart uploads",
          "format": "int64",
          "type": "integer"
        },
        "incompleteUploadParts": {
          "description": "IncompleteUploadParts is the count of parts in incomplete multipart uploads",
          "format": "int64",
          "type": "integer"
        },
        "incompleteUploads": {
          "description": "IncompleteUploads is the count of incomplete multipart uploads",
          "format": "int64",
          "type": "integer"
        },
        "keys": {
          "description": "Keys contains keys with access to this bucket",
          "items": {
            "description": "BucketKeyStatus shows key access status",
            "properties": {
              "keyId": {
                "description": "KeyID is the access key ID",
                "type": "string"
              },
              "name": {
                "description": "Name is the key name",
                "type": "string"
              },
              "permissions": {
                "description": "Permissions granted to this key",
                "properties": {
                  "owner": {
                    "description": "Owner permission",
                    "type": "boolean"
                  },
                  "read": {
                    "description": "Read permission",
                    "type": "boolean"
                  },
                  "write": {
                    "description": "Write permission",
                    "type": "boolean"
                  }
                },
                "type": "object",
                "additionalProperties": false
              }
            },
            "type": "object",
            "additionalProperties": false
          },
          "type": "array"
        },
        "localAliases": {
          "description": "LocalAliases tracks per-key local aliases for this bucket",
          "items": {
            "description": "LocalAliasStatus shows the status of a local alias for this bucket",
            "properties": {
              "alias": {
                "description": "Alias is the local alias name",
                "type": "string"
              },
              "keyId": {
                "description": "KeyID is the access key ID that owns this alias",
                "type": "string"
              },
              "keyName": {
                "description": "KeyName is the friendly name of the key",
                "type": "string"
              }
            },
            "type": "object",
            "additionalProperties": false
          },
          "type": "array"
        },
        "objectCount": {
          "description": "ObjectCount is the current object count",
          "format": "int64",
          "type": "integer"
        },
        "observedGeneration": {
          "description": "ObservedGeneration is the last observed generation",
          "format": "int64",
          "type": "integer"
        },
        "phase": {
          "description": "Phase represents the current phase",
          "type": "string"
        },
        "quotaUsage": {
          "description": "QuotaUsage shows current quota consumption",
          "properties": {
            "objectCount": {
              "description": "ObjectCount is the current object count",
              "format": "int64",
              "type": "integer"
            },
            "objectLimit": {
              "description": "ObjectLimit is the configured object limit (0 = unlimited)",
              "format": "int64",
              "type": "integer"
            },
            "objectPercent": {
              "description": "ObjectPercent is the percentage of object quota used",
              "format": "int32",
              "type": "integer"
            },
            "sizeBytes": {
              "description": "SizeBytes is the current size in bytes",
              "format": "int64",
              "type": "integer"
            },
            "sizeLimit": {
              "description": "SizeLimit is the configured size limit in bytes (0 = unlimited)",
              "format": "int64",
              "type": "integer"
            },
            "sizePercent": {
              "description": "SizePercent is the percentage of size quota used",
              "format": "int32",
              "type": "integer"
            }
          },
          "type": "object",
          "additionalProperties": false
        },
        "size": {
          "description": "Size is the current bucket size",
          "type": "string"
        },
        "websiteConfig": {
          "description": "WebsiteConfig shows the current website configuration details",
          "properties": {
            "errorDocument": {
              "description": "ErrorDocument is the configured error document",
              "type": "string"
            },
            "indexDocument": {
              "description": "IndexDocument is the configured index document",
              "type": "string"
            }
          },
          "type": "object",
          "additionalProperties": false
        },
        "websiteEnabled": {
          "description": "WebsiteEnabled indicates if website hosting is currently enabled",
          "type": "boolean"
        },
        "websiteUrl": {
          "description": "WebsiteURL is the computed website URL (if website hosting is enabled)",
          "type": "string"
        }
      },
      "type": "object",
      "additionalProperties": false
    }
  },
  "required": [
    "spec"
  ],
  "type": "object"
}
