1035 lines
38 KiB
Protocol Buffer
1035 lines
38 KiB
Protocol Buffer
// common/proto/table_definition.proto
|
|
syntax = "proto3";
|
|
package komp_ac.table_definition;
|
|
|
|
import "common.proto";
|
|
|
|
// The TableDefinition service manages the entire lifecycle of user-defined
|
|
// tables (stored as both metadata and physical PostgreSQL tables) inside
|
|
// logical "profiles" (schemas). Each table has stored structure, links, and
|
|
// validation rules.
|
|
service TableDefinition {
|
|
// Creates a profile with default modules and managed structures, without a user table.
|
|
rpc CreateProfile(CreateProfileRequest) returns (CreateProfileResponse);
|
|
|
|
rpc GetModuleConfiguration(GetModuleConfigurationRequest) returns (ModuleConfiguration);
|
|
rpc SetModuleConfiguration(SetModuleConfigurationRequest) returns (ModuleConfiguration);
|
|
|
|
// Creates a new table (and schema if missing) with system columns,
|
|
// linked-table foreign keys, user-defined columns, and optional indexes.
|
|
// Also inserts metadata and default validation rules. Entirely transactional.
|
|
rpc PostTableDefinition(PostTableDefinitionRequest) returns (TableDefinitionResponse);
|
|
|
|
// Explicitly creates the optional administrator-managed exchange-rate table
|
|
// in an existing profile. The server owns its core shape and constraints.
|
|
rpc CreateCustomExchangeRatesTable(CreateCustomExchangeRatesTableRequest) returns (CreateCustomExchangeRatesTableResponse);
|
|
|
|
// Creates a regular user-table bundle from the restricted komp_ac_fields
|
|
// contract embedded in a Typst invoice template. This is invoked explicitly
|
|
// by the user; templates do not provision tables merely by existing.
|
|
rpc CreateInvoiceTemplateTable(CreateInvoiceTemplateTableRequest) returns (CreateInvoiceTemplateTableResponse);
|
|
|
|
// Applies the administrator-reviewed, explicitly typed table bundle and
|
|
// exact komp_ac_fields bindings for an imported Typst template.
|
|
rpc ApplyInvoiceTemplateTable(ApplyInvoiceTemplateTableRequest) returns (CreateInvoiceTemplateTableResponse);
|
|
|
|
// Appends new user-defined columns to an existing table.
|
|
// Existing columns, links, and table logic are never changed by this call.
|
|
rpc AddTableColumns(AddTableColumnsRequest) returns (TableDefinitionResponse);
|
|
|
|
// Atomically removes selected columns and appends new columns to an empty
|
|
// dynamic table. Column identities come from GetProfileDetails. The call is
|
|
// rejected after any row, including a soft-deleted row, has been stored.
|
|
rpc PutTableDefinition(PutTableDefinitionRequest) returns (PutTableDefinitionResponse);
|
|
|
|
// Lists all profiles (schemas) and their tables with declared dependencies.
|
|
// This provides a tree-like overview of table relationships.
|
|
rpc GetProfileTree(komp_ac.common.Empty) returns (ProfileTreeResponse);
|
|
|
|
// Lists the tables visible in one data-entry scope. When profile_name is
|
|
// absent, only global tables are returned.
|
|
rpc GetTableCatalog(GetTableCatalogRequest) returns (GetTableCatalogResponse);
|
|
|
|
// Lists every column type a table may declare, along with the SQL type it
|
|
// maps to. Pure data retrieval - no business logic.
|
|
rpc ListColumnTypes(komp_ac.common.Empty) returns (ListColumnTypesResponse);
|
|
|
|
// Fetches all tables with their columns and scripts for a specific profile.
|
|
// Pure data retrieval - no business logic.
|
|
rpc GetProfileDetails(GetProfileDetailsRequest) returns (GetProfileDetailsResponse);
|
|
|
|
// Copies one complete profile into a new profile without copying table data.
|
|
rpc CopyProfile(CopyProfileRequest) returns (CopyProfileResponse);
|
|
|
|
// Serializes selected table structure and every required structural dependency.
|
|
// Dynamic table rows and deployment-local security state are never included.
|
|
rpc ExportProfileBlueprint(ExportProfileBlueprintRequest) returns (ExportProfileBlueprintResponse);
|
|
|
|
// Reconciles a portable blueprint against a destination profile without writing.
|
|
rpc PlanProfileBlueprintImport(PlanProfileBlueprintImportRequest) returns (PlanProfileBlueprintImportResponse);
|
|
|
|
// Applies a previously reviewed blueprint plan atomically. The plan hash protects
|
|
// against both a changed package and destination drift between preview and apply.
|
|
rpc ImportProfileBlueprint(ImportProfileBlueprintRequest) returns (ImportProfileBlueprintResponse);
|
|
|
|
// 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);
|
|
|
|
// Replaces the columns whose values identify rows to users. This is
|
|
// presentation metadata and may be changed after rows have been stored.
|
|
rpc SetRowDisplayColumns(SetRowDisplayColumnsRequest) returns (SetRowDisplayColumnsResponse);
|
|
|
|
// Replaces the user-managed indexes of an existing dynamic table. Physical
|
|
// indexes are created or dropped even when rows have already been stored.
|
|
rpc SetTableIndexes(SetTableIndexesRequest) returns (SetTableIndexesResponse);
|
|
|
|
// Changes whether one existing column is required. Enabling the requirement
|
|
// is rejected while an active row has no value for the column.
|
|
rpc SetColumnRequired(SetColumnRequiredRequest) returns (SetColumnRequiredResponse);
|
|
|
|
// Clear selected profile overrides and apply the current module defaults atomically.
|
|
rpc ResetModuleDefaults(ResetModuleDefaultsRequest) returns (ResetModuleDefaultsResponse);
|
|
|
|
// Replaces the optional user-visible aliases for a fixed-option column.
|
|
// Stored values remain stable machine values and scripts never depend on labels.
|
|
rpc SetColumnOptionAliases(SetColumnOptionAliasesRequest) returns (SetColumnOptionAliasesResponse);
|
|
|
|
// Shows or hides one column in bundled data-entry forms. This is presentation
|
|
// metadata only: hidden columns remain available to data APIs, scripts and
|
|
// backend calculations.
|
|
rpc SetColumnFormVisibility(SetColumnFormVisibilityRequest) returns (SetColumnFormVisibilityResponse);
|
|
|
|
// Drops a table and its metadata, then deletes the profile if it becomes empty.
|
|
rpc DeleteTable(DeleteTableRequest) returns (DeleteTableResponse);
|
|
|
|
// Deletes an entire profile only when none of its user or backend-managed
|
|
// tables, audit stores, document stores, or accounting stores contain data.
|
|
rpc DeleteProfile(DeleteProfileRequest) returns (DeleteProfileResponse);
|
|
}
|
|
|
|
message CreateProfileRequest {
|
|
string profile_name = 1;
|
|
// Omit to leave the bookkeeping currency unconfigured.
|
|
optional string accounting_currency = 2;
|
|
}
|
|
|
|
message CreateProfileResponse {
|
|
int64 profile_id = 1;
|
|
}
|
|
|
|
message ModuleScope {
|
|
oneof target {
|
|
komp_ac.common.Empty defaults = 1;
|
|
string profile_name = 2;
|
|
}
|
|
}
|
|
|
|
// A missing profile returns the defaults that would be copied on ordinary creation.
|
|
message GetModuleConfigurationRequest {
|
|
ModuleScope scope = 1;
|
|
}
|
|
|
|
// Profile updates require an existing profile. Defaults affect future profiles only.
|
|
message SetModuleConfigurationRequest {
|
|
ModuleScope scope = 1;
|
|
repeated string enabled_modules = 2;
|
|
// Initializes an existing profile's bookkeeping currency. Empty leaves it unchanged.
|
|
// Defaults scope and changes to an already configured currency are rejected.
|
|
string accounting_currency = 3;
|
|
repeated ModuleDataAccessUpdate data_access_updates = 4;
|
|
}
|
|
|
|
message ModuleConfiguration {
|
|
ModuleScope scope = 1;
|
|
repeated string available_modules = 2;
|
|
repeated string selected_modules = 3;
|
|
repeated string effective_modules = 5;
|
|
string accounting_currency = 6;
|
|
repeated ModuleDataAccessRequest data_access_requests = 7;
|
|
}
|
|
|
|
message ModuleDataExportId {
|
|
string providing_module = 1;
|
|
string name = 2;
|
|
uint32 version = 3;
|
|
}
|
|
|
|
message ModuleDataExport {
|
|
ModuleDataExportId id = 1;
|
|
string description = 2;
|
|
map<string, string> translations = 3;
|
|
}
|
|
|
|
enum ModuleDataAccessDecision {
|
|
MODULE_DATA_ACCESS_DECISION_UNSPECIFIED = 0;
|
|
MODULE_DATA_ACCESS_DECISION_ALLOW = 1;
|
|
MODULE_DATA_ACCESS_DECISION_REVOKE = 2;
|
|
}
|
|
|
|
message ModuleDataAccessRequest {
|
|
string requesting_module = 1;
|
|
reserved 2, 3;
|
|
ModuleDataExport data_export = 5;
|
|
bool granted = 4;
|
|
}
|
|
|
|
message ModuleDataAccessUpdate {
|
|
string requesting_module = 1;
|
|
reserved 2;
|
|
ModuleDataExportId export_id = 4;
|
|
ModuleDataAccessDecision decision = 3;
|
|
}
|
|
|
|
message CreateCustomExchangeRatesTableRequest {
|
|
string profile_name = 1;
|
|
}
|
|
|
|
message CreateCustomExchangeRatesTableResponse {
|
|
int64 table_definition_id = 1;
|
|
bool created = 2;
|
|
}
|
|
|
|
// Defines the input for creating a new table definition.
|
|
message PostTableDefinitionRequest {
|
|
// Table name to create inside the target profile.
|
|
// Must be lowercase, alphanumeric with underscores,
|
|
// start with a letter, and be <= 63 chars.
|
|
// Forbidden names include the system columns and tables owned by dedicated
|
|
// server operations, such as "custom_exchange_rates". The "_id" suffix is
|
|
// allowed.
|
|
string table_name = 1;
|
|
|
|
// The table's columns, including its links and stored linked values.
|
|
// A linked value uses ColumnDefinition.linked_value; its physical type and
|
|
// money metadata are inferred from the linked source column.
|
|
repeated ColumnDefinition columns = 3;
|
|
|
|
// Column names to index, matching names declared above. System columns
|
|
// ("id", "deleted", "created_at", "row_revision") already have indexes, and
|
|
// a LINK column is indexed when it is created. Requests naming either are
|
|
// rejected.
|
|
repeated string indexes = 4;
|
|
|
|
// Name of profile (Postgres schema) where the table will be created.
|
|
// Same naming rules as table_name; cannot collide with reserved schemas
|
|
// like "public", "information_schema", or ones starting with "pg_".
|
|
string profile_name = 5;
|
|
|
|
// Columns whose values identify a row to users in pickers, in the order
|
|
// they are shown. Each must name one of the user-defined columns above.
|
|
// Empty means the row is identified by its id alone.
|
|
repeated string row_display_columns = 7;
|
|
|
|
// Default ISO-4217 currency for this table's MONEY columns. Explicit column
|
|
// currencies take precedence; when omitted, the profile currency is used.
|
|
// The resolved default is saved for columns added later. When this request
|
|
// creates a profile, it also initializes that profile's bookkeeping currency.
|
|
// Supplying a table default never changes an existing profile's currency.
|
|
string accounting_currency = 8;
|
|
|
|
// Initial compiled direct-rate provider. It is enabled for each initial
|
|
// foreign currency below; more provider/currency bindings may be appended later.
|
|
string rate_source_id = 11;
|
|
|
|
// Append-only foreign currencies initially enabled for this profile.
|
|
repeated string foreign_currencies = 12;
|
|
|
|
// When true, the table is stored once in the global physical schema and is
|
|
// visible from every profile. profile_name is ignored.
|
|
bool global = 9;
|
|
|
|
// Names for the columns a definition row generates, in place of the ones the
|
|
// backend would give them. See GeneratedColumnAlias.
|
|
repeated GeneratedColumnAlias generated_aliases = 10;
|
|
|
|
}
|
|
|
|
// Renames one column a definition row generates, at the moment it is created.
|
|
//
|
|
// A generated column cannot be named in the column list -- the definition row
|
|
// is required to be named after its own type, and what it expands into is the
|
|
// backend's to decide. The name is only ever a display name over a physical
|
|
// column, though, so it is free to be anything: this is where that choice is
|
|
// made, instead of a SetColumnPresentation call afterwards.
|
|
//
|
|
// ACCOUNTING, PHONE and IBAN generated columns may be renamed: their
|
|
// relationships are recorded by physical column, so the rest of the system can
|
|
// find them without knowing their display names. ACCOUNTING_TRANSFER connectors
|
|
// are the exception and are refused here exactly as SetColumnPresentation refuses
|
|
// them.
|
|
message GeneratedColumnAlias {
|
|
// The name the backend would otherwise give the column: one of ACCOUNTING's
|
|
// "name", "tax_point_date", "debit", "credit" or "account", or a PHONE or
|
|
// IBAN companion such as "work_phone_ext". Must name a column the request
|
|
// really generates -- an alias for anything else is rejected rather than
|
|
// ignored, so a typo cannot pass silently.
|
|
string generated_name = 1;
|
|
|
|
// What the column should be called instead. Preserved exactly for display.
|
|
// Aliases may contain Unicode letters, numbers, spaces, punctuation and
|
|
// symbols, but not leading/trailing whitespace or control characters, and
|
|
// are limited to 63 UTF-8 bytes. Uniqueness and lookup use a compatibility-
|
|
// normalized, Unicode-case-folded key that collapses whitespace and ignores
|
|
// emoji while keeping punctuation significant.
|
|
string alias = 2;
|
|
}
|
|
|
|
// Defines the input for explicitly creating tables backed by one invoice
|
|
// Enables a stored global Typst template for one profile and immediately
|
|
// creates the input-table family declared by that template.
|
|
message CreateInvoiceTemplateTableRequest {
|
|
string profile_name = 1;
|
|
string template_name = 2;
|
|
repeated string row_display_columns = 3;
|
|
}
|
|
|
|
message ApplyInvoiceTemplateTableRequest {
|
|
string profile_name = 1;
|
|
string template_name = 2;
|
|
repeated InvoiceTemplateTableDefinition tables = 3;
|
|
repeated InvoiceTemplateFieldBinding field_bindings = 4;
|
|
|
|
// The immutable version whose komp_ac_fields the administrator mapped.
|
|
// Applying never silently switches to a newer version with a different
|
|
// contract between inspection and submission.
|
|
int64 template_version_id = 5;
|
|
}
|
|
|
|
// One administrator-designed table in the template input bundle. The empty
|
|
// collection_path is the root; a path ending in [] owns that repeated scope.
|
|
// The nested table definition retains every normal table option, including
|
|
// ACCOUNTING, generated aliases, ledgers, indexes, links and display columns.
|
|
message InvoiceTemplateTableDefinition {
|
|
string collection_path = 1;
|
|
PostTableDefinitionRequest definition = 2;
|
|
}
|
|
|
|
enum InvoiceTemplateAccountingRole {
|
|
INVOICE_TEMPLATE_ACCOUNTING_ROLE_UNSPECIFIED = 0;
|
|
INVOICE_TEMPLATE_ACCOUNTING_NAME = 1;
|
|
INVOICE_TEMPLATE_ACCOUNTING_TAX_POINT_DATE = 2;
|
|
INVOICE_TEMPLATE_ACCOUNTING_ACCOUNT = 3;
|
|
INVOICE_TEMPLATE_ACCOUNTING_DEBIT = 4;
|
|
INVOICE_TEMPLATE_ACCOUNTING_CREDIT = 5;
|
|
}
|
|
|
|
// Maps one path from komp_ac_fields to one table column. A regular binding
|
|
// names a declared column. An accounting binding names a semantic generated
|
|
// role, so aliases and the order of Typst fields cannot change its meaning.
|
|
message InvoiceTemplateFieldBinding {
|
|
string field_path = 1;
|
|
string collection_path = 2;
|
|
string column_name = 3;
|
|
InvoiceTemplateAccountingRole accounting_role = 4;
|
|
|
|
// Optional source reached through column_name when that column is a LINK.
|
|
// Both names are empty for a value stored directly on the invoice table.
|
|
string source_table_name = 5;
|
|
string source_column_name = 6;
|
|
}
|
|
|
|
// One physical dynamic table created for an invoice template scope. The root
|
|
// has an empty collection_path and parent_table_name. Each [] scope names its
|
|
// collection and the generated table that owns those repeated rows.
|
|
message GeneratedInvoiceTemplateTable {
|
|
string table_name = 1;
|
|
string collection_path = 2;
|
|
string parent_table_name = 3;
|
|
string sql = 4;
|
|
}
|
|
|
|
// Reports the complete table bundle created from one invoice template.
|
|
message CreateInvoiceTemplateTableResponse {
|
|
bool success = 1;
|
|
repeated GeneratedInvoiceTemplateTable tables = 2;
|
|
int64 template_version_id = 3;
|
|
}
|
|
|
|
// Defines append-only column additions for an existing table.
|
|
message AddTableColumnsRequest {
|
|
// Existing profile/schema name.
|
|
string profile_name = 1;
|
|
|
|
// Existing table name in the profile.
|
|
string table_name = 2;
|
|
|
|
// New user-defined columns only. Existing columns cannot be changed here.
|
|
// Stored linked values use ColumnDefinition.linked_value.
|
|
repeated ColumnDefinition columns = 3;
|
|
|
|
// Optional indexes for the new columns only.
|
|
repeated string indexes = 4;
|
|
|
|
// Names for the columns the appended definition rows generate, exactly as on
|
|
// PostTableDefinitionRequest.
|
|
repeated GeneratedColumnAlias generated_aliases = 5;
|
|
|
|
}
|
|
|
|
// One atomic structural edit to an existing empty table.
|
|
//
|
|
// Removals use stable column IDs rather than aliases. Generated companion
|
|
// columns must be removed together with their generating column. New columns
|
|
// follow the same contract as AddTableColumns.
|
|
message PutTableDefinitionRequest {
|
|
string profile_name = 1;
|
|
string table_name = 2;
|
|
repeated int64 remove_column_ids = 3;
|
|
repeated ColumnDefinition add_columns = 4;
|
|
repeated string add_indexes = 5;
|
|
repeated GeneratedColumnAlias generated_aliases = 6;
|
|
|
|
// Revision returned by GetProfileDetails. Prevents a stale editor from
|
|
// overwriting a newer structural or presentation change.
|
|
int64 expected_row_version = 7;
|
|
|
|
// New physical/catalog name. Empty, or equal to table_name, keeps the
|
|
// current name for backwards-compatible callers.
|
|
string new_table_name = 8;
|
|
}
|
|
|
|
message PutTableDefinitionResponse {
|
|
bool success = 1;
|
|
string sql = 2;
|
|
int64 row_version = 3;
|
|
repeated int64 removed_column_ids = 4;
|
|
}
|
|
|
|
enum MoneyRounding {
|
|
MONEY_ROUNDING_NONE = 0;
|
|
MONEY_ROUNDING_HALF_UP = 1;
|
|
}
|
|
|
|
// Describes one user-defined column for a table.
|
|
message ColumnDefinition {
|
|
// Public display name for this column; the physical column uses a stable
|
|
// server-assigned ordinal name. Preserved exactly for display. It may contain
|
|
// Unicode letters, numbers, spaces, punctuation and symbols, but not
|
|
// leading/trailing whitespace or control characters, and is limited to 63
|
|
// UTF-8 bytes. Its canonical form must be unique within the table and cannot
|
|
// claim a reserved system-column name.
|
|
string name = 1;
|
|
|
|
// Logical column type. Supported values (case-insensitive):
|
|
// TEXT
|
|
// BOOLEAN
|
|
// INSTANT (local input resolved in the authenticated user's timezone
|
|
// and displayed in the viewer timezone)
|
|
// USER_DATETIME (local input resolved in the user's timezone)
|
|
// RAW_DATETIME (timezone-free civil datetime)
|
|
// PHONE (international or national phone number; generates extension/type/country/calling-code companions)
|
|
// TIME (timezone-free time of day)
|
|
// MONEY (= unconstrained NUMERIC; currency is declared below)
|
|
// ACCOUNT_STATEMENT_CLASS (A = assets, P = equity and liabilities,
|
|
// N = expenses, V = revenue)
|
|
// ACCOUNTING (creates schema-managed name, account, debit, and credit fields;
|
|
// account always selects a row from the profile's managed ledger_accounts table;
|
|
// name is limited to 10 characters and one stored row contributes
|
|
// one line to the profile journal)
|
|
// ACCOUNTING_TRANSFER (creates automatic source-period/account/book/
|
|
// denomination fields and writable target equivalents; one
|
|
// table may contain only one accounting transfer definition)
|
|
// INT
|
|
// BIGINT
|
|
// DATE
|
|
// DURATION
|
|
// PERIOD
|
|
// LINK(table) → BIGINT referencing that table in the same profile, indexed
|
|
// automatically. A table may hold several links to the same
|
|
// target as long as the columns are named differently.
|
|
string field_type = 2;
|
|
|
|
// MONEY rounding applied before a value is stored.
|
|
MoneyRounding rounding = 3;
|
|
|
|
// When true, this numeric column is server-owned and projected
|
|
// from quantity-ledger contributions.
|
|
bool quantity_ledger = 4;
|
|
|
|
// Canonical uppercase ISO-4217 currency code. MONEY inherits the table/profile
|
|
// default when omitted. Forbidden for field types without currency support.
|
|
string currency = 5;
|
|
|
|
// When true, the server rejects omitted or explicitly null values.
|
|
bool required = 6;
|
|
|
|
// Enables a Boolean ledger on Boolean columns. ANY means
|
|
// one true contribution wins; ALL means one false contribution wins.
|
|
BooleanLedgerOperator boolean_ledger = 7;
|
|
|
|
// Defines this named column as a stored, read-only value copied through an
|
|
// existing LINK column. field_type and money metadata are inferred from the
|
|
// source column and must not be supplied by the caller.
|
|
optional LinkedValueDefinition linked_value = 8;
|
|
}
|
|
|
|
message LinkedValueDefinition {
|
|
// Exact display name of a LINK column in the table being defined.
|
|
string link_column = 1;
|
|
|
|
// Exact display name of an atomic column in the linked table.
|
|
string source_column = 2;
|
|
}
|
|
|
|
enum BooleanLedgerOperator {
|
|
BOOLEAN_LEDGER_OPERATOR_UNSPECIFIED = 0;
|
|
BOOLEAN_LEDGER_OPERATOR_ANY = 1;
|
|
BOOLEAN_LEDGER_OPERATOR_ALL = 2;
|
|
}
|
|
|
|
// Response after table creation (success + DDL preview).
|
|
message TableDefinitionResponse {
|
|
// True if all DB changes and metadata inserts succeeded.
|
|
bool success = 1;
|
|
|
|
// The actual SQL executed: CREATE TABLE + CREATE INDEX statements.
|
|
string sql = 2;
|
|
}
|
|
|
|
// Describes the tree of all profiles and their tables.
|
|
message ProfileTreeResponse {
|
|
// One link: the table it points at, and the column carrying it.
|
|
message Dependency {
|
|
// Table being referenced.
|
|
string table_name = 1;
|
|
|
|
// Column holding the reference, named by whoever declared the link. This
|
|
// is what identifies the link, since a table may point at one target
|
|
// several times.
|
|
string column_name = 2;
|
|
}
|
|
|
|
// Table entry in a profile.
|
|
message Table {
|
|
// Internal ID from table_definitions.id (metadata record).
|
|
int64 id = 1;
|
|
|
|
// Table name within the profile (schema).
|
|
string name = 2;
|
|
|
|
// Links this table declares. One entry per link, so a table that names the
|
|
// same target twice appears twice.
|
|
repeated Dependency depends_on = 3;
|
|
|
|
// Columns whose values make up the human-readable row label, in order.
|
|
repeated string row_display_columns = 4;
|
|
|
|
// "dynamic" for user-defined tables, "system" for backend-managed tables.
|
|
ManagedTableKind table_kind = 5;
|
|
|
|
// True when this table is shared by every profile.
|
|
bool global = 6;
|
|
|
|
// Profile (schema) the table is actually stored in. A global table is
|
|
// listed under every profile it is visible from, so this names the one it
|
|
// belongs to rather than the one it was reached through, and callers can
|
|
// use it as the table's identity without deciding anything themselves.
|
|
string profile_name = 7;
|
|
}
|
|
|
|
// Profile (schema) entry.
|
|
message Profile {
|
|
// Name of the schema/profile (as stored in `schemas.name`).
|
|
string name = 1;
|
|
|
|
// All tables in that schema and their dependencies.
|
|
repeated Table tables = 2;
|
|
}
|
|
|
|
// All profiles in the system.
|
|
repeated Profile profiles = 1;
|
|
|
|
// The profile holding the tables every profile shares. Callers browse this
|
|
// one when the user has not chosen a profile, so the name is reported here
|
|
// rather than being known in advance.
|
|
string shared_profile_name = 2;
|
|
}
|
|
|
|
message GetTableCatalogRequest {
|
|
// Selected profile. Omit this field to request the global-only scope.
|
|
optional string profile_name = 1;
|
|
}
|
|
|
|
message GetTableCatalogResponse {
|
|
repeated ProfileTreeResponse.Table tables = 1;
|
|
}
|
|
|
|
// Request to fetch all tables, columns and scripts for a profile.
|
|
message GetProfileDetailsRequest {
|
|
// Profile (schema) name to fetch details for.
|
|
string profile_name = 1;
|
|
}
|
|
|
|
// Response with all tables, columns and scripts for a profile.
|
|
message GetProfileDetailsResponse {
|
|
string profile_name = 1;
|
|
repeated TableDetail tables = 2;
|
|
}
|
|
|
|
// Request to copy one full profile into a new profile.
|
|
message CopyProfileRequest {
|
|
string source_profile_name = 1;
|
|
string target_profile_name = 2;
|
|
repeated string table_names = 3;
|
|
}
|
|
|
|
// Response after copying a profile.
|
|
message CopyProfileResponse {
|
|
bool success = 1;
|
|
string message = 2;
|
|
int32 tables_copied = 3;
|
|
int32 scripts_copied = 4;
|
|
}
|
|
|
|
message ExportProfileBlueprintRequest {
|
|
string profile_name = 1;
|
|
// Empty exports every dynamic table in the profile. Otherwise only these tables
|
|
// are created by import; their unselected local dependencies become requirements.
|
|
repeated string table_names = 2;
|
|
}
|
|
|
|
message ExportProfileBlueprintResponse {
|
|
string blueprint_json = 1;
|
|
string blueprint_sha256 = 2;
|
|
int32 tables = 3;
|
|
int32 required_local_tables = 4;
|
|
int32 required_global_tables = 5;
|
|
int32 templates = 6;
|
|
}
|
|
|
|
message PlanProfileBlueprintImportRequest {
|
|
string target_profile_name = 1;
|
|
string blueprint_json = 2;
|
|
}
|
|
|
|
message ProfileBlueprintImportAction {
|
|
// One of create, reuse, add, or conflict.
|
|
string action = 1;
|
|
string resource = 2;
|
|
string detail = 3;
|
|
}
|
|
|
|
message PlanProfileBlueprintImportResponse {
|
|
bool can_import = 1;
|
|
string plan_sha256 = 2;
|
|
repeated ProfileBlueprintImportAction actions = 3;
|
|
}
|
|
|
|
message ImportProfileBlueprintRequest {
|
|
string target_profile_name = 1;
|
|
string blueprint_json = 2;
|
|
string expected_plan_sha256 = 3;
|
|
}
|
|
|
|
message ImportProfileBlueprintResponse {
|
|
bool success = 1;
|
|
string message = 2;
|
|
int32 tables_created = 3;
|
|
int32 globals_created = 4;
|
|
int32 globals_reused = 5;
|
|
int32 templates_created = 6;
|
|
int32 templates_reused = 7;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
enum ManagedTableKind {
|
|
MANAGED_TABLE_KIND_UNSPECIFIED = 0;
|
|
MANAGED_TABLE_KIND_DYNAMIC = 1;
|
|
MANAGED_TABLE_KIND_SYSTEM = 2;
|
|
}
|
|
|
|
// Describes a table with its columns and associated scripts.
|
|
message TableDetail {
|
|
string name = 1;
|
|
int64 id = 2;
|
|
repeated ColumnDefinition columns = 3;
|
|
repeated ScriptInfo scripts = 4;
|
|
repeated string row_display_columns = 6;
|
|
map<string, ColumnBehavior> column_behaviors = 7;
|
|
ManagedTableKind table_kind = 8;
|
|
bool global = 9;
|
|
// Revision of this table definition for optimistic concurrency control.
|
|
int64 row_version = 10;
|
|
|
|
// Profile (schema) the table is actually stored in, which is not the
|
|
// requested profile when a global table is being listed. See
|
|
// ProfileTreeResponse.Table.profile_name.
|
|
string profile_name = 11;
|
|
|
|
// True when the physical table contains at least one row, including a
|
|
// soft-deleted row. Populated tables are append-only: PutTableDefinition is
|
|
// no longer available, while AddTableColumns remains available.
|
|
bool has_data = 12;
|
|
|
|
// User-managed single-column indexes. Backend-managed indexes are omitted.
|
|
repeated string indexes = 13;
|
|
|
|
// True when module-owned storage supports catalog-managed rows and settings.
|
|
bool catalog_managed = 14;
|
|
|
|
// Supported catalog operations, not user permissions or a guarantee that a
|
|
// particular request is valid. Column restrictions, locks, existing data and
|
|
// optimistic concurrency checks still apply. Unknown values must be ignored.
|
|
repeated CatalogFeature catalog_features = 15;
|
|
}
|
|
|
|
enum CatalogFeature {
|
|
CATALOG_FEATURE_UNSPECIFIED = 0;
|
|
CATALOG_FEATURE_WRITE_ROWS = 1;
|
|
CATALOG_FEATURE_DELETE_ROWS = 2;
|
|
CATALOG_FEATURE_ARCHIVE_ROWS = 3;
|
|
CATALOG_FEATURE_COLUMN_PRESENTATION = 4;
|
|
CATALOG_FEATURE_COLUMN_REQUIRED = 5;
|
|
CATALOG_FEATURE_COLUMN_FORM_VISIBILITY = 6;
|
|
CATALOG_FEATURE_COLUMN_OPTION_ALIASES = 7;
|
|
CATALOG_FEATURE_ROW_DISPLAY_COLUMNS = 8;
|
|
CATALOG_FEATURE_VALIDATION = 9;
|
|
CATALOG_FEATURE_SCRIPTS = 10;
|
|
CATALOG_FEATURE_ADD_COLUMNS = 11;
|
|
CATALOG_FEATURE_REPLACE_DEFINITION = 12;
|
|
CATALOG_FEATURE_INDEXES = 13;
|
|
CATALOG_FEATURE_DELETE_TABLE = 14;
|
|
CATALOG_FEATURE_RESET_MODULE_DEFAULTS = 15;
|
|
}
|
|
|
|
message ResetModuleDefaultsRequest {
|
|
string profile_name = 1;
|
|
string table_name = 2;
|
|
// Stable column IDs, not aliases. Only these label overrides are cleared.
|
|
repeated int64 column_alias_ids = 3;
|
|
// Only these required-setting overrides are cleared.
|
|
repeated int64 column_required_ids = 4;
|
|
bool reset_row_display_columns = 5;
|
|
int64 expected_row_version = 6;
|
|
}
|
|
|
|
message ResetModuleDefaultsResponse {
|
|
bool success = 1;
|
|
// Reload table details to obtain the effective settings after the reset.
|
|
int64 row_version = 2;
|
|
}
|
|
|
|
// Server-owned behavior for one logical column returned in table details.
|
|
message ColumnBehavior {
|
|
// True when the server created the column as a companion of another column.
|
|
bool generated = 1;
|
|
|
|
// True when clients must display but never submit edits for the column.
|
|
bool read_only = 2;
|
|
|
|
// Logical source column name, empty for ordinary user-defined columns.
|
|
string generated_from = 3;
|
|
|
|
// True when clients may offer this column in an alias rename picker.
|
|
bool renameable = 4;
|
|
|
|
// Stable public identity used when updating this column's presentation.
|
|
int64 column_id = 5;
|
|
|
|
// True when bundled data-entry clients should not render this column.
|
|
// This is not an authorization boundary; data APIs still expose the column.
|
|
bool hidden_from_forms = 6;
|
|
|
|
// Current public option names. For a renamed option, both fields contain its
|
|
// alias; the stored value is never disclosed. Public writes use the alias.
|
|
repeated OptionValueAlias option_value_aliases = 7;
|
|
}
|
|
|
|
// A script that targets a specific column in a table.
|
|
message ScriptInfo {
|
|
int64 script_id = 1;
|
|
string target_column = 2;
|
|
string target_column_type = 3;
|
|
string script = 4;
|
|
string description = 5;
|
|
}
|
|
|
|
// One column's desired public presentation. Its position in the containing
|
|
// repeated field is its presentation order.
|
|
message ColumnPresentation {
|
|
// Stable public identity of the table_definition_columns row.
|
|
int64 column_id = 1;
|
|
string alias = 2;
|
|
}
|
|
|
|
// Atomically replaces every user-visible column alias and their order.
|
|
message SetColumnPresentationRequest {
|
|
string profile_name = 1;
|
|
string table_name = 2;
|
|
repeated ColumnPresentation columns = 3;
|
|
// Row version returned by GetProfileDetails when this presentation was read.
|
|
int64 expected_row_version = 4;
|
|
}
|
|
|
|
message SetColumnPresentationResponse {
|
|
bool success = 1;
|
|
string message = 2;
|
|
repeated ColumnPresentation columns = 3;
|
|
// New row version after the update.
|
|
int64 row_version = 4;
|
|
}
|
|
|
|
// Atomically replaces the columns whose values identify rows in pickers and
|
|
// link labels. Their order is the order in which their values are displayed.
|
|
message SetRowDisplayColumnsRequest {
|
|
string profile_name = 1;
|
|
string table_name = 2;
|
|
repeated string row_display_columns = 3;
|
|
// Row version returned by GetProfileDetails when this metadata was read.
|
|
int64 expected_row_version = 4;
|
|
}
|
|
|
|
message SetRowDisplayColumnsResponse {
|
|
bool success = 1;
|
|
repeated string row_display_columns = 2;
|
|
// New row version after the update, or the current version for a no-op.
|
|
int64 row_version = 3;
|
|
}
|
|
|
|
// Atomically replaces the table's user-managed single-column indexes. Indexes
|
|
// owned by the backend, including link and navigation indexes, are unchanged.
|
|
message SetTableIndexesRequest {
|
|
string profile_name = 1;
|
|
string table_name = 2;
|
|
repeated string indexes = 3;
|
|
// Row version returned by GetProfileDetails when the indexes were read.
|
|
int64 expected_row_version = 4;
|
|
}
|
|
|
|
message SetTableIndexesResponse {
|
|
bool success = 1;
|
|
repeated string indexes = 2;
|
|
// New row version after the update, or the current version for a no-op.
|
|
int64 row_version = 3;
|
|
}
|
|
|
|
message SetColumnRequiredRequest {
|
|
string profile_name = 1;
|
|
string table_name = 2;
|
|
// Stable column identity returned in GetProfileDetails.column_behaviors.
|
|
int64 column_id = 3;
|
|
bool required = 4;
|
|
// Row version returned by GetProfileDetails when the column was read.
|
|
int64 expected_row_version = 5;
|
|
}
|
|
|
|
message SetColumnRequiredResponse {
|
|
bool success = 1;
|
|
int64 column_id = 2;
|
|
bool required = 3;
|
|
// New row version after the update, or the current version for a no-op.
|
|
int64 row_version = 4;
|
|
}
|
|
|
|
// One public option name. `value` identifies the option by its current public
|
|
// alias and `alias` is its desired public alias; stored values remain internal.
|
|
message OptionValueAlias {
|
|
string value = 1;
|
|
string alias = 2;
|
|
}
|
|
|
|
message SetColumnOptionAliasesRequest {
|
|
string profile_name = 1;
|
|
string table_name = 2;
|
|
int64 column_id = 3;
|
|
// Partial sets are supported; omitted values use their canonical spelling.
|
|
// An empty list removes every alias from the column.
|
|
repeated OptionValueAlias aliases = 4;
|
|
int64 expected_row_version = 5;
|
|
}
|
|
|
|
message SetColumnOptionAliasesResponse {
|
|
bool success = 1;
|
|
string message = 2;
|
|
int64 column_id = 3;
|
|
repeated OptionValueAlias aliases = 4;
|
|
int64 row_version = 5;
|
|
}
|
|
|
|
message SetColumnFormVisibilityRequest {
|
|
string profile_name = 1;
|
|
string table_name = 2;
|
|
int64 column_id = 3;
|
|
bool hidden_from_forms = 4;
|
|
// Row version returned by GetProfileDetails when the column was read.
|
|
int64 expected_row_version = 5;
|
|
}
|
|
|
|
message SetColumnFormVisibilityResponse {
|
|
bool success = 1;
|
|
string message = 2;
|
|
int64 column_id = 3;
|
|
bool hidden_from_forms = 4;
|
|
// New row version after the update.
|
|
int64 row_version = 5;
|
|
}
|
|
|
|
// Request to delete one table definition entirely.
|
|
message DeleteTableRequest {
|
|
// Profile (schema) name owning the table (must exist).
|
|
string profile_name = 1;
|
|
|
|
// Table to drop (must exist in the profile).
|
|
// Executes DROP TABLE "profile"."table" CASCADE and then removes metadata.
|
|
string table_name = 2;
|
|
}
|
|
|
|
// Response after table deletion.
|
|
message DeleteTableResponse {
|
|
// True if table and metadata were successfully deleted in one transaction.
|
|
bool success = 1;
|
|
|
|
// Human-readable summary of what was removed.
|
|
string message = 2;
|
|
}
|
|
|
|
message DeleteProfileRequest {
|
|
string profile_name = 1;
|
|
}
|
|
|
|
message DeleteProfileResponse {
|
|
bool success = 1;
|
|
string message = 2;
|
|
int32 tables_deleted = 3;
|
|
}
|
|
|
|
// How a column type is spelled in ColumnDefinition.field_type.
|
|
enum ColumnTypeSpelling {
|
|
// The name is the whole spelling: "text", "money", "gtin_13".
|
|
COLUMN_TYPE_SPELLING_BARE = 0;
|
|
|
|
reserved 1;
|
|
|
|
// The name takes the name of another table in the same profile:
|
|
// "link(adresar)". The column holds that table's id, and the server creates
|
|
// the foreign key and its index. A picker offers the profile's other tables
|
|
// as the argument.
|
|
COLUMN_TYPE_SPELLING_LINK = 2;
|
|
}
|
|
|
|
// Response describing the whole column-type vocabulary.
|
|
//
|
|
// This is the authority a client builds its column-type picker from: every rule
|
|
// a client would otherwise hardcode about what a type means is a field here. The
|
|
// list covers types clients may NOT declare as well (see `declarable`), so that
|
|
// the same call also explains the types GetProfileDetails reports back for
|
|
// server-generated companion columns.
|
|
message ListColumnTypesResponse {
|
|
// One column type and everything a client needs to know to offer it.
|
|
message ColumnType {
|
|
// Logical column type (e.g. "money", "instant"). Passed to the server as
|
|
// ColumnDefinition.field_type — see `spelling`, which is what says whether
|
|
// this name is the whole spelling.
|
|
string name = 1;
|
|
|
|
// Underlying PostgreSQL type the logical type maps to (e.g. "NUMERIC").
|
|
// Empty when `compound` is true.
|
|
string sql_type = 2;
|
|
|
|
// False for types the server generates on its own and rejects when a client
|
|
// declares them: the phone and IBAN companions, and the accounting-transfer
|
|
// connectors. A column-type picker must offer only declarable types.
|
|
bool declarable = 3;
|
|
|
|
// True when the type is a definition row rather than a column: it expands
|
|
// into several schema-managed companion columns and no column of this name
|
|
// survives. A compound type can therefore never be indexed, never be a row
|
|
// display column, and has no single sql_type of its own.
|
|
bool compound = 4;
|
|
|
|
// Whether `name` is the whole spelling or takes arguments.
|
|
ColumnTypeSpelling spelling = 5;
|
|
|
|
// Whether ColumnDefinition.currency is required. Currency is rejected on
|
|
// every type where this is false.
|
|
bool requires_currency = 6;
|
|
|
|
// True when the type may only be chosen while the table is being created.
|
|
// AddTableColumns rejects these, because they bring schema-managed columns
|
|
// that cannot be bolted onto a table that already exists.
|
|
bool creation_only = 7;
|
|
|
|
// Whether ColumnDefinition.quantity_ledger may be set on this type.
|
|
bool allows_quantity_ledger = 8;
|
|
// Whether ColumnDefinition.boolean_ledger may be set on this type.
|
|
bool allows_boolean_ledger = 11;
|
|
|
|
// Optional name grouping several types a client offers behind one choice —
|
|
// "temporal" for the date and time types, "gtin" for the GTIN lengths.
|
|
// Empty when the type stands on its own.
|
|
string group = 9;
|
|
|
|
// One column a compound type expands into.
|
|
message GeneratedColumn {
|
|
// Name the server gives the column. Fixed, and reserved: a table
|
|
// declaring a compound type may not also declare a column of this name.
|
|
string name = 1;
|
|
|
|
// The generated column's own logical type, as this same catalog
|
|
// describes it.
|
|
string field_type = 2;
|
|
|
|
// Whether the generated column carries the currency and rounding
|
|
// declared on the definition row.
|
|
bool inherits_currency = 3;
|
|
}
|
|
|
|
// What this type expands into, in the order the server creates the
|
|
// columns. Populated for compound types only, where the generated names
|
|
// are fixed; empty for every other type, including the ones whose
|
|
// companions are named after the declared column (phone, iban).
|
|
//
|
|
// A picker offering a compound type shows these, so choosing it is not a
|
|
// blind choice. The columns stay the server's to create — none of them may
|
|
// be declared.
|
|
repeated GeneratedColumn generated_columns = 10;
|
|
}
|
|
|
|
// Every column type, declarable or not, ordered by name.
|
|
repeated ColumnType column_types = 1;
|
|
|
|
// Every canonical ISO-4217 code accepted by currency-bearing columns and
|
|
// profile accounting settings, ordered alphabetically.
|
|
repeated string currency_codes = 2;
|
|
}
|