pgkiln 0.66.0 → 0.68.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/SECURITY.md CHANGED
@@ -117,6 +117,7 @@ first version (MVP). Every finding below has a regression test in
117
117
  | Passkey sign-in without a password, workspace rule (0.62.0) | *Sign in with a passkey* asks the browser for any passkey of this site (empty allow list) with `userVerification: required`, and the server refuses an answer whose authenticator data lacks the user-verified flag, so the passkey alone stands for possession plus a fingerprint, face or PIN. The credential id is looked up for this relying party only; a user handle, when the browser sends one, must be the developer's (a SHA-256-derived handle, not the user name). The same one-time challenge, origin, RP ID hash, signature and counter checks as at the second step apply; failures are logged as `login_failed` with the developer's name when the key is known and count for the per-user and per-IP lockout. Administrators turn it off in Instance settings. A workspace's rule (administrators and its own administrators only, CSRF-checked) can only add a requirement; `pgkiln admin set-2fa-policy off` clears every workspace's rule. While a second factor is required of a developer, a sign-in with the default password leads only to the password change. |
118
118
  | Single sign-on for developers (0.63.0) | A provider or directory signs developers in only with *builder* turned on. The flow is the applications' (state, PKCE, nonce, browser-binding cookie, ID token or SAML assertion checks) with a pending row without an application; developers are found by the provider's stable subject in `meta.developer_identity`, never by a name alone. An existing developer is linked by name only when the administrator allows it, once, never a break-glass administrator, and an e-mail user name only when verified; otherwise the developer links the identity on Security, which needs their session and CSRF token to start and the same browser to finish, and one identity can't be linked to two developers. Automatic accounts need the developers group when one is set and start as developers; the administrators group decides the role at every sign-in but never demotes a break-glass administrator. A workspace's single sign-on rule (administrators and its own administrators, CSRF-checked) refuses the pgkiln password and a passkey alone, after the password check so it reveals nothing; it can only be turned on while a break-glass administrator exists and by someone who could still sign in; the last break-glass administrator and a developer's last identity can't be removed while it applies. Failures are logged as `login_failed` with the reason. |
119
119
  | Two-factor sign-in for application users (0.64.0) | Per application (`meta.app.mfa`: off, optional, required, required for roles). The account's TOTP secrets are encrypted with `PGKILN_SECRET_KEY` and stored only after a code confirms them; recovery codes are SHA-256 and used up atomically; each 30-second step once, one step either side. A password or LDAP sign-in that needs the step creates no session: the pending sign-in (5 minutes, 10 while adding an app) lives in the signed-out session, bound to it and to the page's CSRF token, and a forged token ends it. Wrong codes count as failed sign-ins (the per-user and per-IP lockout). A *Keep me signed in* or session-sharing token stands in for the step only when its method ends in `+2fa`; an identity provider's sign-in is left to the provider. Without the instance key the step can't be required and enrolment refuses rather than skips. Removing an app needs a current or recovery code and is refused for the last app while the application requires it; a developer's reset (Users, with a reason) removes the apps and codes and ends the account's sessions, remembered and shared sign-ins. Every enrolment, removal, reset and used recovery code is in the activity log. The factor tables are closed to the runtime roles. |
120
+ | Lockout checks and key rotation (0.67.0) | Only administrators see the checks and confirm a key backup (CSRF); the page shows a 16-character fingerprint of `PGKILN_SECRET_KEY` from a separate derivation, never the key; values from the database (RP IDs, names) are escaped. `pgkiln admin rotate-key` reads both keys from the environment (never arguments, so not in the shell history or the process list), decrypts every secret before it writes, and changes everything or nothing in one transaction; it is logged and mailed to the administrators. The runtime role reads none of the encrypted columns (tested for every `*_enc` column) |
120
121
 
121
122
  ## Findings of the MVP review and their fixes
122
123
 
