diff --git a/common/proto/table_definition.proto b/common/proto/table_definition.proto index bba0b921..b3f6d94e 100644 --- a/common/proto/table_definition.proto +++ b/common/proto/table_definition.proto @@ -58,6 +58,9 @@ service TableDefinition { // Returns the stored rename history for column aliases in one profile. rpc GetColumnAliasRenameHistory(GetColumnAliasRenameHistoryRequest) returns (GetColumnAliasRenameHistoryResponse); + // Returns the unified append-only history for column and option aliases. + rpc GetAliasChangeHistory(GetAliasChangeHistoryRequest) returns (GetAliasChangeHistoryResponse); + // Atomically replaces the aliases and presentation order of a table's columns. // Physical column names and identities remain unchanged. rpc SetColumnPresentation(SetColumnPresentationRequest) returns (SetColumnPresentationResponse); @@ -485,6 +488,43 @@ message GetColumnAliasRenameHistoryResponse { repeated ColumnAliasRenameHistoryEntry entries = 2; } +enum AliasChangeKind { + ALIAS_CHANGE_KIND_UNSPECIFIED = 0; + ALIAS_CHANGE_KIND_COLUMN = 1; + ALIAS_CHANGE_KIND_OPTION = 2; +} + +message GetAliasChangeHistoryRequest { + string profile_name = 1; + optional int64 table_definition_id = 2; + optional int64 column_id = 3; + AliasChangeKind alias_kind = 4; + optional string option_value = 5; + uint32 limit = 6; +} + +message AliasChangeHistoryEntry { + int64 id = 1; + string change_set_id = 2; + AliasChangeKind alias_kind = 3; + string profile_name = 4; + int64 table_definition_id = 5; + string table_name = 6; + optional int64 column_id = 7; + string column_name = 8; + optional string option_value = 9; + optional string old_alias = 10; + optional string new_alias = 11; + optional string changed_by_user_id = 12; + optional string changed_by_user_name = 13; + string changed_at = 14; +} + +message GetAliasChangeHistoryResponse { + string profile_name = 1; + repeated AliasChangeHistoryEntry entries = 2; +} + // Describes a table with its columns and associated scripts. message TableDetail { string name = 1; @@ -530,8 +570,8 @@ message ColumnBehavior { // This is not an authorization boundary; data APIs still expose the column. bool hidden_from_forms = 6; - // User-selected labels for stable option values. Empty means clients display - // the canonical value. Writes may submit either value or alias. + // Current public aliases for stable option values. Identity aliases equal the + // canonical value. Once renamed, public writes must use the current alias. repeated OptionValueAlias option_value_aliases = 7; } diff --git a/common/src/proto/descriptor.bin b/common/src/proto/descriptor.bin index d5dd41f1..f6f8374b 100644 Binary files a/common/src/proto/descriptor.bin and b/common/src/proto/descriptor.bin differ diff --git a/common/src/proto/komp_ac.table_definition.rs b/common/src/proto/komp_ac.table_definition.rs index a9e9ca17..b8b02056 100644 --- a/common/src/proto/komp_ac.table_definition.rs +++ b/common/src/proto/komp_ac.table_definition.rs @@ -485,6 +485,62 @@ pub struct GetColumnAliasRenameHistoryResponse { #[prost(message, repeated, tag = "2")] pub entries: ::prost::alloc::vec::Vec, } +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct GetAliasChangeHistoryRequest { + #[prost(string, tag = "1")] + pub profile_name: ::prost::alloc::string::String, + #[prost(int64, optional, tag = "2")] + pub table_definition_id: ::core::option::Option, + #[prost(int64, optional, tag = "3")] + pub column_id: ::core::option::Option, + #[prost(enumeration = "AliasChangeKind", tag = "4")] + pub alias_kind: i32, + #[prost(string, optional, tag = "5")] + pub option_value: ::core::option::Option<::prost::alloc::string::String>, + #[prost(uint32, tag = "6")] + pub limit: u32, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct AliasChangeHistoryEntry { + #[prost(int64, tag = "1")] + pub id: i64, + #[prost(string, tag = "2")] + pub change_set_id: ::prost::alloc::string::String, + #[prost(enumeration = "AliasChangeKind", tag = "3")] + pub alias_kind: i32, + #[prost(string, tag = "4")] + pub profile_name: ::prost::alloc::string::String, + #[prost(int64, tag = "5")] + pub table_definition_id: i64, + #[prost(string, tag = "6")] + pub table_name: ::prost::alloc::string::String, + #[prost(int64, optional, tag = "7")] + pub column_id: ::core::option::Option, + #[prost(string, tag = "8")] + pub column_name: ::prost::alloc::string::String, + #[prost(string, optional, tag = "9")] + pub option_value: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, optional, tag = "10")] + pub old_alias: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, optional, tag = "11")] + pub new_alias: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, optional, tag = "12")] + pub changed_by_user_id: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, optional, tag = "13")] + pub changed_by_user_name: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, tag = "14")] + pub changed_at: ::prost::alloc::string::String, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetAliasChangeHistoryResponse { + #[prost(string, tag = "1")] + pub profile_name: ::prost::alloc::string::String, + #[prost(message, repeated, tag = "2")] + pub entries: ::prost::alloc::vec::Vec, +} /// Describes a table with its columns and associated scripts. #[derive(serde::Serialize, serde::Deserialize)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -545,8 +601,8 @@ pub struct ColumnBehavior { /// This is not an authorization boundary; data APIs still expose the column. #[prost(bool, tag = "6")] pub hidden_from_forms: bool, - /// User-selected labels for stable option values. Empty means clients display - /// the canonical value. Writes may submit either value or alias. + /// Current public aliases for stable option values. Identity aliases equal the + /// canonical value. Once renamed, public writes must use the current alias. #[prost(message, repeated, tag = "7")] pub option_value_aliases: ::prost::alloc::vec::Vec, } @@ -900,6 +956,36 @@ impl BooleanLedgerOperator { } } } +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum AliasChangeKind { + Unspecified = 0, + Column = 1, + Option = 2, +} +impl AliasChangeKind { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Unspecified => "ALIAS_CHANGE_KIND_UNSPECIFIED", + Self::Column => "ALIAS_CHANGE_KIND_COLUMN", + Self::Option => "ALIAS_CHANGE_KIND_OPTION", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "ALIAS_CHANGE_KIND_UNSPECIFIED" => Some(Self::Unspecified), + "ALIAS_CHANGE_KIND_COLUMN" => Some(Self::Column), + "ALIAS_CHANGE_KIND_OPTION" => Some(Self::Option), + _ => None, + } + } +} /// How a column type is spelled in ColumnDefinition.field_type. #[derive(serde::Serialize, serde::Deserialize)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] @@ -1403,6 +1489,36 @@ pub mod table_definition_client { ); self.inner.unary(req, path, codec).await } + /// Returns the unified append-only history for column and option aliases. + pub async fn get_alias_change_history( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/komp_ac.table_definition.TableDefinition/GetAliasChangeHistory", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "komp_ac.table_definition.TableDefinition", + "GetAliasChangeHistory", + ), + ); + self.inner.unary(req, path, codec).await + } /// Atomically replaces the aliases and presentation order of a table's columns. /// Physical column names and identities remain unchanged. pub async fn set_column_presentation( @@ -1651,6 +1767,14 @@ pub mod table_definition_server { tonic::Response, tonic::Status, >; + /// Returns the unified append-only history for column and option aliases. + async fn get_alias_change_history( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; /// Atomically replaces the aliases and presentation order of a table's columns. /// Physical column names and identities remain unchanged. async fn set_column_presentation( @@ -2353,6 +2477,55 @@ pub mod table_definition_server { }; Box::pin(fut) } + "/komp_ac.table_definition.TableDefinition/GetAliasChangeHistory" => { + #[allow(non_camel_case_types)] + struct GetAliasChangeHistorySvc(pub Arc); + impl< + T: TableDefinition, + > tonic::server::UnaryService + for GetAliasChangeHistorySvc { + type Response = super::GetAliasChangeHistoryResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_alias_change_history( + &inner, + request, + ) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = GetAliasChangeHistorySvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } "/komp_ac.table_definition.TableDefinition/SetColumnPresentation" => { #[allow(non_camel_case_types)] struct SetColumnPresentationSvc(pub Arc); diff --git a/server b/server index 7bb3706e..1804c1dd 160000 --- a/server +++ b/server @@ -1 +1 @@ -Subproject commit 7bb3706ec6e670e1e7d6495d2f699d50a9bc41e3 +Subproject commit 1804c1dd19206ff3ac21f7a849807fb117dd0ad7