255 lines
14 KiB
Markdown
255 lines
14 KiB
Markdown
# Changelog
|
|
|
|
All notable changes to the **komp_ac web** crate — the Axum SSR/HTMX web frontend
|
|
for the komp_ac gRPC backend — are documented in this file.
|
|
|
|
This changelog tracks only the **gRPC endpoints** the web crate consumes (the
|
|
browser never calls gRPC directly; Axum proxies to the backend through these
|
|
clients) and the extent to which each is used by the pages that mount them.
|
|
Other, non-API changes are intentionally out of scope.
|
|
|
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
|
---
|
|
|
|
## [Unreleased]
|
|
|
|
### Changed
|
|
|
|
- **Editable empty-table definitions** — the table-definition column page now
|
|
calls `PutTableDefinition` to atomically remove selected columns and append
|
|
replacements, with stable column identities and optimistic revision checks.
|
|
Add-only changes continue to work for populated tables.
|
|
- **The shared profile is named by the backend** — `ProfileTreeResponse`
|
|
gained `shared_profile_name`, and every page that browses the shared tables
|
|
now reads the name from there instead of spelling `__global` itself. Catalog
|
|
discovery retains its global-only request, which does not require the shared
|
|
profile to have been created yet.
|
|
|
|
---
|
|
|
|
## [v0.8.46] — 2026-08-16
|
|
|
|
### Added
|
|
|
|
- **Role, user and permission administration** — `/permissions` consumes
|
|
`ListRoles`, `AddRole`, `RemoveRole`, `ListUsers`, `AssignUserRole`,
|
|
`ListRolePermissions`, `ListGrantableObjects`, `GrantPermission` and
|
|
`RevokePermission`. Direct and inherited grants are distinguished, and the
|
|
action controls come from each grantable object returned by the backend.
|
|
- **Table-family permissions in table definition** — selecting a table shows
|
|
its grant matrix for every editable data role. Creating a table redirects to
|
|
that table in the definition workspace so its initial grants can be assigned
|
|
immediately.
|
|
- **Password management** — `/password` consumes `ChangePassword` for the
|
|
signed-in user, while the user table consumes `ResetUserPassword` for
|
|
administrator resets allowed by the backend role hierarchy.
|
|
- **`TableDefinition.ListColumnTypes`** — called by the add-table and
|
|
table-definition loaders. The whole response is consumed: `name`, `group`,
|
|
`declarable`, `compound`, `spelling`, `requires_currency`, `creation_only`,
|
|
`allows_quantity_ledger` and `sql_type` are each read by a rule that used to
|
|
be hardcoded in `crate::schema`. The column vocabulary is now the backend's,
|
|
so a type it adds is offered by both screens without a change here.
|
|
|
|
### Changed
|
|
|
|
- **Permissions moved out of the admin panel into their own nav section, split
|
|
in three** — `/admin/permissions` is gone; the pages are `/permissions/roles`
|
|
(which roles exist), `/permissions/users` (who holds them) and
|
|
`/permissions/grants` (what a role may do). No new gRPC endpoint is consumed:
|
|
the same `GrantPermission` and `RevokePermission` calls now come from one
|
|
`POST /permissions/grants/apply`, which issues one call per `object|action`
|
|
pair so a shortcut — a whole row, a whole profile, everything — is a longer
|
|
list rather than a different request. Shortcuts grant the wildcard objects
|
|
`ListGrantableObjects` already returns (`data:*`, `data:<profile>/*`,
|
|
`journal:*`, `ecb:*`), so they keep covering profiles and tables created
|
|
later, and `AddRole` may be followed by a starter set of those grants in the
|
|
same submission. Revoking tolerates the `NOT_FOUND` a pair the role does not
|
|
hold directly answers with, which is what makes "remove all of this"
|
|
idempotent.
|
|
- **Web authorization follows permission objects, not role names** — structural
|
|
pages check their `struct:<area>/manage` permission from `GetAuthorization`,
|
|
so inherited `superadmin` authorization works and data roles are no longer
|
|
treated as administrators. Login redirects structural users to the admin
|
|
workspace and data users to analytics.
|
|
- **Import and export are their own grant actions** — the import page requires
|
|
the caller's `import` grant and the export page the caller's `export` grant,
|
|
on top of the underlying row action each transfer performs (`insert` for
|
|
import, `read` for export). A table is offered only when the caller holds
|
|
both, so the menu never leads to a transfer the backend would refuse halfway
|
|
through. Profile-tree discovery for these pages is authenticated.
|
|
- **CSV transfer system columns and header normalizing** — the import page
|
|
gained a "File includes system columns" checkbox (so `deleted` loads back as
|
|
it left) and a "Normalize headers" action that rewrites header rows into the
|
|
backend's column spellings before anything is posted; the export page gained
|
|
an "Include system columns" checkbox that adds `id`, `deleted`, and
|
|
`row_revision`. No new gRPC endpoint is consumed — these reuse
|
|
`PostTableDataBulk`, `GetTableDataByPosition`, and `GetTableDataCount`.
|
|
- **Permission mutations keep the browser session** — grants, role changes and
|
|
assignments now reload the live authorization state without replacing the
|
|
identity-only JWT. The permissions workspace reloads in place and shows the
|
|
updated effective policy.
|
|
- **The column-type picker is the server's list** — it no longer carries its
|
|
own. Types the web crate never offered are now reachable: `numeric` and the
|
|
`ACCOUNTING_TRANSFER` compound column. Server-generated companion types
|
|
(`phone_country`, `iban_bban`, the transfer connectors) are listed by the
|
|
endpoint but never offered, and are refused if one is posted anyway.
|
|
- **Creation-only types are refused on the append panel by rule, not by name** —
|
|
`POST /admin/table-definition/columns` used to exclude `accounting` alone;
|
|
it now excludes every type the response marks `creation_only`, which is what
|
|
`AddTableColumns` rejects.
|
|
- **Compound columns are staged as the backend expands them** — a compound
|
|
column takes its type's name, cannot be indexed, and is not offered as a row
|
|
display column, since no column of that name survives the expansion.
|
|
- **Currency and quantity-ledger rules come from the response** —
|
|
`requires_currency` decides which types carry a currency (previously MONEY
|
|
and ACCOUNTING by name), and `allows_quantity_ledger` both validates the
|
|
choice and writes the hint under the input.
|
|
- **`GetProfileDetails` columns show the SQL type behind them** — the
|
|
workspace's column list renders `sql_type` from the catalog beside each
|
|
logical type, including for the companion columns the backend generates.
|
|
- **`TableDefinition.GetProfileTree` — `depends_on` is one entry per link** —
|
|
each dependency now carries the target `table_name` and the `column_name`
|
|
holding the reference. Both the admin panel and the table-definition
|
|
workspace render each entry as `table (column)`, so a table that points at
|
|
one target twice shows as two links.
|
|
- **`AuthService.Register` — the `role` field is gone** — the request no
|
|
longer carries a client-chosen role; every registration lands as `guest`.
|
|
The register page dropped the role input and its suggestion list.
|
|
- **`EcbService.GetEcbPipelineStatus`** — a new `/admin/ecb` page (with a
|
|
polling `/admin/ecb/status` card) renders the recent ECB import batches and
|
|
their state. The page is gated on the caller's `ecb:*` read permission, and
|
|
the backend stays the authority: a caller who slips past the page check gets
|
|
`PermissionDenied` from the RPC.
|
|
- **`TableDefinition.GetTableCatalog`** — the form catalog now feeds the
|
|
add-table, table-definition, import/export and admin loaders, replacing
|
|
locally assembled table lists. Global tables appear in the catalog and are
|
|
selectable as link targets from any profile; a global table may only link to
|
|
other global tables.
|
|
- **Link columns are declarable** — the add-table page picks a link target
|
|
table from the profile's offered targets and writes `link(table)` for the
|
|
column type. A link is never indexed by the form: the server indexes it, and
|
|
the draft refuses a tampered `indexed` flag for one.
|
|
- **Columns can be made required** — add-table gained a required toggle that
|
|
travels with the column into `PostTableDefinition`.
|
|
- **`TablesData.GetTableDataCount`** — the CSV export asks for the row count
|
|
before downloading, so the export loop knows how many
|
|
`GetTableDataByPosition` pages to read.
|
|
|
|
### Not covered
|
|
|
|
The endpoints and fields below are part of the current proto surface but the
|
|
web crate does not implement them. They are listed so it stays visible what
|
|
the backend gained that this client has not wired up yet.
|
|
|
|
- **`TableValidation.DisplayMask.storage_mode`** — the new `MaskStorageMode`
|
|
option is always left absent (raw); there is no formatted-storage choice in
|
|
the validation UI.
|
|
- **`TableScript.ScriptDependency.link_column` / `name_in_script`** — the new
|
|
dependency fields are not read; the web only surfaces the id and warnings
|
|
`PostTableScript` returns.
|
|
- **`TablesData` account as a string** — accounting-enabled tables now take a
|
|
slash-delimited `account` path instead of the `account_id` reference, and
|
|
the structure endpoint exposes the column as `account`. The bulk-import and
|
|
CSV-export paths treat columns generically and were not changed; the web has
|
|
no accounting data-entry surface of its own.
|
|
|
|
## [v0.8.38] — 2026-08-05
|
|
|
|
The web crate wires up seven gRPC services and calls the following endpoints.
|
|
Coverage notes describe which pages exercise each call and how deeply its
|
|
response is consumed.
|
|
|
|
### Auth (`AuthServiceClient`)
|
|
|
|
- **`AuthService.Login`** — called by `POST /login`. Exchanges identifier and
|
|
password for an access token; the token and `expires_in` are written into the
|
|
`analytics_token` HTTP-only cookie that every subsequent gRPC call is signed
|
|
with. Fully covered end-to-end.
|
|
- **`AuthService.Register`** — called by `POST /register`. Submits the full
|
|
`RegisterRequest` surface (username, email, password, password_confirmation,
|
|
role, timezone, phone_country). Only the success/error message is shown; it
|
|
does not create a session.
|
|
- **`AuthService.GetAuthorization`** — called by every admin page loader
|
|
(`/admin`, table-definition, add-table, add-logic, add-validation,
|
|
import/export). Returns the caller's role; the web crate uses it for two
|
|
things: gating the admin panel to `role == "admin"` and rendering the navbar
|
|
with the current role. Response fields beyond `role` are not used.
|
|
|
|
### Table definition (`TableDefinitionClient`)
|
|
|
|
- **`TableDefinition.GetProfileTree`** — called by the analytics, admin, table
|
|
definition, add-table, add-logic, and add-validation loaders. Populates the
|
|
profile selectors (profile name + table count) and, in the admin panel, the
|
|
per-profile table list including `depends_on` and `row_display_columns`.
|
|
Response is consumed fairly deeply.
|
|
- **`TableDefinition.PostTableDefinition`** — called by `POST /admin/tables`
|
|
(add-table page). Creates a table from the draft; the returned `success`,
|
|
`sql`, and `message` are surfaced. Full form → endpoint mapping.
|
|
- **`TableDefinition.GetProfileDetails`** — called by the table-definition
|
|
workspace loader. Returns per-table columns (name, type, currency,
|
|
quantity-ledger, rounding, generated/read-only behaviors and `generated_from`
|
|
for Steel scripts), scripts (target column/type/description/source), row
|
|
display columns, and table kind. The most deeply consumed definition endpoint.
|
|
- **`TableDefinition.GetColumnAliasRenameHistory`** — called by the
|
|
table-definition workspace loader. Returns rename history entries
|
|
(table, old/new column names, timestamp); only those four fields are rendered.
|
|
- **`TableDefinition.AddTableColumns`** — called by
|
|
`POST /admin/table-definition/columns`. Adds columns to an existing table.
|
|
- **`TableDefinition.SetColumnPresentation`** — called by
|
|
`POST /admin/tables/presentation`. Atomically changes column aliases and order.
|
|
- **`TableDefinition.DeleteTable`** — called by
|
|
`POST /admin/table-definition/delete`. Deletes a table definition.
|
|
- **`TableDefinition.CopyProfile`** — called by
|
|
`POST /admin/table-definition/copy`. Copies a profile.
|
|
- **`TableDefinition.CreateInvoiceTemplateTable`** — called by
|
|
`POST /admin/table-definition/invoice-template`. Creates a table from the
|
|
invoice template contract.
|
|
|
|
### Table script (`TableScriptClient`)
|
|
|
|
- **`TableScript.PostTableScript`** — called by `POST /admin/logic`
|
|
(add-logic page). Creates a Steel table script; the returned id and warnings
|
|
are surfaced to the user.
|
|
|
|
### Table validation (`TableValidationServiceClient`)
|
|
|
|
- **`TableValidationService.UpdateFieldValidation`** — called by
|
|
`POST /admin/validation`. Creates/updates a field validation.
|
|
- **`TableValidationService.UpsertValidationRule`** — called by
|
|
`POST /admin/validation/rules`. Creates/updates a reusable validation rule.
|
|
- **`TableValidationService.ApplyValidationSet`** — called by
|
|
`POST /admin/validation/sets`. Applies a validation set.
|
|
- **`TableValidationService.UpsertValidationSet`** — called by
|
|
`POST /admin/validation/sets`. Creates/updates a reusable validation set.
|
|
|
|
Each validation POST maps the submitted form into the corresponding request and
|
|
renders only the returned `success`/`message`.
|
|
|
|
### Table structure (`TableStructureServiceClient`)
|
|
|
|
- **`TableStructureService.GetTableStructure`** — called by the admin panel,
|
|
CSV import, and CSV export. Returns table structures used three ways: the
|
|
admin column browse (name, type, nullable, primary key, quantity-ledger),
|
|
import header validation, and export column ordering. Only the structure for
|
|
the selected/imported/exported tables is requested at a time.
|
|
|
|
### Tables data (`TablesDataClient`)
|
|
|
|
- **`TablesData.PostTableDataBulk`** — called by `POST /admin/import`. Chunked
|
|
bulk insert of parsed CSV rows into a table, with per-chunk requests.
|
|
- **`TablesData.GetTableDataByPosition`** — called by `POST /admin/export.csv`.
|
|
Reads table rows by position for CSV download, one request per table.
|
|
|
|
### Analytics (`AnalyticsServiceClient`)
|
|
|
|
- **`AnalyticsService.GetAnalyticsCatalog`** — called by `POST /api/catalog`.
|
|
Returns the live public analytics catalog for a profile (tables, columns,
|
|
types, links); rendered in the sidebar and used to generate starter queries
|
|
and LLM schema context.
|
|
- **`AnalyticsService.ExecuteAnalyticsQuery`** — called by `POST /api/query`.
|
|
Runs a read-only analytics SQL query; the result columns/rows feed the
|
|
ECharts charts and table view.
|
|
- The analytics profile selector is fed by `TableDefinition.GetProfileTree`
|
|
(see above), not by a dedicated analytics profile endpoint.
|