diff --git a/client b/client index 097aba8b..b36ef1de 160000 --- a/client +++ b/client @@ -1 +1 @@ -Subproject commit 097aba8b61146e44161aeaf01886b7c95218abd4 +Subproject commit b36ef1decba9a4ed5e965938372ae72036b5566c diff --git a/common/proto/accounting.proto b/common/proto/accounting.proto index e10f6f09..9eaadcb4 100644 --- a/common/proto/accounting.proto +++ b/common/proto/accounting.proto @@ -165,7 +165,7 @@ message JournalLineInput { string account = 2; string amount = 3; string description = 4; - // Empty uses previous publication and ECB. Set this per line when the + // Empty uses the profile provider's previous publication. Set this per line when the // accountant needs a different rule, a saved custom rate, or a one-off rate. optional komp_ac.exchange_rates.ExchangeRateSelection exchange_rate_selection = 5; } diff --git a/common/proto/exchange_rates.proto b/common/proto/exchange_rates.proto index ac377d5e..07589265 100644 --- a/common/proto/exchange_rates.proto +++ b/common/proto/exchange_rates.proto @@ -56,7 +56,7 @@ message PreviewDirectConversionResponse { optional string foreign_currency = 10; optional string foreign_units = 11; string source_id = 12; - optional int64 rate_observation_id = 13; + optional int64 official_observation_id = 13; optional string observation_hash = 14; optional string source_payload_hash = 15; optional string rate_fetched_at = 16; @@ -96,7 +96,7 @@ message ConversionEvidence { string rounding_method = 13; optional string rate_date = 14; string source_id = 15; - optional int64 rate_observation_id = 16; + optional int64 official_observation_id = 16; optional string observation_hash = 17; optional string source_payload_hash = 18; optional string rate_fetched_at = 19; diff --git a/common/proto/table_definition.proto b/common/proto/table_definition.proto index 138dc008..59f52604 100644 --- a/common/proto/table_definition.proto +++ b/common/proto/table_definition.proto @@ -105,7 +105,7 @@ message PostTableDefinitionRequest { string accounting_currency = 8; // Compiled direct-rate provider selected when the profile is created. - // Currently only "ecb" is available, and it requires EUR accounting. + // The server validates this identifier against its compiled provider registry. string rate_source_id = 11; // Append-only foreign currencies initially enabled for this profile. diff --git a/common/src/proto/descriptor.bin b/common/src/proto/descriptor.bin index 41a042a7..0b721938 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.accounting.rs b/common/src/proto/komp_ac.accounting.rs index b59eec42..c38af7d6 100644 --- a/common/src/proto/komp_ac.accounting.rs +++ b/common/src/proto/komp_ac.accounting.rs @@ -68,7 +68,7 @@ pub struct JournalLineInput { pub amount: ::prost::alloc::string::String, #[prost(string, tag = "4")] pub description: ::prost::alloc::string::String, - /// Empty uses previous publication and ECB. Set this per line when the + /// Empty uses the profile provider's previous publication. Set this per line when the /// accountant needs a different rule, a saved custom rate, or a one-off rate. #[prost(message, optional, tag = "5")] pub exchange_rate_selection: ::core::option::Option< diff --git a/common/src/proto/komp_ac.exchange_rates.rs b/common/src/proto/komp_ac.exchange_rates.rs index e4ff9888..0ea8af54 100644 --- a/common/src/proto/komp_ac.exchange_rates.rs +++ b/common/src/proto/komp_ac.exchange_rates.rs @@ -52,7 +52,7 @@ pub struct PreviewDirectConversionResponse { #[prost(string, tag = "12")] pub source_id: ::prost::alloc::string::String, #[prost(int64, optional, tag = "13")] - pub rate_observation_id: ::core::option::Option, + pub official_observation_id: ::core::option::Option, #[prost(string, optional, tag = "14")] pub observation_hash: ::core::option::Option<::prost::alloc::string::String>, #[prost(string, optional, tag = "15")] @@ -126,7 +126,7 @@ pub struct ConversionEvidence { #[prost(string, tag = "15")] pub source_id: ::prost::alloc::string::String, #[prost(int64, optional, tag = "16")] - pub rate_observation_id: ::core::option::Option, + pub official_observation_id: ::core::option::Option, #[prost(string, optional, tag = "17")] pub observation_hash: ::core::option::Option<::prost::alloc::string::String>, #[prost(string, optional, tag = "18")] diff --git a/common/src/proto/komp_ac.table_definition.rs b/common/src/proto/komp_ac.table_definition.rs index 0a96ce46..c4456156 100644 --- a/common/src/proto/komp_ac.table_definition.rs +++ b/common/src/proto/komp_ac.table_definition.rs @@ -52,7 +52,7 @@ pub struct PostTableDefinitionRequest { #[prost(string, tag = "8")] pub accounting_currency: ::prost::alloc::string::String, /// Compiled direct-rate provider selected when the profile is created. - /// Currently only "ecb" is available, and it requires EUR accounting. + /// The server validates this identifier against its compiled provider registry. #[prost(string, tag = "11")] pub rate_source_id: ::prost::alloc::string::String, /// Append-only foreign currencies initially enabled for this profile. diff --git a/server b/server index b929f654..d21be00a 160000 --- a/server +++ b/server @@ -1 +1 @@ -Subproject commit b929f654ed1f4443967fd959ee8e6b5213d45c10 +Subproject commit d21be00ac243bd9b16a855f9acab7dec5b2e88af diff --git a/web/src/authz.rs b/web/src/authz.rs index cbae399b..42d43931 100644 --- a/web/src/authz.rs +++ b/web/src/authz.rs @@ -12,7 +12,7 @@ pub(crate) const READ: &str = "read"; /// Every ECB object, which is what the pipeline status is checked against: /// one importer feeds every profile, so reading its health is not a /// per-profile question. -pub(crate) const ALL_ECB: &str = "ecb:*"; +pub(crate) const ALL_EXCHANGE_RATES: &str = "exchange-rates:*"; /// The two bulk-transfer actions, mirroring /// `server/src/auth/rbac/objects.rs`. Taking a whole table out as a file is @@ -44,8 +44,8 @@ pub(crate) fn can_manage(snapshot: &AuthorizationSnapshot, area: &str) -> bool { /// Whether the caller may see the reference-rate pipeline. Mirrors the /// server's own check in `server/src/ecb/grpc.rs`. -pub(crate) fn can_read_ecb(snapshot: &AuthorizationSnapshot) -> bool { - permits(snapshot, ALL_ECB, READ) +pub(crate) fn can_read_exchange_rates(snapshot: &AuthorizationSnapshot) -> bool { + permits(snapshot, ALL_EXCHANGE_RATES, READ) } /// Whether the caller holds a transfer action on any table at all — what the diff --git a/web/src/pages/add_table/draft.rs b/web/src/pages/add_table/draft.rs index e726d400..f67e49a4 100644 --- a/web/src/pages/add_table/draft.rs +++ b/web/src/pages/add_table/draft.rs @@ -97,8 +97,8 @@ impl TableDraft { /// thing that knows it. pub(crate) fn new() -> Self { Self { - accounting_currency: "EUR".to_string(), - rate_source_id: "ecb".to_string(), + accounting_currency: String::new(), + rate_source_id: String::new(), columns: ColumnDraft::new(ColumnCatalog::default()), ..Self::default() } diff --git a/web/src/pages/admin/admin/loader.rs b/web/src/pages/admin/admin/loader.rs index c6eae4f1..491bfd46 100644 --- a/web/src/pages/admin/admin/loader.rs +++ b/web/src/pages/admin/admin/loader.rs @@ -182,7 +182,7 @@ pub(crate) async fn load_admin_page( can_manage_validations: crate::authz::can_manage(&authorization, crate::authz::STRUCT_VALIDATION), can_import: crate::authz::can_transfer_anything(&authorization, crate::authz::IMPORT), can_export: crate::authz::can_transfer_anything(&authorization, crate::authz::EXPORT), - can_ecb: crate::authz::can_read_ecb(&authorization), + can_exchange_rates: crate::authz::can_read_exchange_rates(&authorization), }) } diff --git a/web/src/pages/admin/admin/state.rs b/web/src/pages/admin/admin/state.rs index 04d50ac2..4b3497fb 100644 --- a/web/src/pages/admin/admin/state.rs +++ b/web/src/pages/admin/admin/state.rs @@ -28,7 +28,7 @@ pub(crate) struct AdminPageState { /// Whether the exchange-rate pipeline is visible to this caller. Not a /// structural area: it is granted through the ECB object, like the /// conversions it reports on. - pub can_ecb: bool, + pub can_exchange_rates: bool, } impl AdminPageState { diff --git a/web/src/pages/admin/admin/ui.rs b/web/src/pages/admin/admin/ui.rs index b3812080..3c8b4fce 100644 --- a/web/src/pages/admin/admin/ui.rs +++ b/web/src/pages/admin/admin/ui.rs @@ -64,7 +64,7 @@ mod tests { can_permissions: true, can_import: false, can_export: false, - can_ecb: false, + can_exchange_rates: false, active: "admin", }; let page = AdminPageState { @@ -80,7 +80,7 @@ mod tests { can_manage_validations: true, can_import: true, can_export: true, - can_ecb: true, + can_exchange_rates: true, }; let html = render_page(&page); for route in [ @@ -126,7 +126,7 @@ mod tests { can_manage_validations: true, can_import: true, can_export: true, - can_ecb: true, + can_exchange_rates: true, }; let html = render_workspace(&page); @@ -163,7 +163,7 @@ mod tests { can_manage_validations: true, can_import: true, can_export: true, - can_ecb: true, + can_exchange_rates: true, }; let html = render_workspace(&page); @@ -203,7 +203,7 @@ mod tests { can_manage_validations: true, can_import: true, can_export: true, - can_ecb: true, + can_exchange_rates: true, }; let html = render_workspace(&page); @@ -242,7 +242,7 @@ mod tests { can_manage_validations: true, can_import: true, can_export: true, - can_ecb: true, + can_exchange_rates: true, }; let html = render_workspace(&page); diff --git a/web/src/pages/admin/ecb/loader.rs b/web/src/pages/admin/ecb/loader.rs index 43ee1be9..d0fee580 100644 --- a/web/src/pages/admin/ecb/loader.rs +++ b/web/src/pages/admin/ecb/loader.rs @@ -37,7 +37,7 @@ pub(crate) async fn load_ecb_page( })? .into_inner(); - if !crate::authz::can_read_ecb(&authorization) { + if !crate::authz::can_read_exchange_rates(&authorization) { return Err(LoadError::Forbidden); } diff --git a/web/src/pages/permissions/grants/state.rs b/web/src/pages/permissions/grants/state.rs index 300dea95..e905684e 100644 --- a/web/src/pages/permissions/grants/state.rs +++ b/web/src/pages/permissions/grants/state.rs @@ -59,7 +59,7 @@ pub(crate) struct RoleOption { /// The objects of one profile, or the wildcards that cover every profile. pub(crate) struct ObjectGroup { pub title: String, - /// The `data:*` / `journal:*` / `ecb:*` group, which is the one whose + /// The `data:*` / `journal:*` / `exchange-rates:*` group, which is the one whose /// shortcuts mean "everything, including what is created later". pub global: bool, pub rows: Vec, @@ -228,7 +228,7 @@ mod tests { cells: cells(&ACTIONS, &["read"]), }, ObjectRow { - object: "ecb:acme".to_string(), + object: "exchange-rates:acme".to_string(), label: "ECB rates".to_string(), note: String::new(), wildcard: true, @@ -259,12 +259,12 @@ mod tests { "data:acme/*|delete", "data:acme/*|export", "data:acme/*|import", - "ecb:acme|read", + "exchange-rates:acme|read", ] ); assert_eq!( group.read_pairs(), - vec!["data:acme/*|read", "ecb:acme|read"] + vec!["data:acme/*|read", "exchange-rates:acme|read"] ); } diff --git a/web/src/pages/permissions/grants/ui.rs b/web/src/pages/permissions/grants/ui.rs index d859f885..60dd5d58 100644 --- a/web/src/pages/permissions/grants/ui.rs +++ b/web/src/pages/permissions/grants/ui.rs @@ -49,7 +49,7 @@ mod tests { can_permissions: true, can_import: false, can_export: false, - can_ecb: true, + can_exchange_rates: true, active: "permissions", }, tabs: Tabs { diff --git a/web/src/pages/permissions/roles/state.rs b/web/src/pages/permissions/roles/state.rs index 11d7673c..d80b12ba 100644 --- a/web/src/pages/permissions/roles/state.rs +++ b/web/src/pages/permissions/roles/state.rs @@ -82,10 +82,10 @@ pub(crate) fn starter_grants( "read" => Ok(vec![ ("data:*", "read"), ("journal:*", "read"), - ("ecb:*", "read"), + ("exchange-rates:*", "read"), ]), "full" => { - let mut grants = vec![("ecb:*", "read")]; + let mut grants = vec![("exchange-rates:*", "read")]; for object in ["data:*", "journal:*"] { for action in ["read", "insert", "update", "delete"] { grants.push((object, action)); @@ -120,7 +120,7 @@ mod tests { assert!( grants .iter() - .all(|(object, action)| *object != "ecb:*" || *action == "read"), + .all(|(object, action)| *object != "exchange-rates:*" || *action == "read"), "{level} granted a write on ECB rates" ); } diff --git a/web/src/pages/permissions/roles/ui.rs b/web/src/pages/permissions/roles/ui.rs index 87190f82..b8bfbaac 100644 --- a/web/src/pages/permissions/roles/ui.rs +++ b/web/src/pages/permissions/roles/ui.rs @@ -38,7 +38,7 @@ mod tests { can_permissions: true, can_import: false, can_export: false, - can_ecb: true, + can_exchange_rates: true, active: "permissions", }, tabs: Tabs { diff --git a/web/src/pages/permissions/users/ui.rs b/web/src/pages/permissions/users/ui.rs index ba7ee3d1..4e84f9b8 100644 --- a/web/src/pages/permissions/users/ui.rs +++ b/web/src/pages/permissions/users/ui.rs @@ -38,7 +38,7 @@ mod tests { can_permissions: true, can_import: false, can_export: false, - can_ecb: true, + can_exchange_rates: true, active: "permissions", }, tabs: Tabs { diff --git a/web/src/ui/mod.rs b/web/src/ui/mod.rs index d7a268f1..d20f2515 100644 --- a/web/src/ui/mod.rs +++ b/web/src/ui/mod.rs @@ -112,7 +112,7 @@ pub(crate) struct Nav { pub can_permissions: bool, pub can_import: bool, pub can_export: bool, - pub can_ecb: bool, + pub can_exchange_rates: bool, pub active: &'static str, } @@ -164,7 +164,7 @@ impl Nav { crate::authz::can_transfer_anything(authorization, crate::authz::IMPORT); nav.can_export = crate::authz::can_transfer_anything(authorization, crate::authz::EXPORT); - nav.can_ecb = crate::authz::can_read_ecb(authorization); + nav.can_exchange_rates = crate::authz::can_read_exchange_rates(authorization); nav } @@ -185,7 +185,7 @@ impl Nav { can_permissions: false, can_import: false, can_export: false, - can_ecb: false, + can_exchange_rates: false, active, } } @@ -268,7 +268,7 @@ impl Default for Nav { can_permissions: false, can_import: false, can_export: false, - can_ecb: false, + can_exchange_rates: false, active: "", } } diff --git a/web/templates/pages/add_table/builder.html b/web/templates/pages/add_table/builder.html index e76ed268..b539ea83 100644 --- a/web/templates/pages/add_table/builder.html +++ b/web/templates/pages/add_table/builder.html @@ -80,18 +80,12 @@ {% if page.draft.show_accounting_currency() %}