diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index d3f3493c..00bf3c3a 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -136,7 +136,7 @@ jobs: strategy: fail-fast: false matrix: - version: ["1.32.27", "1.33.18", "1.34.20", "1.35.16", "1.36.10", "1.37.5-e0fe0d5.amd64"] + version: ["1.32.27", "1.33.18", "1.34.20", "1.35.23", "1.36.21", "1.37.12", "1.38.4"] uses: ./.github/workflows/test-on-weaviate-version.yml secrets: inherit with: diff --git a/src/Weaviate.Client.Tests/Integration/TestCollections.cs b/src/Weaviate.Client.Tests/Integration/TestCollections.cs index f66f7694..b81b6953 100644 --- a/src/Weaviate.Client.Tests/Integration/TestCollections.cs +++ b/src/Weaviate.Client.Tests/Integration/TestCollections.cs @@ -126,6 +126,13 @@ public async Task Test_Collections_Export_Cases(string key) var expected = CollectionConfig.FromCollectionCreate(c); + if (ServerVersionIsInRange("1.38.0") && expected.ReplicationConfig is not null) + { + // Weaviate 1.38 removed the per-collection asyncEnabled setting: the server + // derives it as `factor > 1` and ignores the value sent at creation. + expected.ReplicationConfig.AsyncEnabled = expected.ReplicationConfig.Factor > 1; + } + Assert.Equal(expected, export); } #endif @@ -404,7 +411,16 @@ public async Task Test_Collections_Export_NonDefaultValues_Sharding() // ReplicationConfig validation Assert.NotNull(export.ReplicationConfig); - Assert.True(export.ReplicationConfig.AsyncEnabled); + if (ServerVersionIsInRange("1.38.0")) + { + // Weaviate 1.38 removed the per-collection asyncEnabled setting: the server + // derives it as `factor > 1` (factor is 1 here) and ignores the value sent. + Assert.False(export.ReplicationConfig.AsyncEnabled); + } + else + { + Assert.True(export.ReplicationConfig.AsyncEnabled); + } Assert.True( new[] { @@ -561,7 +577,16 @@ public async Task Test_Collections_Export_NonDefaultValues_MultiTenacy() // ReplicationConfig validation Assert.NotNull(export.ReplicationConfig); - Assert.True(export.ReplicationConfig.AsyncEnabled); + if (ServerVersionIsInRange("1.38.0")) + { + // Weaviate 1.38 removed the per-collection asyncEnabled setting: the server + // derives it as `factor > 1` (factor is 1 here) and ignores the value sent. + Assert.False(export.ReplicationConfig.AsyncEnabled); + } + else + { + Assert.True(export.ReplicationConfig.AsyncEnabled); + } Assert.True( new[] { diff --git a/src/Weaviate.Client.Tests/Integration/TestRbacRoles.cs b/src/Weaviate.Client.Tests/Integration/TestRbacRoles.cs index 6a0d0d78..517160c9 100644 --- a/src/Weaviate.Client.Tests/Integration/TestRbacRoles.cs +++ b/src/Weaviate.Client.Tests/Integration/TestRbacRoles.cs @@ -574,4 +574,44 @@ public async Task CreateRoleWithMcpPermission() await _weaviate.Roles.Delete(roleName, TestContext.Current.CancellationToken); } } + + /// + /// Tests that create role with namespaces permission round trips (Weaviate 1.38+) + /// + [Fact] + public async Task CreateRoleWithNamespacesPermission() + { + RequireVersion("1.38.0"); + var roleName = MakeRoleName("namespaces"); + try + { + await _weaviate.Roles.Delete(roleName, TestContext.Current.CancellationToken); + var created = await _weaviate.Roles.Create( + roleName, + [new Permissions.Namespaces("*") { Manage = true }], + TestContext.Current.CancellationToken + ); + Assert.NotNull(created); + Assert.Equal(roleName, created.Name); + Assert.Single(created.Permissions); + var scope = Assert.IsType(created.Permissions.Single()); + Assert.True(scope.Manage); + Assert.Equal("*", scope.Resource.Namespace); + + var fetched = await _weaviate.Roles.Get( + roleName, + TestContext.Current.CancellationToken + ); + Assert.NotNull(fetched); + Assert.Equal(roleName, fetched!.Name); + Assert.Single(fetched.Permissions); + var fetchedScope = Assert.IsType(fetched.Permissions.Single()); + Assert.True(fetchedScope.Manage); + Assert.Equal("*", fetchedScope.Resource.Namespace); + } + finally + { + await _weaviate.Roles.Delete(roleName, TestContext.Current.CancellationToken); + } + } } diff --git a/src/Weaviate.Client.Tests/Unit/PermissionsScopeTests.cs b/src/Weaviate.Client.Tests/Unit/PermissionsScopeTests.cs index 02d78508..ca789d7e 100644 --- a/src/Weaviate.Client.Tests/Unit/PermissionsScopeTests.cs +++ b/src/Weaviate.Client.Tests/Unit/PermissionsScopeTests.cs @@ -389,6 +389,54 @@ public void Backups_Aggregates_ManageBackupsOnly() Assert.True(backups[0].Manage); } + /// + /// Tests that namespaces aggregates manage namespaces only (Weaviate 1.38+) + /// + [Fact] + public void Namespaces_Aggregates_ManageNamespacesOnly() + { + var resource = new Rest.Dto.Namespaces { Namespace = "ns-.*" }; + var permissions = new List + { + new() + { + Action = Weaviate.Client.Rest.Dto.PermissionAction.Manage_namespaces, + Namespaces = resource, + }, + }; + var namespaces = Permissions + .Namespaces.Parse(permissions) + .Cast() + .ToList(); + Assert.Single(namespaces); + Assert.True(namespaces[0].Manage); + Assert.Equal("ns-.*", namespaces[0].Resource.Namespace); + } + + /// + /// Tests that namespaces round trips through the dto (Weaviate 1.38+) + /// + [Fact] + public void Namespaces_ToDto_RoundTrips() + { + var scope = new Permissions.Namespaces("team-a") { Manage = true }; + + var dtos = scope.ToDto().ToList(); + + var dto = Assert.Single(dtos); + Assert.Equal(Weaviate.Client.Rest.Dto.PermissionAction.Manage_namespaces, dto.Action); + Assert.NotNull(dto.Namespaces); + Assert.Equal("team-a", dto.Namespaces!.Namespace); + + var parsed = Assert.Single(Permissions.Namespaces.Parse(dtos)); + var roundTripped = Assert.IsType(parsed); + Assert.True(roundTripped.Manage); + Assert.Equal("team-a", roundTripped.Resource.Namespace); + + // No actions set -> no permission entries are emitted. + Assert.Empty(new Permissions.Namespaces("team-a").ToDto()); + } + /// /// Tests that all permission actions are mentioned /// @@ -411,6 +459,7 @@ public void AllPermissionActions_AreMentioned() var testedActions = new HashSet { "Manage_backups", + "Manage_namespaces", "Read_cluster", "Create_data", "Read_data", diff --git a/src/Weaviate.Client/Models/PermissionResource.cs b/src/Weaviate.Client/Models/PermissionResource.cs index e74d1948..8d80b2f8 100644 --- a/src/Weaviate.Client/Models/PermissionResource.cs +++ b/src/Weaviate.Client/Models/PermissionResource.cs @@ -70,6 +70,12 @@ public record ReplicateResource(string? Collection = "*", string? Shard = "*"); /// Optional alias name (defaults to "*" for all aliases) public record AliasesResource(string? Collection = "*", string? Alias = "*"); +/// +/// Represents a namespaces resource, optionally scoped to a namespace. Requires Weaviate 1.38 or later. +/// +/// Optional namespace name or regex pattern (defaults to "*" for all namespaces) +public record NamespacesResource(string? Namespace = "*"); + /// /// The permission resource extensions class /// @@ -191,6 +197,16 @@ internal static Rest.Dto.Aliases ToDto(this AliasesResource resource) return new Rest.Dto.Aliases { Collection = resource.Collection, Alias = resource.Alias }; } + /// + /// Returns the dto using the specified resource + /// + /// The resource + /// The rest dto namespaces + internal static Rest.Dto.Namespaces ToDto(this NamespacesResource resource) + { + return new Rest.Dto.Namespaces { Namespace = resource.Namespace }; + } + /// /// Returns the model using the specified resource /// @@ -421,4 +437,26 @@ internal static PermissionScope ToModel( Delete = actions.Contains(Rest.Dto.PermissionAction.Delete_collections), }; } + + /// + /// Returns the model using the specified resource + /// + /// The resource + /// The permissions + /// The permission scope + internal static PermissionScope ToModel( + this Rest.Dto.Namespaces resource, + IEnumerable permissions + ) + { + var actions = permissions + .Where(p => p.Namespaces == resource) + .Select(p => p.Action) + .ToHashSet(); + + return new Permissions.Namespaces(resource.Namespace) + { + Manage = actions.Contains(Rest.Dto.PermissionAction.Manage_namespaces), + }; + } } diff --git a/src/Weaviate.Client/Models/RbacPermissions.cs b/src/Weaviate.Client/Models/RbacPermissions.cs index 0ee6887f..9a488ad0 100644 --- a/src/Weaviate.Client/Models/RbacPermissions.cs +++ b/src/Weaviate.Client/Models/RbacPermissions.cs @@ -267,6 +267,74 @@ internal static List Parse(IEnumerable inf } } + /// + /// The namespaces class. Requires Weaviate 1.38 or later. + /// + /// + public class Namespaces : PermissionScope + { + /// + /// Gets the value of the resource + /// + public NamespacesResource Resource { get; } + + /// + /// Gets or sets the value of the manage + /// + public bool Manage { get; set; } + + /// + /// Initializes a new instance of the class + /// + /// The namespace name or regex pattern + public Namespaces(string? @namespace) + : this(new NamespacesResource(@namespace)) { } + + /// + /// Initializes a new instance of the class + /// + /// The resource + /// + Namespaces(NamespacesResource resource) + { + Resource = resource ?? throw new ArgumentNullException(nameof(resource)); + } + + /// + /// Returns the dto + /// + /// An enumerable of rest dto permission + internal override IEnumerable ToDto() + { + var permissions = new[] + { + (Action: Rest.Dto.PermissionAction.Manage_namespaces, Allowed: Manage), + }; + + return permissions + .Where(p => p.Allowed) + .Select(p => new Rest.Dto.Permission + { + Namespaces = Resource.ToDto(), + Action = p.Action, + }); + } + + /// + /// Parses the infos + /// + /// The infos + /// A list of permission scope + internal static List Parse(IEnumerable infos) + { + return infos + .Where(i => i.Namespaces != null) + .GroupBy(i => i.Namespaces!) + .Select(group => group.Key.ToModel(group.AsEnumerable())) + .ToList(); + } + } + /// /// The mcp class /// @@ -988,6 +1056,7 @@ internal static List Parse(IEnumerable inf scopes.AddRange(Alias.Parse(infos)); scopes.AddRange(Data.Parse(infos)); scopes.AddRange(Backups.Parse(infos)); + scopes.AddRange(Namespaces.Parse(infos)); scopes.AddRange(Mcp.Parse(infos)); scopes.AddRange(Cluster.Parse(infos)); scopes.AddRange(Nodes.Parse(infos)); diff --git a/src/Weaviate.Client/Models/Replication.cs b/src/Weaviate.Client/Models/Replication.cs index ad8e7cab..c2ab5fb8 100644 --- a/src/Weaviate.Client/Models/Replication.cs +++ b/src/Weaviate.Client/Models/Replication.cs @@ -58,6 +58,13 @@ public enum ReplicationOperationState /// [System.Text.Json.Serialization.JsonStringEnumMemberName("CANCELLED")] Cancelled, + + /// + /// Replica has finished copying and is being integrated as a queryable member of the + /// shard. Occurs between and . + /// + [System.Text.Json.Serialization.JsonStringEnumMemberName("INTEGRATING")] + Integrating, } /// diff --git a/src/Weaviate.Client/PublicAPI.Unshipped.txt b/src/Weaviate.Client/PublicAPI.Unshipped.txt index 09359d23..9b7e6354 100644 --- a/src/Weaviate.Client/PublicAPI.Unshipped.txt +++ b/src/Weaviate.Client/PublicAPI.Unshipped.txt @@ -1,4 +1,5 @@ #nullable enable +Weaviate.Client.Models.ReplicationOperationState.Integrating = 6 -> Weaviate.Client.Models.ReplicationOperationState *REMOVED*Weaviate.Client.VectorizerFactory.Text2VecAWSBedrock(string! region, string! model, bool? vectorizeCollectionName = null) -> Weaviate.Client.Models.VectorizerConfig! *REMOVED*Weaviate.Client.VectorizerFactory.Text2VecAWSSagemaker(string! region, string! endpoint, string? targetModel = null, string? targetVariant = null, bool? vectorizeCollectionName = null) -> Weaviate.Client.Models.VectorizerConfig! *REMOVED*Weaviate.Client.VectorizerFactory.Text2VecGoogleVertex(string? apiEndpoint = null, string? model = null, string? projectId = null, string? titleProperty = null, int? dimensions = null, string? taskType = null, bool? vectorizeCollectionName = null) -> Weaviate.Client.Models.VectorizerConfig! @@ -9,3 +10,23 @@ Weaviate.Client.Models.Vectorizer.Text2VecGoogle.Location.set -> void Weaviate.Client.VectorizerFactory.Text2VecAWSBedrock(string! region, string! model, int? dimensions = null, bool? vectorizeCollectionName = null) -> Weaviate.Client.Models.VectorizerConfig! Weaviate.Client.VectorizerFactory.Text2VecAWSSagemaker(string! region, string! endpoint, string? targetModel = null, string? targetVariant = null, int? dimensions = null, bool? vectorizeCollectionName = null) -> Weaviate.Client.Models.VectorizerConfig! Weaviate.Client.VectorizerFactory.Text2VecGoogleVertex(string? apiEndpoint = null, string? model = null, string? projectId = null, string? titleProperty = null, int? dimensions = null, string? taskType = null, bool? vectorizeCollectionName = null, string? location = null) -> Weaviate.Client.Models.VectorizerConfig! +override Weaviate.Client.Models.NamespacesResource.Equals(object? obj) -> bool +override Weaviate.Client.Models.NamespacesResource.GetHashCode() -> int +override Weaviate.Client.Models.NamespacesResource.ToString() -> string! +static Weaviate.Client.Models.NamespacesResource.operator !=(Weaviate.Client.Models.NamespacesResource? left, Weaviate.Client.Models.NamespacesResource? right) -> bool +static Weaviate.Client.Models.NamespacesResource.operator ==(Weaviate.Client.Models.NamespacesResource? left, Weaviate.Client.Models.NamespacesResource? right) -> bool +virtual Weaviate.Client.Models.NamespacesResource.$() -> Weaviate.Client.Models.NamespacesResource! +virtual Weaviate.Client.Models.NamespacesResource.EqualityContract.get -> System.Type! +virtual Weaviate.Client.Models.NamespacesResource.Equals(Weaviate.Client.Models.NamespacesResource? other) -> bool +virtual Weaviate.Client.Models.NamespacesResource.PrintMembers(System.Text.StringBuilder! builder) -> bool +Weaviate.Client.Models.NamespacesResource +Weaviate.Client.Models.NamespacesResource.Deconstruct(out string? Namespace) -> void +Weaviate.Client.Models.NamespacesResource.Namespace.get -> string? +Weaviate.Client.Models.NamespacesResource.Namespace.init -> void +Weaviate.Client.Models.NamespacesResource.NamespacesResource(string? Namespace = "*") -> void +Weaviate.Client.Models.NamespacesResource.NamespacesResource(Weaviate.Client.Models.NamespacesResource! original) -> void +Weaviate.Client.Models.Permissions.Namespaces +Weaviate.Client.Models.Permissions.Namespaces.Manage.get -> bool +Weaviate.Client.Models.Permissions.Namespaces.Manage.set -> void +Weaviate.Client.Models.Permissions.Namespaces.Namespaces(string? namespace) -> void +Weaviate.Client.Models.Permissions.Namespaces.Resource.get -> Weaviate.Client.Models.NamespacesResource! diff --git a/src/Weaviate.Client/ReplicationsClient.cs b/src/Weaviate.Client/ReplicationsClient.cs index efe8fecb..f31aa226 100644 --- a/src/Weaviate.Client/ReplicationsClient.cs +++ b/src/Weaviate.Client/ReplicationsClient.cs @@ -183,6 +183,8 @@ private static ReplicationOperationState ParseState( ReplicationOperationState.Hydrating, Rest.Dto.ReplicationReplicateDetailsReplicaStatusState.FINALIZING => ReplicationOperationState.Finalizing, + Rest.Dto.ReplicationReplicateDetailsReplicaStatusState.INTEGRATING => + ReplicationOperationState.Integrating, Rest.Dto.ReplicationReplicateDetailsReplicaStatusState.DEHYDRATING => ReplicationOperationState.Dehydrating, Rest.Dto.ReplicationReplicateDetailsReplicaStatusState.READY => diff --git a/src/Weaviate.Client/Rest/Dto/Models.g.cs b/src/Weaviate.Client/Rest/Dto/Models.g.cs index 966bb969..fa799be1 100644 --- a/src/Weaviate.Client/Rest/Dto/Models.g.cs +++ b/src/Weaviate.Client/Rest/Dto/Models.g.cs @@ -163,6 +163,14 @@ internal partial record DBUserInfo public System.DateTimeOffset? LastUsedAt { get; set; } = default!; + /// + /// The namespace this user is bound to. Only populated for callers with global-operator privileges; omitted otherwise. + /// + + [System.Text.Json.Serialization.JsonPropertyName("namespace")] + + public string? Namespace { get; set; } = default!; + } [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] @@ -284,6 +292,14 @@ internal partial record Permission public Aliases? Aliases { get; set; } = default!; + /// + /// Resources applicable for namespace actions. + /// + + [System.Text.Json.Serialization.JsonPropertyName("namespaces")] + + public Namespaces? Namespaces { get; set; } = default!; + /// /// Allowed actions in weaviate. /// @@ -353,6 +369,22 @@ internal partial record Principal public UserTypeInput? UserType { get; set; } = default!; + /// + /// The namespace this principal is bound to. Empty for global principals (e.g. static API keys). + /// + + [System.Text.Json.Serialization.JsonPropertyName("namespace")] + + public string? Namespace { get; set; } = default!; + + /// + /// True for principals that operate across all namespaces (e.g. static API keys). Authoritative marker for operator-level principals; do not infer from an empty namespace. + /// + + [System.Text.Json.Serialization.JsonPropertyName("isGlobalOperator")] + + public bool? IsGlobalOperator { get; set; } = default!; + } /// @@ -517,6 +549,315 @@ internal partial record ErrorResponse } + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] + internal partial record IndexStatusResponse + { + + [System.Text.Json.Serialization.JsonPropertyName("collection")] + + public string? Collection { get; set; } = default!; + + [System.Text.Json.Serialization.JsonPropertyName("properties")] + + public System.Collections.Generic.IList? Properties { get; set; } = default!; + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] + internal partial record PropertyIndexStatus + { + + [System.Text.Json.Serialization.JsonPropertyName("name")] + + public string? Name { get; set; } = default!; + + [System.Text.Json.Serialization.JsonPropertyName("dataType")] + + public string? DataType { get; set; } = default!; + + [System.Text.Json.Serialization.JsonPropertyName("description")] + + public string? Description { get; set; } = default!; + + [System.Text.Json.Serialization.JsonPropertyName("indexes")] + + public System.Collections.Generic.IList? Indexes { get; set; } = default!; + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] + internal partial record IndexStatus + { + + [System.Text.Json.Serialization.JsonPropertyName("type")] + [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))] + + public IndexStatusType? Type { get; set; } = default!; + + [System.Text.Json.Serialization.JsonPropertyName("status")] + [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))] + + public IndexStatusStatus? Status { get; set; } = default!; + + [System.Text.Json.Serialization.JsonPropertyName("progress")] + + public float? Progress { get; set; } = default!; + + [System.Text.Json.Serialization.JsonPropertyName("tokenization")] + + public string? Tokenization { get; set; } = default!; + + [System.Text.Json.Serialization.JsonPropertyName("targetTokenization")] + + public string? TargetTokenization { get; set; } = default!; + + /// + /// BM25 algorithm currently backing this searchable index. 'wand' is the legacy map-based bucket strategy; 'blockmax' is the Block Max WAND inverted strategy. Only populated for `type=searchable` entries. Not populated for filterable or rangeable indexes. + /// + + [System.Text.Json.Serialization.JsonPropertyName("algorithm")] + [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))] + + public IndexStatusAlgorithm? Algorithm { get; set; } = default!; + + /// + /// BM25 algorithm this searchable index is being rebuilt onto. Populated only while an in-flight rebuild is changing the algorithm; mirrors `targetTokenization` for the change-tokenization verb. Today the only supported transition is wand -> blockmax. + /// + + [System.Text.Json.Serialization.JsonPropertyName("targetAlgorithm")] + [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))] + + public IndexStatusTargetAlgorithm? TargetAlgorithm { get; set; } = default!; + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] + internal partial record IndexUpdateRequest + { + + [System.Text.Json.Serialization.JsonPropertyName("searchable")] + + public IndexUpdateSearchable? Searchable { get; set; } = default!; + + [System.Text.Json.Serialization.JsonPropertyName("filterable")] + + public IndexUpdateFilterable? Filterable { get; set; } = default!; + + [System.Text.Json.Serialization.JsonPropertyName("rangeable")] + + public IndexUpdateRangeable? Rangeable { get; set; } = default!; + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] + internal partial record IndexUpdateSearchable + { + + [System.Text.Json.Serialization.JsonPropertyName("tokenization")] + + public string? Tokenization { get; set; } = default!; + + /// + /// When true, rebuilds the searchable index for this property from the stored objects. Preserves the current tokenization and BM25 algorithm. Only valid when the property's current algorithm is `blockmax`; on a WAND property the request is rejected with guidance to use `algorithm:"blockmax"` first. + /// + + [System.Text.Json.Serialization.JsonPropertyName("rebuild")] + + public bool? Rebuild { get; set; } = default!; + + /// + /// Switch the BM25 algorithm for this property's searchable index. Currently only `blockmax` is accepted. From WAND this triggers the Map → BlockMax migration; on an already-`blockmax` property the request is rejected. WAND is deprecated; downgrade is intentionally not supported. + /// + + [System.Text.Json.Serialization.JsonPropertyName("algorithm")] + [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))] + + public IndexUpdateSearchableAlgorithm? Algorithm { get; set; } = default!; + + [System.Text.Json.Serialization.JsonPropertyName("enabled")] + + public bool? Enabled { get; set; } = default!; + + /// + /// When true, cancels the in-flight reindex task targeting this property's searchable index. The task transitions to CANCELLED; partial state is left on disk for the next-restart finalize. + /// + + [System.Text.Json.Serialization.JsonPropertyName("cancel")] + + public bool? Cancel { get; set; } = default!; + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] + internal partial record IndexUpdateFilterable + { + + [System.Text.Json.Serialization.JsonPropertyName("rebuild")] + + public bool? Rebuild { get; set; } = default!; + + [System.Text.Json.Serialization.JsonPropertyName("enabled")] + + public bool? Enabled { get; set; } = default!; + + /// + /// Change the tokenization used by the filterable index on this text/text[] property. Only valid when the property already has a filterable index. Use this for filterable-only properties; for properties that ALSO have a searchable index, prefer searchable.tokenization since it retokenizes both buckets in a single coordinated migration. + /// + + [System.Text.Json.Serialization.JsonPropertyName("tokenization")] + + public string? Tokenization { get; set; } = default!; + + /// + /// When true, cancels the in-flight reindex task targeting this property's filterable index. + /// + + [System.Text.Json.Serialization.JsonPropertyName("cancel")] + + public bool? Cancel { get; set; } = default!; + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] + internal partial record IndexUpdateRangeable + { + + [System.Text.Json.Serialization.JsonPropertyName("enabled")] + + public bool? Enabled { get; set; } = default!; + + /// + /// When true, rebuilds the rangeable index from the existing filterable bucket (same source-of-truth as enable-rangeable). + /// + + [System.Text.Json.Serialization.JsonPropertyName("rebuild")] + + public bool? Rebuild { get; set; } = default!; + + /// + /// When true, cancels the in-flight reindex task targeting this property's rangeable index. + /// + + [System.Text.Json.Serialization.JsonPropertyName("cancel")] + + public bool? Cancel { get; set; } = default!; + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] + internal partial record IndexUpdateResponse + { + + [System.Text.Json.Serialization.JsonPropertyName("taskId")] + + public string? TaskId { get; set; } = default!; + + [System.Text.Json.Serialization.JsonPropertyName("status")] + + public string? Status { get; set; } = default!; + + } + + /// + /// Returned with HTTP 429 when a configured Weaviate usage limit (objects/collections/tenants/shards) is exceeded. The structured fields (`errorCode`, `limit`, `value`) are stable contract; the `message` text is operator-overridable via the `USAGE_LIMITS_ERROR_MESSAGE` template. + /// + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] + internal partial record UsageLimitExceededResponse + { + /// + /// Machine-stable identifier. Always `USAGE_LIMIT_EXCEEDED` for this response. + /// + + [System.Text.Json.Serialization.JsonPropertyName("errorCode")] + [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))] + + public UsageLimitExceededResponseErrorCode? ErrorCode { get; set; } = default!; + + /// + /// Which limit was hit. + /// + + [System.Text.Json.Serialization.JsonPropertyName("limit")] + [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))] + + public UsageLimitExceededResponseLimit? Limit { get; set; } = default!; + + /// + /// The configured threshold value (the cap, not the current count). + /// + + [System.Text.Json.Serialization.JsonPropertyName("value")] + + public long? Value { get; set; } = default!; + + /// + /// Human-readable message rendered from the `USAGE_LIMITS_ERROR_MESSAGE` template with `{limit}` and `{value}` placeholders substituted. + /// + + [System.Text.Json.Serialization.JsonPropertyName("message")] + + public string? Message { get; set; } = default!; + + } + + /// + /// Returned with HTTP 422 from class create/update endpoints. For restriction violations (operator-disallowed config via ALLOWED_VECTOR_INDEX_TYPES or ALLOWED_COMPRESSION_TYPES) the structured fields (`errorCode`, `restriction`, `value`, `allowed`, `message`) are populated; the `message` text is rendered from the operator-overridable `RESTRICTIONS_ERROR_MESSAGE` template. For unrelated 422 errors the `error` array is populated (matching the legacy ErrorResponse shape) and the structured fields are omitted. + /// + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] + internal partial record RestrictionViolationResponse + { + /// + /// Legacy ErrorResponse-style error list, populated for non-restriction 422 errors. + /// + + [System.Text.Json.Serialization.JsonPropertyName("error")] + + public System.Collections.Generic.IList? Error { get; set; } = default!; + + /// + /// Machine-stable identifier. Set to `CONFIG_NOT_ALLOWED` for restriction violations; omitted otherwise. + /// + + [System.Text.Json.Serialization.JsonPropertyName("errorCode")] + [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))] + + public RestrictionViolationResponseErrorCode? ErrorCode { get; set; } = default!; + + /// + /// Which restriction was violated. + /// + + [System.Text.Json.Serialization.JsonPropertyName("restriction")] + [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))] + + public RestrictionViolationResponseRestriction? Restriction { get; set; } = default!; + + /// + /// The disallowed value the client submitted. + /// + + [System.Text.Json.Serialization.JsonPropertyName("value")] + + public string? Value { get; set; } = default!; + + /// + /// The operator-configured allow-list. + /// + + [System.Text.Json.Serialization.JsonPropertyName("allowed")] + + public System.Collections.Generic.IList? Allowed { get; set; } = default!; + + /// + /// Human-readable message rendered from the `RESTRICTIONS_ERROR_MESSAGE` template with `{restriction}`, `{value}`, `{allowed}` placeholders substituted. + /// + + [System.Text.Json.Serialization.JsonPropertyName("message")] + + public string? Message { get; set; } = default!; + + } + /// /// Request to create a new export operation /// @@ -910,14 +1251,6 @@ internal partial record ReplicationConfig public int? Factor { get; set; } = default!; - /// - /// Enable asynchronous replication (default: `false`). - /// - - [System.Text.Json.Serialization.JsonPropertyName("asyncEnabled")] - - public bool? AsyncEnabled { get; set; } = default!; - /// /// Configuration parameters for asynchronous replication. /// @@ -1860,6 +2193,14 @@ internal partial record Property public bool? IndexInverted { get; set; } = default!; + /// + /// Internal RAFT-replicated counter bumped by semantic runtime-reindex migrations (e.g. change-tokenization, enable-filterable, enable-searchable). Used by the data path to resolve the property's inverted-index bucket name; a single RAFT commit flipping the schema flag AND bumping this counter atomically cuts the cluster from the old bucket to the new one. Defaults to 0. Internal use; clients should not set this. + /// + + [System.Text.Json.Serialization.JsonPropertyName("bucketGeneration")] + + public long? BucketGeneration { get; set; } = default!; + /// /// Whether to include this property in the filterable, Roaring Bitmap index. If `false`, this property cannot be used in `where` filters. <br/><br/>Note: Unrelated to vectorization behavior. /// @@ -1916,7 +2257,7 @@ internal partial record Property } /// - /// Text analysis options for a property. The asciiFold setting is immutable after creation, while the asciiFoldIgnore list can be updated later; changes to asciiFoldIgnore only affect newly indexed data and do not retroactively re-index existing data. Applies only to text and text[] data types that use an inverted index (searchable or filterable). + /// Text analysis options for a property. These settings are immutable after the property is created. Applies only to text and text[] data types that use an inverted index (searchable or filterable). /// [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] internal partial record TextAnalyzerConfig @@ -1930,7 +2271,7 @@ internal partial record TextAnalyzerConfig public bool? AsciiFold { get; set; } = default!; /// - /// If provided, specifies a list of characters that should be excluded from ascii folding. For example, if ['é'] is provided, then 'é' will not be folded to 'e' during indexing and search. This list can be updated after the property is created, but updates only affect documents indexed after the change. + /// If provided, specifies a list of characters that should be excluded from ascii folding. For example, if ['é'] is provided, then 'é' will not be folded to 'e' during indexing and search. This list is immutable after the property is created. /// [System.Text.Json.Serialization.JsonPropertyName("asciiFoldIgnore")] @@ -2142,6 +2483,14 @@ internal partial record BackupCreateStatusResponse public double? Size { get; set; } = default!; + /// + /// The ID of the base backup this incremental backup was built on; empty if the backup is not incremental. + /// + + [System.Text.Json.Serialization.JsonPropertyName("incremental_base_backup_id")] + + public string? Incremental_base_backup_id { get; set; } = default!; + } /// @@ -2334,7 +2683,7 @@ internal partial record BackupCreateRequest public BackupConfig? Config { get; set; } = default!; /// - /// List of collections to include in the backup creation process. If not set, all collections are included. Cannot be used together with `exclude`. + /// List of collections to include in the backup creation process. If not set, all collections are included. Cannot be used together with `exclude`. Permits wildcards, e.g. `*` or `prefix*`. /// [System.Text.Json.Serialization.JsonPropertyName("include")] @@ -2342,13 +2691,21 @@ internal partial record BackupCreateRequest public System.Collections.Generic.IList? Include { get; set; } = default!; /// - /// List of collections to exclude from the backup creation process. If not set, all collections are included. Cannot be used together with `include`. + /// List of collections to exclude from the backup creation process. If not set, all collections are included. Cannot be used together with `include`. Permits wildcards, e.g. `*` or `prefix*`. /// [System.Text.Json.Serialization.JsonPropertyName("exclude")] public System.Collections.Generic.IList? Exclude { get; set; } = default!; + /// + /// List of dynamic DB users to include in the backup. Permits `*` and `?` wildcards, e.g. `*` or `prefix*`. When omitted, the whole dynamic-user store is captured as part of the cluster snapshot and no per-user permission check is applied; when set, only matching users are captured and each is authorized individually. + /// + + [System.Text.Json.Serialization.JsonPropertyName("includeUsers")] + + public System.Collections.Generic.IList? IncludeUsers { get; set; } = default!; + /// /// The ID of an existing backup to use as the base for a file-based incremental backup. If set, only files that have changed since the base backup will be included in the new backup. /// @@ -4019,6 +4376,72 @@ internal partial record AliasResponse } + /// + /// A cluster-level namespace used to group resources under a common administrative unit. Namespace names must contain only lowercase letters, digits, and hyphens, must start and end with a letter or digit, must be 3-36 characters long, and must not be a reserved name. + /// + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] + internal partial record Namespace + { + /// + /// The unique name of the namespace. + /// + + [System.Text.Json.Serialization.JsonPropertyName("name")] + + public string? Name { get; set; } = default!; + + /// + /// The cluster node where this namespace's shards are placed. Set at create time and updatable later. Updating it only affects future placement decisions; existing live shards are not moved. + /// + + [System.Text.Json.Serialization.JsonPropertyName("home_node")] + + public string? Home_node { get; set; } = default!; + + /// + /// Lifecycle state. "active" namespaces accept all operations. "deleting" namespaces are being removed: new classes, aliases, and users can no longer be created in the namespace, and the namespace itself disappears once removal completes. + /// + + [System.Text.Json.Serialization.JsonPropertyName("state")] + [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))] + + public NamespaceState? State { get; set; } = default!; + + } + + /// + /// Optional body for namespace creation. When `home_node` is omitted, the cluster picks one automatically. + /// + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] + internal partial record NamespaceCreateRequest + { + /// + /// Optional. Cluster node to place this namespace's shards on. Must be a current storage candidate. When omitted, the cluster picks one. + /// + + [System.Text.Json.Serialization.JsonPropertyName("home_node")] + + public string? Home_node { get; set; } = default!; + + } + + /// + /// Update payload for an existing namespace. + /// + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] + internal partial record NamespaceUpdateRequest + { + /// + /// Cluster node to use for future placements in this namespace. Must be a current storage candidate. Existing live shards are not moved. + /// + + [System.Text.Json.Serialization.JsonPropertyName("home_node")] + [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)] + + public string Home_node { get; set; } = default!; + + } + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] internal partial record Body { @@ -4384,6 +4807,14 @@ internal partial record Anonymous3 public double? Size { get; set; } = default!; + /// + /// The ID of the base backup this incremental backup was built on; empty if the backup is not incremental. + /// + + [System.Text.Json.Serialization.JsonPropertyName("incremental_base_backup_id")] + + public string? Incremental_base_backup_id { get; set; } = default!; + } [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] @@ -4591,6 +5022,19 @@ internal partial record Aliases } + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] + internal partial record Namespaces + { + /// + /// A string that specifies which namespaces this permission applies to. Can be an exact namespace name or a regex pattern. The default value `*` applies the permission to all namespaces. + /// + + [System.Text.Json.Serialization.JsonPropertyName("namespace")] + + public string? Namespace { get; set; } = "*"; + + } + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] internal enum PermissionAction { @@ -4706,6 +5150,9 @@ internal enum PermissionAction [System.Text.Json.Serialization.JsonStringEnumMemberName(@"update_mcp")] Update_mcp = 36, + [System.Text.Json.Serialization.JsonStringEnumMemberName(@"manage_namespaces")] + Manage_namespaces = 37, + } [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] @@ -4758,6 +5205,133 @@ internal partial record Error } + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] + internal enum IndexStatusType + { + + [System.Text.Json.Serialization.JsonStringEnumMemberName(@"filterable")] + Filterable = 0, + + [System.Text.Json.Serialization.JsonStringEnumMemberName(@"searchable")] + Searchable = 1, + + [System.Text.Json.Serialization.JsonStringEnumMemberName(@"rangeable")] + Rangeable = 2, + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] + internal enum IndexStatusStatus + { + + [System.Text.Json.Serialization.JsonStringEnumMemberName(@"ready")] + Ready = 0, + + [System.Text.Json.Serialization.JsonStringEnumMemberName(@"indexing")] + Indexing = 1, + + [System.Text.Json.Serialization.JsonStringEnumMemberName(@"pending")] + Pending = 2, + + [System.Text.Json.Serialization.JsonStringEnumMemberName(@"failed")] + Failed = 3, + + [System.Text.Json.Serialization.JsonStringEnumMemberName(@"cancelled")] + Cancelled = 4, + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] + internal enum IndexStatusAlgorithm + { + + [System.Text.Json.Serialization.JsonStringEnumMemberName(@"wand")] + Wand = 0, + + [System.Text.Json.Serialization.JsonStringEnumMemberName(@"blockmax")] + Blockmax = 1, + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] + internal enum IndexStatusTargetAlgorithm + { + + [System.Text.Json.Serialization.JsonStringEnumMemberName(@"wand")] + Wand = 0, + + [System.Text.Json.Serialization.JsonStringEnumMemberName(@"blockmax")] + Blockmax = 1, + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] + internal enum IndexUpdateSearchableAlgorithm + { + + [System.Text.Json.Serialization.JsonStringEnumMemberName(@"blockmax")] + Blockmax = 0, + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] + internal enum UsageLimitExceededResponseErrorCode + { + + [System.Text.Json.Serialization.JsonStringEnumMemberName(@"USAGE_LIMIT_EXCEEDED")] + USAGE_LIMIT_EXCEEDED = 0, + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] + internal enum UsageLimitExceededResponseLimit + { + + [System.Text.Json.Serialization.JsonStringEnumMemberName(@"objects")] + Objects = 0, + + [System.Text.Json.Serialization.JsonStringEnumMemberName(@"collections")] + Collections = 1, + + [System.Text.Json.Serialization.JsonStringEnumMemberName(@"tenants")] + Tenants = 2, + + [System.Text.Json.Serialization.JsonStringEnumMemberName(@"shards")] + Shards = 3, + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] + internal partial record Error2 + { + + [System.Text.Json.Serialization.JsonPropertyName("message")] + + public string? Message { get; set; } = default!; + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] + internal enum RestrictionViolationResponseErrorCode + { + + [System.Text.Json.Serialization.JsonStringEnumMemberName(@"CONFIG_NOT_ALLOWED")] + CONFIG_NOT_ALLOWED = 0, + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] + internal enum RestrictionViolationResponseRestriction + { + + [System.Text.Json.Serialization.JsonStringEnumMemberName(@"vector_index_type")] + Vector_index_type = 0, + + [System.Text.Json.Serialization.JsonStringEnumMemberName(@"compression")] + Compression = 1, + + } + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] internal enum ExportCreateRequestFile_format { @@ -4949,14 +5523,17 @@ internal enum ReplicationReplicateDetailsReplicaStatusState [System.Text.Json.Serialization.JsonStringEnumMemberName(@"FINALIZING")] FINALIZING = 2, + [System.Text.Json.Serialization.JsonStringEnumMemberName(@"INTEGRATING")] + INTEGRATING = 3, + [System.Text.Json.Serialization.JsonStringEnumMemberName(@"DEHYDRATING")] - DEHYDRATING = 3, + DEHYDRATING = 4, [System.Text.Json.Serialization.JsonStringEnumMemberName(@"READY")] - READY = 4, + READY = 5, [System.Text.Json.Serialization.JsonStringEnumMemberName(@"CANCELLED")] - CANCELLED = 5, + CANCELLED = 6, } @@ -5521,6 +6098,18 @@ internal enum TenantActivityStatus } + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] + internal enum NamespaceState + { + + [System.Text.Json.Serialization.JsonStringEnumMemberName(@"active")] + Active = 0, + + [System.Text.Json.Serialization.JsonStringEnumMemberName(@"deleting")] + Deleting = 1, + + } + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.6.1.0 (NJsonSchema v11.5.1.0 (Newtonsoft.Json v13.0.0.0))")] internal enum Fields { diff --git a/src/Weaviate.Client/Rest/Dto/ReplicationConfigCompat.cs b/src/Weaviate.Client/Rest/Dto/ReplicationConfigCompat.cs new file mode 100644 index 00000000..7a01649f --- /dev/null +++ b/src/Weaviate.Client/Rest/Dto/ReplicationConfigCompat.cs @@ -0,0 +1,22 @@ +namespace Weaviate.Client.Rest.Dto; + +/// +/// Compatibility extension for the generated DTO. +/// +/// +/// Weaviate 1.38 removed asyncEnabled from the OpenAPI spec (async replication +/// is now derived server-side as factor > 1 unless globally disabled), but the +/// server keeps emitting the field on REST responses through a compatibility shim +/// (adapters/handlers/rest/restcompat), and servers up to 1.37 still honor it as a +/// per-collection setting. Keep the property here so the client round-trips it against +/// every supported server version; the generated model no longer carries it. +/// +internal partial record ReplicationConfig +{ + /// + /// Enable asynchronous replication (default: false). On Weaviate 1.38+ this is + /// reported as factor > 1 && !ASYNC_REPLICATION_DISABLED and is ignored on input. + /// + [System.Text.Json.Serialization.JsonPropertyName("asyncEnabled")] + public bool? AsyncEnabled { get; set; } = default!; +} diff --git a/src/Weaviate.Client/Rest/Schema/openapi.json b/src/Weaviate.Client/Rest/Schema/openapi.json index cdc34c4d..2301b93f 100644 --- a/src/Weaviate.Client/Rest/Schema/openapi.json +++ b/src/Weaviate.Client/Rest/Schema/openapi.json @@ -105,6 +105,10 @@ ], "format": "date-time", "description": "Date and time in ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ." + }, + "namespace": { + "type": "string", + "description": "The namespace this user is bound to. Only populated for callers with global-operator privileges; omitted otherwise." } }, "required": [ @@ -307,6 +311,17 @@ } } }, + "namespaces": { + "type": "object", + "description": "Resources applicable for namespace actions.", + "properties": { + "namespace": { + "type": "string", + "default": "*", + "description": "A string that specifies which namespaces this permission applies to. Can be an exact namespace name or a regex pattern. The default value `*` applies the permission to all namespaces." + } + } + }, "action": { "type": "string", "description": "Allowed actions in weaviate.", @@ -347,7 +362,8 @@ "read_groups", "create_mcp", "read_mcp", - "update_mcp" + "update_mcp", + "manage_namespaces" ] } }, @@ -398,6 +414,14 @@ }, "userType": { "$ref": "#/definitions/UserTypeInput" + }, + "namespace": { + "type": "string", + "description": "The namespace this principal is bound to. Empty for global principals (e.g. static API keys)." + }, + "isGlobalOperator": { + "type": "boolean", + "description": "True for principals that operate across all namespaces (e.g. static API keys). Authoritative marker for operator-level principals; do not infer from an empty namespace." } } }, @@ -580,6 +604,255 @@ }, "type": "object" }, + "IndexStatusResponse": { + "type": "object", + "properties": { + "collection": { + "type": "string" + }, + "properties": { + "type": "array", + "items": { + "$ref": "#/definitions/PropertyIndexStatus" + } + } + } + }, + "PropertyIndexStatus": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "dataType": { + "type": "string" + }, + "description": { + "type": "string" + }, + "indexes": { + "type": "array", + "items": { + "$ref": "#/definitions/IndexStatus" + } + } + } + }, + "IndexStatus": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "filterable", + "searchable", + "rangeable" + ] + }, + "status": { + "type": "string", + "enum": [ + "ready", + "indexing", + "pending", + "failed", + "cancelled" + ] + }, + "progress": { + "type": "number", + "format": "float" + }, + "tokenization": { + "type": "string" + }, + "targetTokenization": { + "type": "string" + }, + "algorithm": { + "type": "string", + "enum": [ + "wand", + "blockmax" + ], + "description": "BM25 algorithm currently backing this searchable index. 'wand' is the legacy map-based bucket strategy; 'blockmax' is the Block Max WAND inverted strategy. Only populated for `type=searchable` entries. Not populated for filterable or rangeable indexes." + }, + "targetAlgorithm": { + "type": "string", + "enum": [ + "wand", + "blockmax" + ], + "description": "BM25 algorithm this searchable index is being rebuilt onto. Populated only while an in-flight rebuild is changing the algorithm; mirrors `targetTokenization` for the change-tokenization verb. Today the only supported transition is wand -> blockmax." + } + } + }, + "IndexUpdateRequest": { + "type": "object", + "properties": { + "searchable": { + "$ref": "#/definitions/IndexUpdateSearchable" + }, + "filterable": { + "$ref": "#/definitions/IndexUpdateFilterable" + }, + "rangeable": { + "$ref": "#/definitions/IndexUpdateRangeable" + } + } + }, + "IndexUpdateSearchable": { + "type": "object", + "properties": { + "tokenization": { + "type": "string" + }, + "rebuild": { + "type": "boolean", + "description": "When true, rebuilds the searchable index for this property from the stored objects. Preserves the current tokenization and BM25 algorithm. Only valid when the property's current algorithm is `blockmax`; on a WAND property the request is rejected with guidance to use `algorithm:\"blockmax\"` first." + }, + "algorithm": { + "type": "string", + "enum": [ + "blockmax" + ], + "description": "Switch the BM25 algorithm for this property's searchable index. Currently only `blockmax` is accepted. From WAND this triggers the Map → BlockMax migration; on an already-`blockmax` property the request is rejected. WAND is deprecated; downgrade is intentionally not supported." + }, + "enabled": { + "type": "boolean" + }, + "cancel": { + "type": "boolean", + "description": "When true, cancels the in-flight reindex task targeting this property's searchable index. The task transitions to CANCELLED; partial state is left on disk for the next-restart finalize." + } + } + }, + "IndexUpdateFilterable": { + "type": "object", + "properties": { + "rebuild": { + "type": "boolean" + }, + "enabled": { + "type": "boolean" + }, + "tokenization": { + "type": "string", + "description": "Change the tokenization used by the filterable index on this text/text[] property. Only valid when the property already has a filterable index. Use this for filterable-only properties; for properties that ALSO have a searchable index, prefer searchable.tokenization since it retokenizes both buckets in a single coordinated migration." + }, + "cancel": { + "type": "boolean", + "description": "When true, cancels the in-flight reindex task targeting this property's filterable index." + } + } + }, + "IndexUpdateRangeable": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "rebuild": { + "type": "boolean", + "description": "When true, rebuilds the rangeable index from the existing filterable bucket (same source-of-truth as enable-rangeable)." + }, + "cancel": { + "type": "boolean", + "description": "When true, cancels the in-flight reindex task targeting this property's rangeable index." + } + } + }, + "IndexUpdateResponse": { + "type": "object", + "properties": { + "taskId": { + "type": "string" + }, + "status": { + "type": "string" + } + } + }, + "UsageLimitExceededResponse": { + "description": "Returned with HTTP 429 when a configured Weaviate usage limit (objects/collections/tenants/shards) is exceeded. The structured fields (`errorCode`, `limit`, `value`) are stable contract; the `message` text is operator-overridable via the `USAGE_LIMITS_ERROR_MESSAGE` template.", + "type": "object", + "properties": { + "errorCode": { + "type": "string", + "description": "Machine-stable identifier. Always `USAGE_LIMIT_EXCEEDED` for this response.", + "enum": [ + "USAGE_LIMIT_EXCEEDED" + ] + }, + "limit": { + "type": "string", + "description": "Which limit was hit.", + "enum": [ + "objects", + "collections", + "tenants", + "shards" + ] + }, + "value": { + "type": "integer", + "format": "int64", + "description": "The configured threshold value (the cap, not the current count)." + }, + "message": { + "type": "string", + "description": "Human-readable message rendered from the `USAGE_LIMITS_ERROR_MESSAGE` template with `{limit}` and `{value}` placeholders substituted." + } + } + }, + "RestrictionViolationResponse": { + "description": "Returned with HTTP 422 from class create/update endpoints. For restriction violations (operator-disallowed config via ALLOWED_VECTOR_INDEX_TYPES or ALLOWED_COMPRESSION_TYPES) the structured fields (`errorCode`, `restriction`, `value`, `allowed`, `message`) are populated; the `message` text is rendered from the operator-overridable `RESTRICTIONS_ERROR_MESSAGE` template. For unrelated 422 errors the `error` array is populated (matching the legacy ErrorResponse shape) and the structured fields are omitted.", + "type": "object", + "properties": { + "error": { + "type": "array", + "items": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + }, + "description": "Legacy ErrorResponse-style error list, populated for non-restriction 422 errors." + }, + "errorCode": { + "type": "string", + "description": "Machine-stable identifier. Set to `CONFIG_NOT_ALLOWED` for restriction violations; omitted otherwise.", + "enum": [ + "CONFIG_NOT_ALLOWED" + ] + }, + "restriction": { + "type": "string", + "description": "Which restriction was violated.", + "enum": [ + "vector_index_type", + "compression" + ] + }, + "value": { + "type": "string", + "description": "The disallowed value the client submitted." + }, + "allowed": { + "type": "array", + "items": { + "type": "string" + }, + "description": "The operator-configured allow-list." + }, + "message": { + "type": "string", + "description": "Human-readable message rendered from the `RESTRICTIONS_ERROR_MESSAGE` template with `{restriction}`, `{value}`, `{allowed}` placeholders substituted." + } + } + }, "ExportCreateRequest": { "description": "Request to create a new export operation", "type": "object", @@ -887,11 +1160,6 @@ "description": "Number of times a collection (class) is replicated (default: 1).", "type": "integer" }, - "asyncEnabled": { - "description": "Enable asynchronous replication (default: `false`).", - "type": "boolean", - "x-omitempty": false - }, "asyncConfig": { "description": "Configuration parameters for asynchronous replication.", "$ref": "#/definitions/ReplicationAsyncConfig", @@ -1338,6 +1606,7 @@ "REGISTERED", "HYDRATING", "FINALIZING", + "INTEGRATING", "DEHYDRATING", "READY", "CANCELLED" @@ -1613,6 +1882,11 @@ "type": "boolean", "x-nullable": true }, + "bucketGeneration": { + "description": "Internal RAFT-replicated counter bumped by semantic runtime-reindex migrations (e.g. change-tokenization, enable-filterable, enable-searchable). Used by the data path to resolve the property's inverted-index bucket name; a single RAFT commit flipping the schema flag AND bumping this counter atomically cuts the cluster from the old bucket to the new one. Defaults to 0. Internal use; clients should not set this.", + "type": "integer", + "format": "int64" + }, "indexFilterable": { "description": "Whether to include this property in the filterable, Roaring Bitmap index. If `false`, this property cannot be used in `where` filters.

Note: Unrelated to vectorization behavior.", "type": "boolean", @@ -1664,14 +1938,14 @@ "type": "object" }, "TextAnalyzerConfig": { - "description": "Text analysis options for a property. The asciiFold setting is immutable after creation, while the asciiFoldIgnore list can be updated later; changes to asciiFoldIgnore only affect newly indexed data and do not retroactively re-index existing data. Applies only to text and text[] data types that use an inverted index (searchable or filterable).", + "description": "Text analysis options for a property. These settings are immutable after the property is created. Applies only to text and text[] data types that use an inverted index (searchable or filterable).", "properties": { "asciiFold": { "description": "If true, accent/diacritic marks are folded to their base characters during indexing and search. For example, 'école' matches 'ecole'. Defaults to false.", "type": "boolean" }, "asciiFoldIgnore": { - "description": "If provided, specifies a list of characters that should be excluded from ascii folding. For example, if ['é'] is provided, then 'é' will not be folded to 'e' during indexing and search. This list can be updated after the property is created, but updates only affect documents indexed after the change.", + "description": "If provided, specifies a list of characters that should be excluded from ascii folding. For example, if ['é'] is provided, then 'é' will not be folded to 'e' during indexing and search. This list is immutable after the property is created.", "type": "array", "x-omitempty": true, "items": { @@ -1840,6 +2114,10 @@ "description": "Size of the backup in Gibs", "type": "number", "format": "float64" + }, + "incremental_base_backup_id": { + "description": "The ID of the base backup this incremental backup was built on; empty if the backup is not incremental.", + "type": "string" } } }, @@ -1983,14 +2261,21 @@ "$ref": "#/definitions/BackupConfig" }, "include": { - "description": "List of collections to include in the backup creation process. If not set, all collections are included. Cannot be used together with `exclude`.", + "description": "List of collections to include in the backup creation process. If not set, all collections are included. Cannot be used together with `exclude`. Permits wildcards, e.g. `*` or `prefix*`.", "type": "array", "items": { "type": "string" } }, "exclude": { - "description": "List of collections to exclude from the backup creation process. If not set, all collections are included. Cannot be used together with `include`.", + "description": "List of collections to exclude from the backup creation process. If not set, all collections are included. Cannot be used together with `include`. Permits wildcards, e.g. `*` or `prefix*`.", + "type": "array", + "items": { + "type": "string" + } + }, + "includeUsers": { + "description": "List of dynamic DB users to include in the backup. Permits `*` and `?` wildcards, e.g. `*` or `prefix*`. When omitted, the whole dynamic-user store is captured as part of the cluster snapshot and no per-user permission check is applied; when set, only matching users are captured and each is authorized individually.", "type": "array", "items": { "type": "string" @@ -2096,6 +2381,10 @@ "description": "Size of the backup in Gibs", "type": "number", "format": "float64" + }, + "incremental_base_backup_id": { + "description": "The ID of the base backup this incremental backup was built on; empty if the backup is not incremental.", + "type": "string" } } } @@ -3471,6 +3760,58 @@ } } } + }, + "Namespace": { + "type": "object", + "description": "A cluster-level namespace used to group resources under a common administrative unit. Namespace names must contain only lowercase letters, digits, and hyphens, must start and end with a letter or digit, must be 3-36 characters long, and must not be a reserved name.", + "properties": { + "name": { + "description": "The unique name of the namespace.", + "type": "string" + }, + "home_node": { + "description": "The cluster node where this namespace's shards are placed. Set at create time and updatable later. Updating it only affects future placement decisions; existing live shards are not moved.", + "type": "string" + }, + "state": { + "description": "Lifecycle state. \"active\" namespaces accept all operations. \"deleting\" namespaces are being removed: new classes, aliases, and users can no longer be created in the namespace, and the namespace itself disappears once removal completes.", + "type": "string", + "enum": [ + "active", + "deleting" + ] + } + } + }, + "NamespaceCreateRequest": { + "type": "object", + "description": "Optional body for namespace creation. When `home_node` is omitted, the cluster picks one automatically.", + "properties": { + "home_node": { + "description": "Optional. Cluster node to place this namespace's shards on. Must be a current storage candidate. When omitted, the cluster picks one.", + "type": "string" + } + } + }, + "NamespaceUpdateRequest": { + "type": "object", + "description": "Update payload for an existing namespace.", + "required": [ + "home_node" + ], + "properties": { + "home_node": { + "description": "Cluster node to use for future placements in this namespace. Must be a current storage candidate. Existing live shards are not moved.", + "type": "string" + } + } + }, + "NamespaceListResponse": { + "description": "Response object containing a list of namespaces.", + "type": "array", + "items": { + "$ref": "#/definitions/Namespace" + } } }, "externalDocs": { @@ -3484,7 +3825,7 @@ }, "description": "# Introduction
Weaviate is an open source, AI-native vector database that helps developers create intuitive and reliable AI-powered applications.
### Base Path
The base path for the Weaviate server is structured as `[YOUR-WEAVIATE-HOST]:[PORT]/v1`. As an example, if you wish to access the `schema` endpoint on a local instance, you would navigate to `http://localhost:8080/v1/schema`. Ensure you replace `[YOUR-WEAVIATE-HOST]` and `[PORT]` with your actual server host and port number respectively.
### Questions?
If you have any comments or questions, please feel free to reach out to us at the community forum [https://forum.weaviate.io/](https://forum.weaviate.io/).
### Issues?
If you find a bug or want to file a feature request, please open an issue on our GitHub repository for [Weaviate](https://github.com/weaviate/weaviate).
### Need more documentation?
For a quickstart, code examples, concepts and more, please visit our [documentation page](https://docs.weaviate.io/weaviate).", "title": "Weaviate REST API", - "version": "1.37.2" + "version": "1.38.4" }, "parameters": { "CommonAfterParameterQuery": { @@ -5218,6 +5559,9 @@ "$ref": "#/definitions/ErrorResponse" } }, + "404": { + "description": "No role found." + }, "422": { "description": "The request syntax is correct, but the server couldn't process it due to semantic issues. Please check the values in your request.", "schema": { @@ -5282,6 +5626,12 @@ "404": { "description": "No role found." }, + "410": { + "description": "Endpoint not available in the current cluster configuration.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, "500": { "description": "An error has occurred while trying to fulfill the request. Most likely the ErrorResponse will contain more information about the error.", "schema": { @@ -5475,6 +5825,12 @@ "404": { "description": "No roles found for specified user." }, + "410": { + "description": "Endpoint not available in the current cluster configuration.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, "422": { "description": "The request syntax is correct, but the server couldn't process it due to semantic issues. Please check the values in your request.", "schema": { @@ -6058,6 +6414,12 @@ "404": { "description": "Successful query result but no matching objects were found." }, + "410": { + "description": "Endpoint not available in the current cluster configuration.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, "422": { "description": "The request syntax is correct, but the server couldn't process it due to semantic issues. Please check the values in your request. Ensure the specified collection exists.", "schema": { @@ -6126,6 +6488,12 @@ "$ref": "#/definitions/ErrorResponse" } }, + "429": { + "description": "The configured object-count usage limit was exceeded. See `UsageLimitExceededResponse` for the limit value.", + "schema": { + "$ref": "#/definitions/UsageLimitExceededResponse" + } + }, "500": { "description": "An error occurred while trying to fulfill the request. Check the ErrorResponse for details.", "schema": { @@ -6180,6 +6548,12 @@ "404": { "description": "Object not found." }, + "410": { + "description": "Endpoint not available in the current cluster configuration.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, "500": { "description": "An error occurred while trying to fulfill the request. Check the ErrorResponse for details.", "schema": { @@ -6239,12 +6613,18 @@ "404": { "description": "Object not found." }, - "500": { - "description": "An error occurred while trying to fulfill the request. Check the ErrorResponse for details.", + "410": { + "description": "Endpoint not available in the current cluster configuration.", "schema": { "$ref": "#/definitions/ErrorResponse" } - } + }, + "500": { + "description": "An error occurred while trying to fulfill the request. Check the ErrorResponse for details.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } }, "summary": "Get an object", "tags": [ @@ -6301,6 +6681,12 @@ "404": { "description": "Object not found." }, + "410": { + "description": "Endpoint not available in the current cluster configuration.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, "422": { "description": "The patch object is valid JSON but is unprocessable for other reasons (e.g., invalid schema).", "schema": { @@ -6369,6 +6755,12 @@ "404": { "description": "Object not found." }, + "410": { + "description": "Endpoint not available in the current cluster configuration.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, "422": { "description": "The request syntax is correct, but the server couldn't process it due to semantic issues. Please check the values in your request. Ensure the collection exists and the object properties are valid.", "schema": { @@ -6422,6 +6814,12 @@ "404": { "description": "Object does not exist." }, + "410": { + "description": "Endpoint not available in the current cluster configuration.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, "500": { "description": "An error occurred while trying to fulfill the request. Check the ErrorResponse for details.", "schema": { @@ -6650,6 +7048,12 @@ "$ref": "#/definitions/ErrorResponse" } }, + "429": { + "description": "The configured object-count usage limit was exceeded. See `UsageLimitExceededResponse` for the limit value.", + "schema": { + "$ref": "#/definitions/UsageLimitExceededResponse" + } + }, "500": { "description": "An error occurred while trying to fulfill the request. Check the ErrorResponse for details.", "schema": { @@ -6856,6 +7260,12 @@ "$ref": "#/definitions/ErrorResponse" } }, + "410": { + "description": "Endpoint not available in the current cluster configuration.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, "422": { "description": "The request syntax is correct, but the server couldn't process it due to semantic issues. Please check the values in your request. Ensure the property exists and is a reference type.", "schema": { @@ -6925,6 +7335,12 @@ "$ref": "#/definitions/ErrorResponse" } }, + "410": { + "description": "Endpoint not available in the current cluster configuration.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, "422": { "description": "The request syntax is correct, but the server couldn't process it due to semantic issues. Please check the values in your request. Ensure the property exists and is a reference type.", "schema": { @@ -7000,6 +7416,12 @@ "$ref": "#/definitions/ErrorResponse" } }, + "410": { + "description": "Endpoint not available in the current cluster configuration.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, "500": { "description": "An error occurred while trying to fulfill the request. Check the ErrorResponse for details.", "schema": { @@ -7084,6 +7506,12 @@ "404": { "description": "Source object not found." }, + "410": { + "description": "Endpoint not available in the current cluster configuration.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, "422": { "description": "The request syntax is correct, but the server couldn't process it due to semantic issues. Please check the values in your request. Ensure the property exists and is a reference type.", "schema": { @@ -7171,6 +7599,12 @@ "404": { "description": "Source object not found." }, + "410": { + "description": "Endpoint not available in the current cluster configuration.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, "422": { "description": "The request syntax is correct, but the server couldn't process it due to semantic issues. Please check the values in your request. Ensure the property exists and is a reference type.", "schema": { @@ -7261,6 +7695,12 @@ "$ref": "#/definitions/ErrorResponse" } }, + "410": { + "description": "Endpoint not available in the current cluster configuration.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, "422": { "description": "The request syntax is correct, but the server couldn't process it due to semantic issues. Please check the values in your request. Ensure the property exists and is a reference type.", "schema": { @@ -7410,6 +7850,12 @@ "$ref": "#/definitions/ErrorResponse" } }, + "429": { + "description": "The configured object-count usage limit was exceeded. The whole batch is rejected (no partial fill); the client decides what to retry. See `UsageLimitExceededResponse` for the limit value.", + "schema": { + "$ref": "#/definitions/UsageLimitExceededResponse" + } + }, "500": { "description": "An error occurred while trying to fulfill the request. Check the ErrorResponse for details.", "schema": { @@ -7601,6 +8047,12 @@ "$ref": "#/definitions/ErrorResponse" } }, + "410": { + "description": "Endpoint not available in the current cluster configuration.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, "422": { "description": "The request syntax is correct, but the server couldn't process it due to semantic issues. Please check the values in your request.", "schema": { @@ -7659,6 +8111,12 @@ "$ref": "#/definitions/ErrorResponse" } }, + "410": { + "description": "Endpoint not available in the current cluster configuration.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, "422": { "description": "The request syntax is correct, but the server couldn't process it due to semantic issues. Please check the values in your request.", "schema": { @@ -7854,7 +8312,13 @@ "422": { "description": "Invalid collection definition provided. Check the definition structure and properties.", "schema": { - "$ref": "#/definitions/ErrorResponse" + "$ref": "#/definitions/RestrictionViolationResponse" + } + }, + "429": { + "description": "A configured usage limit (collections/shards) was exceeded. See the `UsageLimitExceededResponse` body for which limit and the configured value.", + "schema": { + "$ref": "#/definitions/UsageLimitExceededResponse" } }, "500": { @@ -7913,6 +8377,12 @@ "404": { "description": "Collection not found." }, + "422": { + "description": "Invalid collection name provided (e.g. malformed namespace prefix). Check the ErrorResponse for details.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, "500": { "description": "An error occurred while retrieving the collection definition. Check the ErrorResponse for details.", "schema": { @@ -8020,7 +8490,7 @@ "422": { "description": "Invalid update attempt.", "schema": { - "$ref": "#/definitions/ErrorResponse" + "$ref": "#/definitions/RestrictionViolationResponse" } }, "500": { @@ -8080,7 +8550,7 @@ "422": { "description": "Invalid property definition provided.", "schema": { - "$ref": "#/definitions/ErrorResponse" + "$ref": "#/definitions/RestrictionViolationResponse" } }, "500": { @@ -8092,6 +8562,139 @@ } } }, + "/schema/{className}/indexes": { + "get": { + "operationId": "schema.objects.indexes.get", + "tags": [ + "schema" + ], + "summary": "Get index status for all properties of a collection", + "description": "Returns per-property index state including active reindex progress. This powers the UI to show live migration status.", + "parameters": [ + { + "name": "className", + "in": "path", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "Index status for all properties.", + "schema": { + "$ref": "#/definitions/IndexStatusResponse" + } + }, + "401": { + "description": "Unauthorized or invalid credentials." + }, + "403": { + "description": "Forbidden", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "404": { + "description": "Collection not found." + }, + "500": { + "description": "An error occurred.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + } + }, + "/schema/{className}/indexes/{propertyName}": { + "put": { + "operationId": "schema.objects.indexes.update", + "tags": [ + "schema" + ], + "summary": "Update index configuration for a property (triggers reindex)", + "description": "Declaratively sets the desired index state for a property. The system computes the diff from the current state and triggers the appropriate reindex task.", + "parameters": [ + { + "name": "className", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "propertyName", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "tenants", + "in": "query", + "required": false, + "type": "array", + "items": { + "type": "string" + }, + "description": "Tenant names to target. Only for non-semantic operations on multi-tenant collections. Omit to target all tenants." + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/IndexUpdateRequest" + } + } + ], + "responses": { + "202": { + "description": "Reindex task submitted.", + "schema": { + "$ref": "#/definitions/IndexUpdateResponse" + } + }, + "400": { + "description": "Invalid request.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "401": { + "description": "Unauthorized or invalid credentials." + }, + "403": { + "description": "Forbidden", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "404": { + "description": "Collection or property not found. cancel:true with nothing to cancel returns 202 with Status: NO_OP instead — 404 is reserved for missing collection/property.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "409": { + "description": "Conflicting reindex task already running.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "500": { + "description": "An error occurred.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "503": { + "description": "Distributed tasks not enabled.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + } + }, "/schema/{className}/properties/{propertyName}/index/{indexName}": { "delete": { "summary": "Delete a property's inverted index", @@ -8470,6 +9073,12 @@ "$ref": "#/definitions/ErrorResponse" } }, + "429": { + "description": "The configured tenant-per-collection usage limit was exceeded. See `UsageLimitExceededResponse` for the limit value.", + "schema": { + "$ref": "#/definitions/UsageLimitExceededResponse" + } + }, "500": { "description": "An error occurred while creating tenants. Check the ErrorResponse for details.", "schema": { @@ -9041,6 +9650,281 @@ } } }, + "/namespaces": { + "get": { + "summary": "List namespaces", + "description": "Retrieve the list of all namespaces the caller has permission to see. Callers without any applicable `manage_namespaces` permission receive an empty list (never 403).", + "operationId": "listNamespaces", + "tags": [ + "namespaces" + ], + "responses": { + "200": { + "description": "Successfully retrieved the list of namespaces (possibly empty).", + "schema": { + "$ref": "#/definitions/NamespaceListResponse" + } + }, + "401": { + "description": "Unauthorized or invalid credentials." + }, + "404": { + "description": "Not Found - The namespaces feature is not enabled on this cluster.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "422": { + "description": "The request syntax is correct, but the server couldn't process it.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "500": { + "description": "An error has occurred while trying to fulfill the request. Most likely the ErrorResponse will contain more information about the error.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + } + }, + "/namespaces/{namespace_id}": { + "post": { + "summary": "Create a new namespace", + "description": "Create a new cluster-level namespace with the given name. Names must contain only lowercase letters, digits, and hyphens, must start and end with a letter or digit, must be 3-36 characters long, and must not be a reserved name.", + "operationId": "createNamespace", + "tags": [ + "namespaces" + ], + "parameters": [ + { + "description": "The name of the namespace. Must start with a lowercase letter, contain only lowercase letters and digits, length 3-36, and not be a reserved name.", + "in": "path", + "name": "namespace_id", + "required": true, + "type": "string" + }, + { + "description": "Optional body. When omitted, `home_node` is picked automatically.", + "in": "body", + "name": "body", + "schema": { + "$ref": "#/definitions/NamespaceCreateRequest" + } + } + ], + "responses": { + "201": { + "description": "Namespace created successfully.", + "schema": { + "$ref": "#/definitions/Namespace" + } + }, + "401": { + "description": "Unauthorized or invalid credentials." + }, + "403": { + "description": "Forbidden", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "404": { + "description": "Not Found - The namespaces feature is not enabled on this cluster.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "409": { + "description": "A namespace with the specified name already exists, or a namespace with the same name is currently being deleted. Differentiate by reading the human-readable message in the error payload.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "422": { + "description": "The request syntax is correct, but the server couldn't process it due to semantic issues (e.g. invalid name format or reserved name).", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "500": { + "description": "An error has occurred while trying to fulfill the request. Most likely the ErrorResponse will contain more information about the error.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + }, + "get": { + "summary": "Get a namespace", + "description": "Retrieve details about a specific namespace by its name.", + "operationId": "getNamespace", + "tags": [ + "namespaces" + ], + "parameters": [ + { + "description": "The name of the namespace.", + "in": "path", + "name": "namespace_id", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "Successfully retrieved the namespace.", + "schema": { + "$ref": "#/definitions/Namespace" + } + }, + "401": { + "description": "Unauthorized or invalid credentials." + }, + "403": { + "description": "Forbidden", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "404": { + "description": "Not Found - Namespace does not exist, or the namespaces feature is not enabled on this cluster.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "422": { + "description": "The request syntax is correct, but the server couldn't process it due to semantic issues (e.g. invalid name format or reserved name).", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "500": { + "description": "An error has occurred while trying to fulfill the request. Most likely the ErrorResponse will contain more information about the error.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + }, + "put": { + "summary": "Update a namespace", + "description": "Update a namespace's `home_node`. The new value applies to future placement decisions only (new collection create, new tenant create, tenant reactivation). Existing live shards are not moved.", + "operationId": "updateNamespace", + "tags": [ + "namespaces" + ], + "parameters": [ + { + "description": "The name of the namespace.", + "in": "path", + "name": "namespace_id", + "required": true, + "type": "string" + }, + { + "description": "Required body. `home_node` is the new placement target.", + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/NamespaceUpdateRequest" + } + } + ], + "responses": { + "200": { + "description": "Namespace updated successfully.", + "schema": { + "$ref": "#/definitions/Namespace" + } + }, + "401": { + "description": "Unauthorized or invalid credentials." + }, + "403": { + "description": "Forbidden", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "404": { + "description": "Not Found - Namespace does not exist, or the namespaces feature is not enabled on this cluster.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "409": { + "description": "The namespace is being deleted; `home_node` cannot be updated while the namespace is in the `deleting` state.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "422": { + "description": "The request syntax is correct, but the server couldn't process it due to semantic issues (e.g. invalid name format, reserved name, or unknown home_node).", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "500": { + "description": "An error has occurred while trying to fulfill the request. Most likely the ErrorResponse will contain more information about the error.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + }, + "delete": { + "summary": "Delete a namespace", + "description": "Mark a namespace for deletion. The endpoint is asynchronous: the namespace is flipped to the \"deleting\" state and its dynamic users are removed synchronously; classes and aliases are torn down by the leader on a periodic cleanup tick. Repeated calls while the namespace is still in the \"deleting\" state are idempotent and return 202.", + "operationId": "deleteNamespace", + "tags": [ + "namespaces" + ], + "parameters": [ + { + "description": "The name of the namespace.", + "in": "path", + "name": "namespace_id", + "required": true, + "type": "string" + } + ], + "responses": { + "202": { + "description": "The namespace has been marked for deletion. Cleanup of its classes, aliases, and users completes asynchronously." + }, + "401": { + "description": "Unauthorized or invalid credentials." + }, + "403": { + "description": "Forbidden", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "404": { + "description": "Not Found - Namespace does not exist, or the namespaces feature is not enabled on this cluster.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "422": { + "description": "The request syntax is correct, but the server couldn't process it due to semantic issues (e.g. invalid name format or reserved name).", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, + "500": { + "description": "An error has occurred while trying to fulfill the request. Most likely the ErrorResponse will contain more information about the error.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + } + }, "/backups/{backend}": { "post": { "summary": "Create a backup", @@ -9945,6 +10829,12 @@ "$ref": "#/definitions/ErrorResponse" } }, + "410": { + "description": "Endpoint not available in the current cluster configuration.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, "500": { "description": "An internal server error occurred while starting the classification task. Check the ErrorResponse for details.", "schema": { @@ -9993,6 +10883,12 @@ "404": { "description": "Classification with the given ID not found." }, + "410": { + "description": "Endpoint not available in the current cluster configuration.", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + }, "500": { "description": "An internal server error occurred while retrieving the classification status. Check the ErrorResponse for details.", "schema": { @@ -10117,6 +11013,10 @@ { "name": "mcp", "description": "Model Context Protocol (MCP) endpoint. Provides tool discovery and invocation for LLM agents via the MCP Streamable HTTP transport." + }, + { + "name": "namespaces", + "description": "Operations for managing cluster-level namespaces. Namespaces group resources under a common administrative unit. Access is gated by the operator-tier `manage_namespaces` action." } ] }