@@ -7,7 +7,7 @@ open item and open an issue or pull request; see [CONTRIBUTING.md](../CONTRIBUTI
7
7
  Legend: ✅ available · 🟡 partial (see notes) · ❌ not yet · ➖ not planned (a deliberate choice,
8
8
  or better served by the PostgreSQL ecosystem; see the notes and [extensions](guide/15-extensions.md))
9
9
 
10
- Last reviewed: 2026-10-21 against **APEX 26.2** (sprints 121, 123–125: the builder in Deutsch, English, Español, Français, Nederlands and Português, step by step: the frame, sign-in, Workspace home, App Builder, Page Designer menus, the SQL Workshop's home, SQL Worksheet, Object Browser and Table Properties, Shared Components, application settings, users, identity providers, developers and workspaces (WS-7); sprint 122: *Ask in your own words* sets faceted search and smart filter facets, smart filters read a typed phrase (WS-5), and Sample Maps, Sample Approvals, Sample Data Loading and Sample Files in the App Gallery (WS-8); sprint 120: the App Gallery's single-topic sample apps (charts, cards, calendar, interactive grids, dynamic actions, reporting), the UX Pattern Catalog and a Utility Apps tab with Lookup Lists, Release Notes and Announcements (WS-8); sprint 119: data security per table, a roles × columns matrix and masked values per application role in a masking view, the same identity for pages, AI tools, REST, AutoREST and MCP (WS-13); sprint 118: Administration → Mail queue with delivery per hour and per workspace, the slowest provider calls and failures with Retry and Purge, a workspace's own mail service, and workspace network access lists that narrow the installation's allow-list (WS-9); sprint 117: Pillar Light and Pillar Dark navigation appearances with a header strip, clearer navigation tree states, subtle colour utilities, RTL; sprint 116: the comparison moved from 26.1 to 26.2, with a section for the 26.2 workspace items WS-1 … WS-13 and OCI managed identities; the App Builder list with Updated by, working copies and the lock; `pgkiln import --only`, a file-level import; stale rows on facet menus and blueprints fixed; sprint 115: popup LOVs that load on scroll, Wait Popup dynamic actions and dynamic actions on menu entries; sprint 114: Workflow 26.2 with custom task outcomes, task events and notifications, Send E-Mail and draft steps, migrating running instances and the diagram as SVG / PNG; sprint 113: Team Development with issues, labels, milestones, templates, a board and a set-up wizard; sprint 112: AI interactive reports with chips, Undo, computed columns and a phrase parser that needs no AI service; sprint 111: AI Agents with tools as a shared component, a Navigate tool with checksummed URLs, Gemini and OpenAI-compatible services; sprint 110: Data Reporter as a workspace tool with datasets, reporting applications, editors and viewers, published reports with stable URLs and pins; sprint 109: the Workspace home above the App Builder and SQL Workshop, with a summary, top applications, users and developers, and an optional release check; sprint 108: the code editor's syntax colours in the builder's light and dark themes, read-only SQL highlighted, the Data Modeler in dark mode; sprint 107: a transaction mode in the SQL Worksheet with Commit and Rollback; DA-18: JavaScript (MLE) not planned, plv8 where installed; sprint 106: the change log of DDL change sets with Flyway, Liquibase and SQL downloads; sprint 104: RESTful Services modules, templates and handlers with PL/pgSQL and media handlers, privileges, OpenAPI and Try it; sprint 103: Schema Export / Import with pg_dump and pg_restore; sprint 102: the SQL Monitor with live sessions, Top SQL and a statement's plan; sprint 101: Scheduling of pg_cron jobs with a schedule builder, run now and run history; sprint 100: RESTful Services, tables and views published as REST endpoints with paging, filters, keys and OpenAPI; sprint 99: Administration → Database Users for PostgreSQL roles; sprint 98: the Data Modeler with relational diagrams, DDL and a data dictionary; sprint 97: charts of a query in the worksheet, saved charts and their dashboard; sprint 96: the SQL Workshop's Launchpad with pins and tool groups, the builder's search with Ctrl+K; sprint 95: Table Properties: create, edit or copy a table in a form with a DDL preview and Apply in one transaction; sprint 94: an object's menu with Open in a panel, Quick DDL, Add index / trigger / policy and Drop with dependents; sprint 93: worksheets saved as SQL Scripts with tabs and a Files list, Format, Convert case, find and replace, bind and substitution variables; sprint 92: the worksheet's Query Result with sort, value dialog, copy and downloads, plans as a tree with the slowest step and misestimates, SQL History with status, search and run again; sprint 91: the SQL Worksheet like Database Actions' SQL: navigator, Run Statement at the cursor and Run Script with a log per statement, Explain Plan, Autotrace, notices, history, Run as an application role; sprint 90: Comment Out in the page designer, gallery labels in title case; sprint 89: the Object Browser's schema, one row of tabs, blank NULLs, Modify column; sprint 88: home cards with colour bands and round icons, the hero on the page background, a page footer with the version and Back to top; sprint 87: the Create Application wizard reloads the page list for a schema, RLS badges, the alias from the name; sprint 86: the page designer by page number, HTML error pages in the builder; sprint 85: the Form Designer, beyond APEX; sprint 84: the date picker, facet menus; sprint 83: Component Settings and Component Groups; sprint 82: Report Queries; sprint 81: Application Computations and Shortcuts in Shared Components; sprint 80: the master grid's first row selected when the page opens and after a search; grid cells as text with their format mask until edited, with cell navigation by arrow keys, Enter, F2 and Escape; sprint 79: generated dashboards with sums, donuts and lines, leaving out charts that say nothing; applications open in their own light or dark mode until the user chooses, per application; a user menu with Appearance and Sign in when signed out; the developer toolbar's App and Page texts and debug state; the report search's column scope in the magnifier; sprint 78: generated faceted search reports with one column per foreign key, the faceted search's total row count, Show all and Yes/No values, one search field, friendly headings and number formats in generated grids and master-detail pages, friendly names in the Create Application wizard's page list; sprint 77: the Page Designer's layout and tree by display position, button positions, the tree's context menu with Duplicate and Copy to other page, Show Common / Show All, Go to group and the Template Options dialog; display positions, button positions and side-column page templates at runtime; sprint 76: the interactive report's menus and pagination, date items in the date format; sprint 75: the SQL Workshop's Object Browser and tabs; sprint 74: the builder's information architecture: Shared Components grid, Settings tabs, application home search and tasks; sprint 73: the Create Application wizard on one page with page types and features; sprint 72: the runtime chrome compared with APEX 26.2's: the developer toolbar, the Iris look, the navigation bar's Help menu and Install button; sprint 71: generated applications compared with APEX 26.2's: labels, foreign key names in reports, file columns, format masks, the Home page and the dashboard; sprint 70: treemap, sunburst and timeline charts; sprint 69: dragging tasks on a Gantt chart; sprint 68: the Data Reporter's welcome page, Find my workspace; sprint 67: REST source catalogs from OpenAPI documents, a workspace's export and import (two rows added); sprint 66: a blueprint from an existing application; sprint 65: facet charts; sprint 64: approval vacation rules and expiration policies; sprint 63: range, box plot and stock charts; sprint 62: workspace preferences (SQL Workshop and RESTful services per workspace), extension links, Manage backups across applications, SQL Workshop utilities with object reports, About Database and a database monitor; sprint 61: the builder's screens compared with APEX 26.1: the workspace sign-in page, the Administration menu with workspace message, environment banner and utilization, the SQL Workshop home, the App Gallery, application groups and cross application reports (four rows added); sprint 60: isolated workspaces with their own database logins, row-level security on pgkiln's tables and workspace database roles, workspace administrators; sprint 59: the Page Designer's help pane, Quick edit from the developer toolbar; sprint 58: page groups; sprint 57: region templates hero, title bar, buttons container, inline dialog and drawer, wizard with wizard progress, the carousel; sprint 56: Generate DDL and Schema Comparison in the SQL Workshop, `pgkiln ddl` and `pgkiln compare`; sprint 55: an editable login page with a Login region and the Minimal page template, Forgot password through the application's mail service; sprint 54: interactive grid views, the single row view, group by and chart; sprint 53: application settings, user preferences and items kept per user, dynamic translations, `meta.data_export` and data export downloads, display image and geocoded address items; sprint 52: every dynamic action event and action, Ajax callbacks, an error handling function, the session timeout warning; sprint 51: checked imports, application backups, availability and Run only, feedback, type-specific attribute help; sprint 50: lost update detection, warn on unsaved changes, the URL and search regions with search configurations, the developer toolbar with a session state viewer, and e-mail through SMTP with OAuth2, Microsoft Graph, Amazon SES and HTTP APIs; import checks, application availability, property help and e-mail compared again; 2026-10-06: pgkiln 0.31.0, in progress: static application files and the Execute JavaScript dynamic action; region, item, dynamic action and process plug-ins; conditional and dynamic theme styles; XML and Excel in `meta.parse_data`, zips in SQL, `meta.v_boolean`; file items in S3-compatible object storage; map layers by the visible area and as vector tiles; a graphical query builder; tenants for workflows and tasks; application files as YAML and region static IDs; Lucide icons and icon modifiers; PWA push notifications; 0.30.0: 136 icons and an icon picker; an axe-core accessibility audit; cropping pictures; session sharing between applications; twenty-two built-in languages; 0.29.0: workspaces; the Iris base style; drawers; built-in template components including the metric card; Theme Roller dark-mode colours, live preview and template options on items and report columns; report selection across pages; instance settings; fourteen built-in languages; 0.28.0: AI with Claude and OpenAI; 0.27.0: Data Reporter; sample data generator; create application from several sheets, pasted data or existing tables; 0.26.0: working copies with a three-way merge; theme, library and boilerplate applications with subscriptions; 0.25.0: Gantt, pyramid and polar charts; map layers, clustering and server-side spatial filters; REST data sources that write back from forms and grids and synchronise into tables, OAuth2 password and refresh-token grants; debug messages per request and an install/upgrade log; `meta.web_request()` and `meta.parse_data()`; Theme Roller style variants and template options; 0.24.0: automations with several actions, error handling per row and runs from SQL; invoke-API workflow steps; Unload Data in the Data Workshop; create page wizards for cards, calendar, chart, map, faceted search, form and master-detail; create an application from a file; 0.23.0: interactive grid aggregates, frozen/moved/resized columns, layouts and saved grid reports, master-detail, row actions and copy/paste; download processes, execution chains in the background, workflow processes, branches to a function's URL or another app, the Dialog Closed event; number format masks, automatic time zone, runtime messages in German, French and Spanish; SQL scripts, Quick SQL, a query builder, XML loading and data load definitions; custom authentication, lists, page and application locks with developer comments, supporting objects; 0.22.0: keyset paging, report PDFs and REST collections streamed from a cursor, database-account authentication; 0.21.0: HTTP-header authentication behind a reverse proxy; 0.20.0: a popup list of values with server-side search; 0.19.0: row-range pagination, maximum row counts and row limits, lazy loading and caching of regions, streamed CSV/Excel downloads; 0.18.0: calendar week/day/list views with drag and drop, bubble/gauge/funnel/radar charts and drill-down, smart filters, a region display selector and more facet types, computations, conditional branches, build options, menu buttons, REST data sources and web credentials, rich text/Markdown, rating, combobox, date range and QR code items; 0.17.0: an App Builder home, workspace dashboard and utilities like APEX's; 0.16.0: a Page Designer with drag-and-drop layout, a code editor with autocomplete, template components and plug-ins, parallel branches and versions of workflows, the `pgkiln` command line with one file per component; 0.15.0: drop and paste files, heat maps, filtering a report by the map area; 0.14.0: stacked, combo, scatter and pie charts, several files per upload item; 0.13.0: map and tree regions; 0.12.0: REST modules in the builder; 0.11.0: workflows and Progressive Web Apps; 0.10.0: LDAP, SAML, "Keep me signed in", document templates, JSON loading, approvals and the task list; pgkiln installs no application, HR is an example).
10
+ Last reviewed: 2026-10-27 against **APEX 26.2** (sprint 134: the builder also in Italiano, 中文 (简体), 中文 (繁體), 日本語 and 한국어, APEX's ten builder languages plus Nederlands (SEC-5); sprints 121, 123–125: the builder in Deutsch, English, Español, Français, Nederlands and Português, step by step: the frame, sign-in, Workspace home, App Builder, Page Designer menus, the SQL Workshop's home, SQL Worksheet, Object Browser and Table Properties, Shared Components, application settings, users, identity providers, developers and workspaces (WS-7); sprint 122: *Ask in your own words* sets faceted search and smart filter facets, smart filters read a typed phrase (WS-5), and Sample Maps, Sample Approvals, Sample Data Loading and Sample Files in the App Gallery (WS-8); sprint 120: the App Gallery's single-topic sample apps (charts, cards, calendar, interactive grids, dynamic actions, reporting), the UX Pattern Catalog and a Utility Apps tab with Lookup Lists, Release Notes and Announcements (WS-8); sprint 119: data security per table, a roles × columns matrix and masked values per application role in a masking view, the same identity for pages, AI tools, REST, AutoREST and MCP (WS-13); sprint 118: Administration → Mail queue with delivery per hour and per workspace, the slowest provider calls and failures with Retry and Purge, a workspace's own mail service, and workspace network access lists that narrow the installation's allow-list (WS-9); sprint 117: Pillar Light and Pillar Dark navigation appearances with a header strip, clearer navigation tree states, subtle colour utilities, RTL; sprint 116: the comparison moved from 26.1 to 26.2, with a section for the 26.2 workspace items WS-1 … WS-13 and OCI managed identities; the App Builder list with Updated by, working copies and the lock; `pgkiln import --only`, a file-level import; stale rows on facet menus and blueprints fixed; sprint 115: popup LOVs that load on scroll, Wait Popup dynamic actions and dynamic actions on menu entries; sprint 114: Workflow 26.2 with custom task outcomes, task events and notifications, Send E-Mail and draft steps, migrating running instances and the diagram as SVG / PNG; sprint 113: Team Development with issues, labels, milestones, templates, a board and a set-up wizard; sprint 112: AI interactive reports with chips, Undo, computed columns and a phrase parser that needs no AI service; sprint 111: AI Agents with tools as a shared component, a Navigate tool with checksummed URLs, Gemini and OpenAI-compatible services; sprint 110: Data Reporter as a workspace tool with datasets, reporting applications, editors and viewers, published reports with stable URLs and pins; sprint 109: the Workspace home above the App Builder and SQL Workshop, with a summary, top applications, users and developers, and an optional release check; sprint 108: the code editor's syntax colours in the builder's light and dark themes, read-only SQL highlighted, the Data Modeler in dark mode; sprint 107: a transaction mode in the SQL Worksheet with Commit and Rollback; DA-18: JavaScript (MLE) not planned, plv8 where installed; sprint 106: the change log of DDL change sets with Flyway, Liquibase and SQL downloads; sprint 104: RESTful Services modules, templates and handlers with PL/pgSQL and media handlers, privileges, OpenAPI and Try it; sprint 103: Schema Export / Import with pg_dump and pg_restore; sprint 102: the SQL Monitor with live sessions, Top SQL and a statement's plan; sprint 101: Scheduling of pg_cron jobs with a schedule builder, run now and run history; sprint 100: RESTful Services, tables and views published as REST endpoints with paging, filters, keys and OpenAPI; sprint 99: Administration → Database Users for PostgreSQL roles; sprint 98: the Data Modeler with relational diagrams, DDL and a data dictionary; sprint 97: charts of a query in the worksheet, saved charts and their dashboard; sprint 96: the SQL Workshop's Launchpad with pins and tool groups, the builder's search with Ctrl+K; sprint 95: Table Properties: create, edit or copy a table in a form with a DDL preview and Apply in one transaction; sprint 94: an object's menu with Open in a panel, Quick DDL, Add index / trigger / policy and Drop with dependents; sprint 93: worksheets saved as SQL Scripts with tabs and a Files list, Format, Convert case, find and replace, bind and substitution variables; sprint 92: the worksheet's Query Result with sort, value dialog, copy and downloads, plans as a tree with the slowest step and misestimates, SQL History with status, search and run again; sprint 91: the SQL Worksheet like Database Actions' SQL: navigator, Run Statement at the cursor and Run Script with a log per statement, Explain Plan, Autotrace, notices, history, Run as an application role; sprint 90: Comment Out in the page designer, gallery labels in title case; sprint 89: the Object Browser's schema, one row of tabs, blank NULLs, Modify column; sprint 88: home cards with colour bands and round icons, the hero on the page background, a page footer with the version and Back to top; sprint 87: the Create Application wizard reloads the page list for a schema, RLS badges, the alias from the name; sprint 86: the page designer by page number, HTML error pages in the builder; sprint 85: the Form Designer, beyond APEX; sprint 84: the date picker, facet menus; sprint 83: Component Settings and Component Groups; sprint 82: Report Queries; sprint 81: Application Computations and Shortcuts in Shared Components; sprint 80: the master grid's first row selected when the page opens and after a search; grid cells as text with their format mask until edited, with cell navigation by arrow keys, Enter, F2 and Escape; sprint 79: generated dashboards with sums, donuts and lines, leaving out charts that say nothing; applications open in their own light or dark mode until the user chooses, per application; a user menu with Appearance and Sign in when signed out; the developer toolbar's App and Page texts and debug state; the report search's column scope in the magnifier; sprint 78: generated faceted search reports with one column per foreign key, the faceted search's total row count, Show all and Yes/No values, one search field, friendly headings and number formats in generated grids and master-detail pages, friendly names in the Create Application wizard's page list; sprint 77: the Page Designer's layout and tree by display position, button positions, the tree's context menu with Duplicate and Copy to other page, Show Common / Show All, Go to group and the Template Options dialog; display positions, button positions and side-column page templates at runtime; sprint 76: the interactive report's menus and pagination, date items in the date format; sprint 75: the SQL Workshop's Object Browser and tabs; sprint 74: the builder's information architecture: Shared Components grid, Settings tabs, application home search and tasks; sprint 73: the Create Application wizard on one page with page types and features; sprint 72: the runtime chrome compared with APEX 26.2's: the developer toolbar, the Iris look, the navigation bar's Help menu and Install button; sprint 71: generated applications compared with APEX 26.2's: labels, foreign key names in reports, file columns, format masks, the Home page and the dashboard; sprint 70: treemap, sunburst and timeline charts; sprint 69: dragging tasks on a Gantt chart; sprint 68: the Data Reporter's welcome page, Find my workspace; sprint 67: REST source catalogs from OpenAPI documents, a workspace's export and import (two rows added); sprint 66: a blueprint from an existing application; sprint 65: facet charts; sprint 64: approval vacation rules and expiration policies; sprint 63: range, box plot and stock charts; sprint 62: workspace preferences (SQL Workshop and RESTful services per workspace), extension links, Manage backups across applications, SQL Workshop utilities with object reports, About Database and a database monitor; sprint 61: the builder's screens compared with APEX 26.1: the workspace sign-in page, the Administration menu with workspace message, environment banner and utilization, the SQL Workshop home, the App Gallery, application groups and cross application reports (four rows added); sprint 60: isolated workspaces with their own database logins, row-level security on pgkiln's tables and workspace database roles, workspace administrators; sprint 59: the Page Designer's help pane, Quick edit from the developer toolbar; sprint 58: page groups; sprint 57: region templates hero, title bar, buttons container, inline dialog and drawer, wizard with wizard progress, the carousel; sprint 56: Generate DDL and Schema Comparison in the SQL Workshop, `pgkiln ddl` and `pgkiln compare`; sprint 55: an editable login page with a Login region and the Minimal page template, Forgot password through the application's mail service; sprint 54: interactive grid views, the single row view, group by and chart; sprint 53: application settings, user preferences and items kept per user, dynamic translations, `meta.data_export` and data export downloads, display image and geocoded address items; sprint 52: every dynamic action event and action, Ajax callbacks, an error handling function, the session timeout warning; sprint 51: checked imports, application backups, availability and Run only, feedback, type-specific attribute help; sprint 50: lost update detection, warn on unsaved changes, the URL and search regions with search configurations, the developer toolbar with a session state viewer, and e-mail through SMTP with OAuth2, Microsoft Graph, Amazon SES and HTTP APIs; import checks, application availability, property help and e-mail compared again; 2026-10-06: pgkiln 0.31.0, in progress: static application files and the Execute JavaScript dynamic action; region, item, dynamic action and process plug-ins; conditional and dynamic theme styles; XML and Excel in `meta.parse_data`, zips in SQL, `meta.v_boolean`; file items in S3-compatible object storage; map layers by the visible area and as vector tiles; a graphical query builder; tenants for workflows and tasks; application files as YAML and region static IDs; Lucide icons and icon modifiers; PWA push notifications; 0.30.0: 136 icons and an icon picker; an axe-core accessibility audit; cropping pictures; session sharing between applications; twenty-two built-in languages; 0.29.0: workspaces; the Iris base style; drawers; built-in template components including the metric card; Theme Roller dark-mode colours, live preview and template options on items and report columns; report selection across pages; instance settings; fourteen built-in languages; 0.28.0: AI with Claude and OpenAI; 0.27.0: Data Reporter; sample data generator; create application from several sheets, pasted data or existing tables; 0.26.0: working copies with a three-way merge; theme, library and boilerplate applications with subscriptions; 0.25.0: Gantt, pyramid and polar charts; map layers, clustering and server-side spatial filters; REST data sources that write back from forms and grids and synchronise into tables, OAuth2 password and refresh-token grants; debug messages per request and an install/upgrade log; `meta.web_request()` and `meta.parse_data()`; Theme Roller style variants and template options; 0.24.0: automations with several actions, error handling per row and runs from SQL; invoke-API workflow steps; Unload Data in the Data Workshop; create page wizards for cards, calendar, chart, map, faceted search, form and master-detail; create an application from a file; 0.23.0: interactive grid aggregates, frozen/moved/resized columns, layouts and saved grid reports, master-detail, row actions and copy/paste; download processes, execution chains in the background, workflow processes, branches to a function's URL or another app, the Dialog Closed event; number format masks, automatic time zone, runtime messages in German, French and Spanish; SQL scripts, Quick SQL, a query builder, XML loading and data load definitions; custom authentication, lists, page and application locks with developer comments, supporting objects; 0.22.0: keyset paging, report PDFs and REST collections streamed from a cursor, database-account authentication; 0.21.0: HTTP-header authentication behind a reverse proxy; 0.20.0: a popup list of values with server-side search; 0.19.0: row-range pagination, maximum row counts and row limits, lazy loading and caching of regions, streamed CSV/Excel downloads; 0.18.0: calendar week/day/list views with drag and drop, bubble/gauge/funnel/radar charts and drill-down, smart filters, a region display selector and more facet types, computations, conditional branches, build options, menu buttons, REST data sources and web credentials, rich text/Markdown, rating, combobox, date range and QR code items; 0.17.0: an App Builder home, workspace dashboard and utilities like APEX's; 0.16.0: a Page Designer with drag-and-drop layout, a code editor with autocomplete, template components and plug-ins, parallel branches and versions of workflows, the `pgkiln` command line with one file per component; 0.15.0: drop and paste files, heat maps, filtering a report by the map area; 0.14.0: stacked, combo, scatter and pie charts, several files per upload item; 0.13.0: map and tree regions; 0.12.0: REST modules in the builder; 0.11.0: workflows and Progressive Web Apps; 0.10.0: LDAP, SAML, "Keep me signed in", document templates, JSON loading, approvals and the task list; pgkiln installs no application, HR is an example).
11
11
 
12
12
  ## At a glance
13
13
 
@@ -23,7 +23,7 @@ Last reviewed: 2026-10-21 against **APEX 26.2** (sprints 121, 123–125: the bui
23
23
  | Data and integration | 13 | 0 | 0 | 2 | REST source catalogs from OpenAPI documents; Generate DDL and schema comparison; `meta.data_export` and data export downloads (CSV, JSON, XML, HTML, Excel, PDF); e-mail through SMTP (password or OAuth2), Microsoft Graph, Amazon SES and HTTP APIs; REST APIs via PostgREST, REST data sources that write back and synchronise, web credentials with OAuth2 grants, CSV/XLSX/JSON/XML loading with saved definitions and unloading, SQL scripts and Quick SQL, report PDFs and document templates |
24
24
  | Workflow, automation and AI | 6 | 0 | 0 | 0 | Scheduled automations with several actions and runs from SQL, approvals, a task list and workflows with parallel branches, versions and invoke-API steps; AI with Claude or OpenAI: *Generate text with AI*, an assistant region with tools, natural-language report filters and blueprints |
25
25
  | Administration | 14 | 0 | 0 | 0 | An APEX-like sign-in with a workspace and a Workspace home; a mail queue dashboard, a workspace's own mail service and network access list (26.1 / 26.2); a workspace's components exported and imported as one file; workspace message, environment banner and utilization; isolated workspaces with their own database logins and roles, and workspace administrators; application availability and Run only, automatic backups, user feedback; a developer toolbar with a session state viewer and debug per session; Top SQL per app; debug messages per request; an install/upgrade log |
26
- | APEX 26.2 workspace (WS-1 … WS-13) | 13 | 0 | 0 | 1 | Workspace home, Data Reporter as a workspace tool, Team Development, AI Agents, AI interactive reports, Workflow 26.2, the mail queue, workspace mail and network access, the 26.1 component details, the App Builder list's details, the Pillar navigation appearances and data security per table (rows, columns and masked values), the App Gallery's single-topic sample apps, UX Pattern Catalog and Utility Apps; the builder in six languages |
26
+ | APEX 26.2 workspace (WS-1 … WS-13) | 13 | 0 | 0 | 1 | Workspace home, Data Reporter as a workspace tool, Team Development, AI Agents, AI interactive reports, Workflow 26.2, the mail queue, workspace mail and network access, the 26.1 component details, the App Builder list's details, the Pillar navigation appearances and data security per table (rows, columns and masked values), the App Gallery's single-topic sample apps, UX Pattern Catalog and Utility Apps; the builder in eleven languages (APEX's ten and Nederlands) |
27
27
  | **Total** | **161** | **0** | **0** | **4** | 165 APEX features compared: 98% available, none missing, 4 deliberately not planned |
28
28
 
29
29
  (Counts are of the rows in the tables below. A review on 2026-10-06 added 18 rows for APEX features that were
@@ -138,7 +138,7 @@ the 26.2 comparison.)
138
138
  | APEX accounts | ✅ | Instance-wide user directory, bcrypt, session rotation, idle and absolute timeouts |
139
139
  | Application Access Control (roles per app, any-user switch) | ✅ | Access control per application |
140
140
  | Social sign-in / OpenID Connect | ✅ | Any OIDC provider (Entra ID, Google, Okta, Keycloak, …): PKCE, group → role mapping, account linking, automatic accounts |
141
- | Multi-factor authentication | ✅ | As in APEX: through the identity provider (OpenID Connect, SAML). Beyond APEX (sprints 126–128): the builder itself has two-factor sign-in with passkeys (WebAuthn, also on their own without a password), authenticator apps (TOTP) and recovery codes, trusted browsers, an instance and per-workspace policy with a grace period and lockout recovery ([chapter 3](guide/03-builder.md#two-factor-sign-in)). Sprint 130: application users too, per application (off, optional, required, required for roles) with authenticator apps and recovery codes, added while signing in or on My account, reset from Users; sprint 131: passkeys, e-mail codes as a fallback, step-up per authorization scheme and REST API tokens only after a second step ([chapter 8](guide/08-security.md#two-factor-sign-in)). Sprint 132: pgkiln checks that the identity provider did multi-factor sign-in (`amr` / `acr`, SAML `AuthnContextClassRef`), requests it, steps up through the provider, or asks its own second step after it ([chapter 8](guide/08-security.md#multi-factor-sign-in-at-the-identity-provider)) |
141
+ | Multi-factor authentication | ✅ | As in APEX: through the identity provider (OpenID Connect, SAML). Beyond APEX (sprints 126–128): the builder itself has two-factor sign-in with passkeys (WebAuthn, also on their own without a password), authenticator apps (TOTP) and recovery codes, trusted browsers, an instance and per-workspace policy with a grace period and lockout recovery ([chapter 3](guide/03-builder.md#two-factor-sign-in)). Sprint 130: application users too, per application (off, optional, required, required for roles) with authenticator apps and recovery codes, added while signing in or on My account, reset from Users; sprint 131: passkeys, e-mail codes as a fallback, step-up per authorization scheme and REST API tokens only after a second step ([chapter 8](guide/08-security.md#two-factor-sign-in)). Sprint 132: pgkiln checks that the identity provider did multi-factor sign-in (`amr` / `acr`, SAML `AuthnContextClassRef`), requests it, steps up through the provider, or asks its own second step after it ([chapter 8](guide/08-security.md#multi-factor-sign-in-at-the-identity-provider)). Sprint 133: lockout checks (instance key and its backup, clock, passkey domain, break-glass administrators) and `pgkiln admin rotate-key` ([chapter 3](guide/03-builder.md#lockout-checks)) |
142
142
  | Change own password | ✅ | A built-in *My account* page (APEX offers the API `CHANGE_CURRENT_USER_PW`) |
143
143
  | Password expiry, change on first use, admin reset, complexity | ✅ | Lifetime in days, expire/unexpire, admin reset, length and letters+digits rules, unlock |
144
144
  | Lockout after failed sign-ins | ✅ | Per user and per IP, time-based (APEX: until an administrator unlocks) |
@@ -221,7 +221,7 @@ the 26.2 comparison.)
221
221
 
222
222
  | APEX | pgkiln | Notes |
223
223
  |---|---|---|
224
- | Developer accounts, workspace sign-in | ✅ | (sprint 61) The builder's sign-in page like APEX's: workspace (optional; it becomes the current one, a wrong one answers like a wrong password), username, password with a Show button, *Remember workspace and username*, a link to Administration. (sprint 68) **Find my workspace**: developers' e-mail addresses, and a mail with their workspaces through the builder's mail service (the same answer for every address, limited per address and IP). (sprint 121) The sign-in page's language links: Deutsch, English, Español, Français, Nederlands, Português (WS-7). (sprint 129, SEC-1) **Single sign-on for developers** (APEX: the workspace's authentication scheme): the applications' OpenID Connect and SAML providers and LDAP directories can sign developers in to the builder, linked by the provider's stable subject (or by the developer on Security), created from a developers group, with an administrators group; a workspace can require it of its developers, with break-glass administrators who keep the password and `pgkiln admin builder-sign-in password` ([chapter 3](guide/03-builder.md#single-sign-on-for-developers)) |
224
+ | Developer accounts, workspace sign-in | ✅ | (sprint 61) The builder's sign-in page like APEX's: workspace (optional; it becomes the current one, a wrong one answers like a wrong password), username, password with a Show button, *Remember workspace and username*, a link to Administration. (sprint 68) **Find my workspace**: developers' e-mail addresses, and a mail with their workspaces through the builder's mail service (the same answer for every address, limited per address and IP). (sprint 121) The sign-in page's language links: Deutsch, English, Español, Français, Nederlands, Português (WS-7); (sprint 134) also Italiano, 中文 (简体), 中文 (繁體), 日本語 and 한국어 (SEC-5). (sprint 129, SEC-1) **Single sign-on for developers** (APEX: the workspace's authentication scheme): the applications' OpenID Connect and SAML providers and LDAP directories can sign developers in to the builder, linked by the provider's stable subject (or by the developer on Security), created from a developers group, with an administrators group; a workspace can require it of its developers, with break-glass administrators who keep the password and `pgkiln admin builder-sign-in password` ([chapter 3](guide/03-builder.md#single-sign-on-for-developers)) |
225
225
  | Workspace home (tool cards, top apps and users, summary, workspace and system message) | ✅ | (sprint 109) `/builder/home` opens after sign-in ([chapter 3](guide/03-builder.md#workspace-home)): App Builder, SQL Workshop, Data Reporter and App Gallery cards; the workspace message edited in place; a Summary of applications, tables, developers and reporting applications; top applications, users and developers over an hour, a day or a week; a system message with the server's version and, with the optional release check (`PGKILN_RELEASE_CHECK`, off by default), *pgkiln X is available*. The App Builder moved to `/builder/apps`; `/builder` opens either, per workspace. |
226
226
  | Workspace message, environment banner, workspace utilization, preferences and extension links (Manage Service) | ✅ | (sprint 61) An **Administration** menu in the icon rail; administrators and workspace administrators set a **workspace message** (on the App Builder home) and an **environment banner** (a coloured label on every builder page of the workspace), and see **workspace utilization** (applications, pages, page views, users, static files, schema storage) ([chapter 3](guide/03-builder.md#workspace-message-and-environment-banner)). (sprint 62) **Workspace preferences**: the SQL Workshop and the applications' RESTful services (REST modules) on or off per workspace; **extension links** in an Extensions menu of the rail ([chapter 3](guide/03-builder.md#workspace-preferences)). **Missing:** the account login controls of APEX's preferences (pgkiln's password policy and sign-in throttling are installation-wide) |
227
227
  | Instance administration, install/upgrade logs (26.1) | ✅ | Versioned migrations (`npm run db:migrate`), every run logged; Workspace utilities → **Installation** (administrators): server version, install and upgrade runs with errors, applied migrations, and warnings for migrations the database misses or the server doesn't know ([chapter 3](guide/03-builder.md)). Workspace utilities → **Instance settings**: session length and sign-in throttling (stored in the database, over the environment variables) and an overview of the server's configuration without secrets; a server whose database lacks migrations says so (503) or applies them (`MIGRATE_ON_START`). Other settings stay environment variables |
@@ -249,7 +249,7 @@ row above where there is one.
249
249
  | WS-4 AI Agents with tools | ✅ | (sprint 111) AI Agents and AI Tools as shared components, a Navigate tool, Gemini and OpenAI-compatible services ([Workflow, automation and AI](#workflow-automation-and-ai)) |
250
250
  | WS-5 AI interactive reports: chips, computed columns | ✅ | (sprint 112) *Ask in your own words* with chips, Undo and computed columns; a phrase parser that needs no AI service; (sprint 122) phrases set faceted search and smart filter facets |
251
251
  | WS-6 Workflow 26.2: outcomes, migrating running instances, drafts, diagram export | ✅ | (sprint 114) Custom task outcomes, task events, Send E-Mail and draft steps, migrating running instances, the diagram as SVG / PNG ([Workflow, automation and AI](#workflow-automation-and-ai)) |
252
- | WS-7 The builder in more languages | ✅ | (sprint 121) The builder in Deutsch, English, Español, Français, Nederlands and Português: links on the sign-in page, a language menu in the status bar, the choice stored per developer (migration 127); builder texts are keyed message files with a coverage check in CI, also for the builder's own JavaScript (sprint 123). Translated (sprints 121, 123–125): the builder's frame, sign-in page, Workspace home, App Builder home, an application's home and tabs, the Page Designer's toolbar, menus, tree and gallery, the SQL Workshop's home and tabs, the SQL Worksheet, Object Browser and Table Properties, Shared Components, an application's settings, Users, identity providers, Developers and Workspaces ([chapter 3](guide/03-builder.md#choosing-the-builder-language)). Still English: the rest of Administration (mail queue, network access, database users, dashboard, utilities, LDAP, instance settings), the other SQL Workshop tools and the region and report settings, until they move over; by design the property editor's and component forms' field names and help |
252
+ | WS-7 The builder in more languages | ✅ | (sprint 121) The builder in Deutsch, English, Español, Français, Nederlands and Português, and (sprint 134, SEC-5) Italiano, 中文 (简体), 中文 (繁體), 日本語 and 한국어 with CJK font stacks: links on the sign-in page, a language menu in the status bar, the choice stored per developer (migration 127); builder texts are keyed message files with a coverage check in CI, also for the builder's own JavaScript (sprint 123). Translated (sprints 121, 123–125): the builder's frame, sign-in page, Workspace home, App Builder home, an application's home and tabs, the Page Designer's toolbar, menus, tree and gallery, the SQL Workshop's home and tabs, the SQL Worksheet, Object Browser and Table Properties, Shared Components, an application's settings, Users, identity providers, Developers and Workspaces ([chapter 3](guide/03-builder.md#choosing-the-builder-language)). Still English: the rest of Administration (mail queue, network access, database users, dashboard, utilities, LDAP, instance settings), the other SQL Workshop tools and the region and report settings, until they move over; by design the property editor's and component forms' field names and help |
253
253
  | WS-8 App Gallery: more sample apps, Utility Apps | ✅ | (sprint 120) Four tabs with counts and a search that also works without JavaScript ([chapter 3](guide/03-builder.md#app-gallery)). *Sample Apps*: HR Demo, Tasks, ten single-topic apps (Sample Charts, Sample Cards, Sample Calendar, Sample Interactive Grids, Sample Dynamic Actions, Sample Reporting; sprint 122: Sample Maps, Sample Approvals, Sample Data Loading, Sample Files) and the **UX Pattern Catalog**, each with its own schema, data, demo account and explanatory texts, installed by administrators from one SQL file in one transaction; *Utility Apps*: Lookup Lists, Release Notes and Announcements as blueprints any developer installs into the workspace. APEX's 27 sample apps include topics pgkiln shows in HR Demo instead (REST, trees, collections); no remote catalogue |
254
254
  | WS-9 Mail queue reporting, workspace SMTP, workspace network ACLs | ✅ | (sprint 118) Administration → Mail queue (per hour and per workspace / application, the slowest provider calls, failures with the provider's answer, Retry and Purge), a workspace's own mail service, and a workspace's network access list that narrows the installation's allow-list for every outgoing call ([Administration](#administration)) |
255
255
  | WS-10 Universal Theme 26.2: Pillar appearances, navigation polish | ✅ | (sprint 117) Theme Roller → Navigation appearance Pillar Light / Pillar Dark per application or style, with a header strip colour for light and dark mode; the current page filled, its parents bold with an accent guide line; `u-color-*-subtle` utilities; a lighter processing indicator; RTL mirrored |
@@ -309,6 +309,11 @@ Small but real differences, for teams comparing the two:
309
309
  the ID token's `amr` / `acr` or the SAML `AuthnContextClassRef`, step-up goes back to it for a fresh multi-factor
310
310
  sign-in, and pgkiln's own second step can follow a provider that cannot enforce MFA
311
311
  ([chapter 8](guide/08-security.md#multi-factor-sign-in-at-the-identity-provider)). APEX trusts the provider's policy.
312
+ - (sprint 133) **Lockout checks**: Instance settings and `pgkiln admin check` warn before anyone is locked out: secrets
313
+ the instance key can't decrypt, a key without a confirmed backup, clock drift that breaks authenticator codes,
314
+ passkeys of another domain (also before a move, with `--url`) and single sign-on without a break-glass
315
+ administrator; `pgkiln admin rotate-key` changes the instance key in one transaction
316
+ ([chapter 3](guide/03-builder.md#lockout-checks)).
312
317
  - One RLS policy set protects both the web UI and the REST API.
313
318
  - An import can be checked before it commits (`pgkiln import --check`): SQL that names a missing
314
319
  table or column refuses the deployment instead of failing at run time.
@@ -185,7 +185,8 @@ which is read at startup; real environment variables take precedence.
185
185
  | `OPENAI_API_KEY` | *(none)* | Default API key of AI services with the provider OpenAI that have no key of their own |
186
186
  | `GEMINI_API_KEY` | *(none)* | (sprint 111) Default API key of AI services with the provider Gemini that have no key of their own |
187
187
  | `OPENAI_COMPATIBLE_API_KEY` | *(none)* | (sprint 111) Default API key of OpenAI-compatible AI services (Ollama, vLLM, Azure OpenAI) that have no key of their own; without either, no key is sent (`none`) |
188
- | `PGKILN_SECRET_KEY` | *(none)* | Encrypts the secrets of web credentials and the API keys of AI services; at least 32 characters (e.g. `openssl rand -base64 32`). Keep it outside the database; changing it means entering the secrets again ([chapter 19](19-rest-data-sources.md)) |
188
+ | `PGKILN_SECRET_KEY` | *(none)* | Encrypts the secrets of web credentials and the API keys of AI services; at least 32 characters (e.g. `openssl rand -base64 32`). Keep it outside the database; change it with `pgkiln admin rotate-key` ([chapter 3](03-builder.md#lockout-checks)), otherwise the secrets must be entered again |
189
+ | `PGKILN_OLD_SECRET_KEY` | *(none)* | (0.67) Only for `pgkiln admin rotate-key`: the key the secrets are stored with now |
189
190
  | `PGKILN_REST_ALLOWED_HOSTS` | *(none: no outgoing calls)* | Hosts REST data sources and `invoke_api` may call: `api.example.com`, `*.example.com`, `host:8443`, `*` (any public host) ([chapter 19](19-rest-data-sources.md#server-configuration-and-the-allow-list)); a workspace's [network access list](03-builder.md#network-access) can narrow it, and the SMTP server of a workspace's own mail service must be on it |
190
191
  | `PGKILN_REST_PRIVATE_HOSTS` | *(none)* | Hosts that may resolve to private, loopback or link-local addresses (also allows them) |
191
192
  | `PGKILN_PUSH_HOSTS` | the browsers' push services | The hosts push notifications may be posted to: `fcm.googleapis.com,updates.push.services.mozilla.com,web.push.apple.com,*.notify.windows.com` when unset ([chapter 17](17-mobile.md#push-notifications)) |
@@ -272,7 +273,9 @@ fixed version in `PGKILN_IMAGE`, change it first); `up -d` replaces the containe
272
273
  container migrates the database before it starts serving. A `compose.yaml` from pgkiln 0.51.0 or older has
273
274
  `pull_policy: missing` under `pgkiln`, which makes `docker compose pull` skip an image that is already present:
274
275
  delete that line (or take the current `deploy/compose.yaml`) before the first upgrade this way. Back up first (`docker compose exec db pg_dump -U pgkiln pgkiln > backup.sql`).
275
- Keep `PGKILN_SECRET_KEY`: without it, stored secrets (web credentials, AI keys, push keys) can't be decrypted.
276
+ Keep `PGKILN_SECRET_KEY`: without it, stored secrets (web credentials, AI keys, push keys, authenticator apps) can't
277
+ be decrypted. Keep a copy outside the server and confirm it on Instance settings; to change it, use
278
+ `pgkiln admin rotate-key` ([chapter 3](03-builder.md#lockout-checks)).
276
279
 
277
280
  ## Upgrading
278
281
 
@@ -170,13 +170,46 @@ Sign-ins are in the activity log as `login` with *builder sso:company* or *build
170
170
  | No administrator can sign in | On the server: `pgkiln admin reset-2fa <developer> --reason "…"` ([chapter 18](18-cli.md)), then sign in with the password |
171
171
  | The policy locks everyone out | On the server: `pgkiln admin set-2fa-policy off` (also clears the workspaces' own rules) |
172
172
  | The identity provider is down and a workspace requires single sign-on | A break-glass administrator signs in with the password and turns the workspace's rule off; without one, on the server: `pgkiln admin builder-sign-in password` |
173
- | Codes are always wrong | Check the time on the phone and on the server (codes allow 30 seconds either way) |
174
- | The instance key was lost or changed | The apps' secrets can't be read: reset the developers (`pgkiln admin reset-2fa`); recovery codes still work |
173
+ | Codes are always wrong | Check the time on the phone and on the server (codes allow 30 seconds either way); *Lockout checks* compares the server's clock |
174
+ | The instance key was changed | Set the old key again and rotate properly: `pgkiln admin rotate-key` ([below](#lockout-checks)) |
175
+ | The instance key was lost | The apps' secrets can't be read: reset the developers (`pgkiln admin reset-2fa`); passkeys and recovery codes still work |
175
176
 
176
177
  The command line needs the owner's database connection (`DATABASE_URL`), so only someone with access to the server
177
178
  can use it. It writes to the activity log and mails the administrators too. With Docker:
178
179
  `docker compose exec pgkiln node bin/pgkiln.js admin reset-2fa admin`.
179
180
 
181
+ ### Lockout checks
182
+
183
+ (0.67) **Instance settings** starts with *Lockout checks*: what could keep developers or application users out later,
184
+ found before it happens. The Workspace home tells administrators how many need attention.
185
+
186
+ | Check | Needs attention when |
187
+ |---|---|
188
+ | Instance key | Secrets are stored but `PGKILN_SECRET_KEY` is not set, or some can't be decrypted with it (the key changed without a rotation) |
189
+ | Instance key backed up | No administrator confirmed a copy of the current key (*I have a copy of this key*, or `pgkiln admin key-backed-up`). The confirmation is kept per key fingerprint, so a new key asks again |
190
+ | Clock | The server's clock is 10 seconds or more off the database's, or GitHub's when the [release check](#workspace-home) is on; from 30 seconds authenticator codes fail |
191
+ | Passkey domain | Passkeys were made for another domain than `PUBLIC_URL` (or `PGKILN_RP_ID`) gives, with the number of people who have no other factor |
192
+ | Break-glass administrators | A workspace requires single sign-on and there is no break-glass administrator, or one without a second factor while two-factor sign-in is required |
193
+
194
+ The server writes the same problems to its log when it starts, and `pgkiln admin check` prints them on the server
195
+ (exit code 1 when one needs attention). **Before moving to another address**, run `pgkiln admin check --url
196
+ https://new.example.com`: it lists the passkeys that won't work there and who has no other factor, so they can add an
197
+ authenticator app or keep their recovery codes at hand first.
198
+
199
+ **Rotating the instance key.** Authenticator apps of developers and app users, web credentials, mail and AI keys and
200
+ the push key are encrypted with `PGKILN_SECRET_KEY`; passkeys and recovery codes are not. To change the key, stop the
201
+ servers (or accept that sign-ins with an authenticator app fail for the minute in between), then on the server:
202
+
203
+ ```bash
204
+ PGKILN_OLD_SECRET_KEY='the current key' PGKILN_SECRET_KEY='the new key' pgkiln admin rotate-key --dry-run
205
+ PGKILN_OLD_SECRET_KEY='the current key' PGKILN_SECRET_KEY='the new key' pgkiln admin rotate-key
206
+ ```
207
+
208
+ It re-encrypts every stored secret in one transaction: a secret that neither key decrypts stops it and nothing
209
+ changes; a secret already under the new key is left alone, so running it twice is harmless. Start the servers with the
210
+ new key (an isolated workspace's database logins get their new passwords on first use), keep a copy of it and confirm
211
+ that on Instance settings. The rotation is in the activity log (`secret_key`) and mailed to the administrators.
212
+
180
213
  ## Workspaces
181
214
 
182
215
  A workspace (APEX: a workspace) groups applications and the developers who build them, for example per team or
@@ -399,8 +432,11 @@ is in the server log, not on the page). Scripts get the plain answers they alway
399
432
 
400
433
  ### Choosing the builder language
401
434
 
402
- (sprint 121, APEX: the builder's language links) The builder speaks **Deutsch, English, Español, Français, Nederlands
403
- and Português** (Brazilian). English is the default.
435
+ (sprint 121, APEX: the builder's language links) The builder speaks **Deutsch, English, Español, Français, Italiano,
436
+ Nederlands, Português** (Brazilian), and (sprint 134) **中文 (简体)** (Simplified Chinese), **中文 (繁體)**
437
+ (Traditional Chinese), **日本語** (Japanese) and **한국어** (Korean): APEX's ten builder languages and Dutch. English
438
+ is the default. In Chinese, Japanese and Korean the builder uses your system's fonts for that language (PingFang,
439
+ Microsoft YaHei / JhengHei, Hiragino, Yu Gothic, Apple SD Gothic Neo, Malgun Gothic, or Noto Sans CJK on Linux).
404
440
 
405
441
  - **On the sign-in page** the languages are links under the form: choosing one shows the sign-in page in that
406
442
  language and, when you then sign in, stores it as your builder language. The choice is remembered on this device
@@ -22,6 +22,10 @@ src/
22
22
  env.ts .env loader (imported first)
23
23
  migrate.ts applies db/migrations and examples (scripts/migrate.ts, pgkiln migrate); logs each run that applies
24
24
  instance.ts instance settings (meta.setting over environment variables, cached 30 s) and the configuration overview
25
+ instance-checks.ts (sprint 133, SEC-6) lockout checks: instance key (unreadable secrets, backup confirmed per fingerprint in
26
+ meta.setting secret_key_backup), clock against the database and GitHub's Date header, passkeys of another
27
+ RP ID, break-glass administrators; rotateKey() re-encrypts every *_enc column in one transaction;
28
+ used by Instance settings, the Workspace home (cached count), server start-up and `pgkiln admin check`
25
29
  release-check.ts (sprint 109) "pgkiln X is available": meta.setting 'release_check' over PGKILN_RELEASE_CHECK (off by default);
26
30
  GitHub's releases/latest (PGKILN_RELEASE_URL in tests), 5 s timeout, 1 MB, cached a day per process,
27
31
  never under node --test without PGKILN_RELEASE_URL; parseRelease keeps a semver and an https link only
@@ -143,7 +147,8 @@ src/
143
147
  nextRuns in a time zone, describeSchedule in words, the builder's presets and fields
144
148
  pgcron.ts (sprint 101, DA-12) pg_cron for SQL Workshop → Scheduling: cronState (installed, loaded, cron.database_name,
145
149
  access), jobs and runs, jobSql/activeSql/unscheduleSql/purgeSql (reviewed, then applySql), runNow
146
- secrets.ts secrets at rest (web credentials): AES-256-GCM with PGKILN_SECRET_KEY
150
+ secrets.ts secrets at rest (web credentials): AES-256-GCM with PGKILN_SECRET_KEY (or a key given, for rotate-key);
151
+ keyFingerprint()
147
152
  websources.ts web credentials (OAuth2 client credentials/password/refresh token grants, token cache, stored refresh
148
153
  tokens) and REST data sources: requests, JSON paths, typed rows, response cache, write-back operations
149
154
  (callOperation); invoke(): the invoke API call shared by the invoke_api process and workflow step
@@ -279,7 +284,7 @@ src/
279
284
  ui.ts IDE shell (icon rail, toolbar, breadcrumb, status bar), builder theme, form helpers, CSRF check, app tabs
280
285
  i18n.ts (sprint 121) the builder's own texts: BUILDER_LANGUAGES, tr(s) / translatorFor(lang) → tx(key, params),
281
286
  tx.rich (markup in a sentence), tx.dyn (keys made at run time), tx.label (known breadcrumb labels)
282
- i18n/ en.ts defines the builder's keys; de, es, fr, nl, pt are Records of the same keys
287
+ i18n/ en.ts defines the builder's keys; de, es, fr, it, nl, pt, zh-cn, zh-tw, ja, ko (sprint 134) are Records of the same keys
283
288
  language.ts (migration 127) the status bar's language menu (POST /builder/language), the sign-in page's
284
289
  language links (?lang=, a cookie), meta.developer.language
285
290
  routes.ts sign-in, app home, settings, activity, developers, create (POST, via newapp.ts)/import (POST)
@@ -420,7 +425,8 @@ src/
420
425
  write-back operations, synchronisation settings, Synchronise now and run history
421
426
  templates.ts template components: preview, plug-in export/import, region settings, report column templates
422
427
  code-editor.ts code fields (data-code marks), /builder/code/completions (scoped to the app's role), /builder/code/check
423
- instance.ts Workspace utilities → Instance settings (src/instance.ts: session and sign-in settings, configuration overview)
428
+ instance.ts Workspace utilities → Instance settings (src/instance.ts: session and sign-in settings, configuration overview;
429
+ Lockout checks from src/instance-checks.ts and POST /instance/key-backup)
424
430
  gallery.ts the App Gallery (sprint 61, 120): examples/gallery/gallery.json, sample apps (administrators: migrate --example,
425
431
  or one SQL file of examples/ or examples/gallery/samples/ in one transaction), starter and utility apps
426
432
  (blueprints of starters/ and utilities/ → openBlueprint's review), custom apps (the workspace's boilerplates);
@@ -577,8 +583,11 @@ test/
577
583
  ## Builder texts in more languages
578
584
 
579
585
  (sprint 121) The builder's own texts are keyed messages, like the runtime's: `src/builder/i18n/en.ts` defines every
580
- key (`<screen>.<what>`, e.g. `rail.app_builder`, `pd.menu.create`, `ab.count` with `{n}`), and `de.ts`, `es.ts`,
581
- `fr.ts`, `nl.ts` and `pt.ts` are `Record<BuilderKey, string>` of the same keys. A page takes its translator from the
586
+ key (`<screen>.<what>`, e.g. `rail.app_builder`, `pd.menu.create`, `ab.count` with `{n}`), and the other ten files
587
+ (`de.ts`, `es.ts`, `fr.ts`, `it.ts`, `nl.ts`, `pt.ts`, (sprint 134) `zh-cn.ts`, `zh-tw.ts`, `ja.ts`, `ko.ts`) are
588
+ `Record<BuilderKey, string>` of the same keys. A language's code is its BCP 47 tag (`zh-CN`, `zh-TW`), used as it is in
589
+ `<html lang>`, the cookie and `meta.developer.language`; `public/builder.css` gives the CJK languages their own font
590
+ stacks by `:lang()`. A page takes its translator from the
582
591
  session and uses it for every text it shows:
583
592
 
584
593
  ```ts
@@ -593,7 +602,7 @@ an optional last argument (`appHeader(a, 'pages', s)`, `workshopTabs('sql', s)`)
593
602
  breadcrumb labels (`tx.label`) so pages that aren't moved yet still get a translated trail.
594
603
 
595
604
  **Moving a screen over**: replace its literal texts with `tx('key')`, add each key with its English text to `en.ts`
596
- (keep the English exactly as it was: tests and e2e tests assert it), then add the key to the five other files
605
+ (keep the English exactly as it was: tests and e2e tests assert it), then add the key to the ten other files
597
606
  (TypeScript refuses a file with a missing or an unknown key). A sentence with a link is one key with a `{link}`
598
607
  placeholder and `tx.rich`, not pieces glued together; a count has a `_one` and a plural key; never lower-case a
599
608
  translated label (German nouns). Flash messages are translated where they are set.
@@ -55,6 +55,9 @@ any (see [what is not exported](03-builder.md#export-format)).
55
55
  | `pgkiln admin reset-2fa <developer> [--reason <text>]` | (0.60) Removes a developer's authenticator apps and recovery codes and ends their builder sessions: [locked out?](03-builder.md#locked-out) |
56
56
  | `pgkiln admin set-2fa-policy off\|admins\|all [--grace <days>]` | (0.60) Sets the builder's [two-factor policy](03-builder.md#two-factor-sign-in); `off` always works (and, 0.62, clears every workspace's own rule), the others need two administrators with an app |
57
57
  | `pgkiln admin builder-sign-in password` | (0.63) Turns off every workspace's [single sign-on rule](03-builder.md#single-sign-on-for-developers), so developers may sign in with the pgkiln password again; logged and mailed to the administrators |
58
+ | `pgkiln admin rotate-key [--dry-run]` | (0.67) Re-encrypts every stored secret from `PGKILN_OLD_SECRET_KEY` to `PGKILN_SECRET_KEY` in one transaction ([rotating the instance key](03-builder.md#lockout-checks)); logged and mailed to the administrators |
59
+ | `pgkiln admin key-backed-up` | (0.67) Records that a copy of the current `PGKILN_SECRET_KEY` is kept outside the server |
60
+ | `pgkiln admin check [--url <address>]` | (0.67) Prints the [lockout checks](03-builder.md#lockout-checks); `--url` checks passkeys against a new public address. Exit code 1 when one needs attention |
58
61
 
59
62
  `users` reads the password from standard input (the first line, e.g. from a secret store:
60
63
  `printf '%s\n' "$PW" | pgkiln users add ops --developer`) or asks for it twice on a terminal. It is
@@ -63,8 +63,8 @@ sources (including write-back, synchronisation and the response cache), `meta.we
63
63
  API, token endpoints, object storage and REST source catalogs. Refusals are logged in the
64
64
  application's debug log and listed under *Refused calls*.
65
65
 
66
- **Changing `PGKILN_SECRET_KEY`** makes the stored secrets unreadable: pgkiln then reports that
67
- the secret must be entered again. Keep the key with your other server secrets, outside the
66
+ **Changing `PGKILN_SECRET_KEY`** without `pgkiln admin rotate-key` ([chapter 3](03-builder.md#lockout-checks))
67
+ makes the stored secrets unreadable: pgkiln then reports that the secret must be entered again. Keep the key with your other server secrets, outside the
68
68
  database: a database dump alone does not reveal the secrets.
69
69
 
70
70
  ## Web credentials
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pgkiln",
3
- "version": "0.66.0",
3
+ "version": "0.68.0",
4
4
  "description": "Open source low-code, SQL-driven application builder for PostgreSQL, inspired by Oracle APEX",
5
5
  "keywords": [
6
6
  "postgresql",
@@ -1582,3 +1582,18 @@ pre.wrap-pre { white-space: pre-wrap; overflow-wrap: anywhere; }
1582
1582
  .settings-panel[data-tab="signin"] .field > .help,
1583
1583
  .settings-panel[data-tab="signin"] p.small { max-width: 75ch; }
1584
1584
  .settings-panel[data-tab="signin"] h3:not(:first-child) { margin-top: 1.5rem; }
1585
+
1586
+ /* (sprint 134, SEC-5) The CJK builder languages: Inter has no Chinese, Japanese or Korean glyphs, so each language
1587
+ names its own system fonts before the generic family (a Japanese font for Chinese text shows the wrong glyph
1588
+ shapes for some characters, and the other way round). The language menu and the sign-in links show each name in
1589
+ its own fonts. Korean wraps at spaces like Latin text rather than between any two syllables. */
1590
+ :is(.ide, .ide-login):lang(zh-CN), :is(.ide-lang-form, .signin-langs) :lang(zh-CN) {
1591
+ --font: "Inter", "Segoe UI Variable Text", "Segoe UI", system-ui, -apple-system, "PingFang SC", "Microsoft YaHei UI", "Microsoft YaHei", "Noto Sans SC", "Noto Sans CJK SC", "Source Han Sans SC", sans-serif; }
1592
+ :is(.ide, .ide-login):lang(zh-TW), :is(.ide-lang-form, .signin-langs) :lang(zh-TW) {
1593
+ --font: "Inter", "Segoe UI Variable Text", "Segoe UI", system-ui, -apple-system, "PingFang TC", "Microsoft JhengHei UI", "Microsoft JhengHei", "Noto Sans TC", "Noto Sans CJK TC", "Source Han Sans TC", sans-serif; }
1594
+ :is(.ide, .ide-login):lang(ja), :is(.ide-lang-form, .signin-langs) :lang(ja) {
1595
+ --font: "Inter", "Segoe UI Variable Text", "Segoe UI", system-ui, -apple-system, "Hiragino Sans", "Hiragino Kaku Gothic ProN", "Yu Gothic UI", Meiryo, "Noto Sans JP", "Noto Sans CJK JP", "Source Han Sans JP", sans-serif; }
1596
+ :is(.ide, .ide-login):lang(ko), :is(.ide-lang-form, .signin-langs) :lang(ko) {
1597
+ --font: "Inter", "Segoe UI Variable Text", "Segoe UI", system-ui, -apple-system, "Apple SD Gothic Neo", "Malgun Gothic", "Noto Sans KR", "Noto Sans CJK KR", "Source Han Sans KR", sans-serif; }
1598
+ :is(.ide-lang-form, .signin-langs) [lang] { font-family: var(--font); }
1599
+ :is(.ide, .ide-login):lang(ko) { word-break: keep-all; overflow-wrap: break-word; }
@@ -171,6 +171,8 @@ export const de: BuilderMessages = {
171
171
  'wh.how_upgrade': 'So aktualisieren Sie',
172
172
  'wh.upgrade_steps': 'Zum Aktualisieren: Sichern Sie die Datenbank, installieren Sie die neue Version ({npm} oder das Docker-Image {docker}), führen Sie {migrate} aus und starten Sie den Server neu.',
173
173
  'wh.check_off': 'Die Prüfung auf neue Versionen ist deaktiviert.',
174
+ 'wh.lockout': 'Prüfungen gegen Aussperren, die Aufmerksamkeit brauchen: {count}.',
175
+ 'wh.lockout_open': 'Instanzeinstellungen',
174
176
  'wh.check_failed': 'Die letzte Prüfung ist fehlgeschlagen ({error}).',
175
177
  'wh.check_failed_older': 'Die letzte Prüfung ist fehlgeschlagen ({error}); das obige Ergebnis ist älter.',
176
178
  'wh.checked': 'Geprüft {ago}.',
@@ -1,6 +1,6 @@
1
1
  // The builder's own texts in English (sprint 121, WS-7): the keys of every builder message file (i18n.ts).
2
2
  // A key is <screen>.<what>; {name} is a placeholder (filled by tx(key, { name })). Keep the other languages
3
- // (de, es, fr, nl, pt) in step: TypeScript and test/builder-i18n.test.ts refuse a missing or an extra key.
3
+ // (de, es, fr, it, nl, pt, zh-cn, zh-tw, ja, ko) in step: TypeScript and test/builder-i18n.test.ts refuse a missing or an extra key.
4
4
  // Keys made at run time (gallery.*, pos.*, slot.*, comp.*, pd.new.* …, sql.tool.*, sql.group.*) are listed here
5
5
  // too; the test checks that every region type, item type, button action, position, slot and SQL Workshop tool has one.
6
6
 
@@ -174,6 +174,8 @@ export const en = {
174
174
  'wh.how_upgrade': 'How to upgrade',
175
175
  'wh.upgrade_steps': 'To upgrade: back up the database, install the new version ({npm}, or the Docker image {docker}), run {migrate} and restart the server.',
176
176
  'wh.check_off': 'The check for new versions is off.',
177
+ 'wh.lockout': 'Lockout checks that need attention: {count}.',
178
+ 'wh.lockout_open': 'Instance settings',
177
179
  'wh.check_failed': 'The last check failed ({error}).',
178
180
  'wh.check_failed_older': 'The last check failed ({error}); the result above is older.',
179
181
  'wh.checked': 'Checked {ago}.',
@@ -171,6 +171,8 @@ export const es: BuilderMessages = {
171
171
  'wh.how_upgrade': 'Cómo actualizar',
172
172
  'wh.upgrade_steps': 'Para actualizar: haga una copia de seguridad de la base de datos, instale la nueva versión ({npm}, o la imagen Docker {docker}), ejecute {migrate} y reinicie el servidor.',
173
173
  'wh.check_off': 'La comprobación de nuevas versiones está desactivada.',
174
+ 'wh.lockout': 'Comprobaciones de bloqueo que requieren atención: {count}.',
175
+ 'wh.lockout_open': 'Ajustes de la instancia',
174
176
  'wh.check_failed': 'La última comprobación ha fallado ({error}).',
175
177
  'wh.check_failed_older': 'La última comprobación ha fallado ({error}); el resultado anterior es más antiguo.',
176
178
  'wh.checked': 'Comprobado {ago}.',
@@ -171,6 +171,8 @@ export const fr: BuilderMessages = {
171
171
  'wh.how_upgrade': 'Comment mettre à niveau',
172
172
  'wh.upgrade_steps': "Pour mettre à niveau : sauvegardez la base de données, installez la nouvelle version ({npm}, ou l'image Docker {docker}), exécutez {migrate} et redémarrez le serveur.",
173
173
  'wh.check_off': 'La recherche de nouvelles versions est désactivée.',
174
+ 'wh.lockout': 'Contrôles contre le verrouillage à examiner : {count}.',
175
+ 'wh.lockout_open': 'Paramètres de l’instance',
174
176
  'wh.check_failed': 'La dernière vérification a échoué ({error}).',
175
177
  'wh.check_failed_older': 'La dernière vérification a échoué ({error}) ; le résultat ci-dessus est plus ancien.',
176
178
  'wh.checked': 'Vérifié {ago}.',