pgkiln 0.31.0 → 0.35.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.
Files changed (107) hide show
  1. package/README.md +2 -2
  2. package/SECURITY.md +10 -0
  3. package/db/migrations/076_form_lost_update.sql +50 -0
  4. package/db/migrations/077_warn_unsaved.sql +41 -0
  5. package/db/migrations/078_url_region.sql +12 -0
  6. package/db/migrations/079_developer_toolbar.sql +53 -0
  7. package/db/migrations/080_search.sql +326 -0
  8. package/db/migrations/081_mail.sql +621 -0
  9. package/db/migrations/082_app_backups.sql +73 -0
  10. package/db/migrations/083_availability.sql +156 -0
  11. package/db/migrations/084_feedback.sql +46 -0
  12. package/db/migrations/085_page_behaviour.sql +65 -0
  13. package/db/migrations/086_data_settings.sql +599 -0
  14. package/docs/apex-feature-parity.md +55 -35
  15. package/docs/guide/01-installation.md +1 -0
  16. package/docs/guide/03-builder.md +118 -2
  17. package/docs/guide/04-pages-and-regions.md +115 -0
  18. package/docs/guide/05-items.md +47 -0
  19. package/docs/guide/06-processing.md +210 -2
  20. package/docs/guide/07-dynamic-actions.md +60 -2
  21. package/docs/guide/08-security.md +13 -2
  22. package/docs/guide/09-reference.md +21 -0
  23. package/docs/guide/11-from-apex.md +5 -1
  24. package/docs/guide/12-development.md +33 -1
  25. package/docs/guide/14-globalization.md +15 -0
  26. package/docs/guide/15-extensions.md +1 -1
  27. package/docs/guide/18-cli.md +30 -1
  28. package/docs/guide/20-ai-agents.md +3 -2
  29. package/examples/hr/hr_50_search.sql +47 -0
  30. package/examples/hr/hr_51_mail.sql +70 -0
  31. package/examples/hr/hr_52_feedback.sql +15 -0
  32. package/examples/hr/hr_53_data_settings.sql +108 -0
  33. package/package.json +3 -1
  34. package/public/app.css +62 -0
  35. package/public/app.js +408 -11
  36. package/public/builder.css +11 -0
  37. package/public/builder.js +27 -0
  38. package/src/app.ts +8 -0
  39. package/src/appfiles.ts +12 -0
  40. package/src/automations.ts +12 -0
  41. package/src/builder/advisor.ts +54 -14
  42. package/src/builder/arrange.ts +2 -2
  43. package/src/builder/availability.ts +74 -0
  44. package/src/builder/backups.ts +134 -0
  45. package/src/builder/components.ts +109 -15
  46. package/src/builder/designer.ts +8 -3
  47. package/src/builder/feedback.ts +82 -0
  48. package/src/builder/forms.ts +4 -1
  49. package/src/builder/home.ts +3 -0
  50. package/src/builder/locks.ts +15 -5
  51. package/src/builder/mail.ts +425 -0
  52. package/src/builder/newapp.ts +1 -1
  53. package/src/builder/region-help.ts +71 -0
  54. package/src/builder/routes.ts +44 -1
  55. package/src/builder/search.ts +4 -4
  56. package/src/builder/shared.ts +3 -2
  57. package/src/builder/ui.ts +7 -1
  58. package/src/cli/apps.ts +46 -5
  59. package/src/cli/main.ts +21 -5
  60. package/src/cli/mcp.ts +16 -4
  61. package/src/cli/replace.ts +36 -4
  62. package/src/geocode.ts +44 -0
  63. package/src/i18n/ar.ts +39 -0
  64. package/src/i18n/cs.ts +39 -0
  65. package/src/i18n/da.ts +39 -0
  66. package/src/i18n/de.ts +39 -0
  67. package/src/i18n/el.ts +39 -0
  68. package/src/i18n/es.ts +39 -0
  69. package/src/i18n/fi.ts +39 -0
  70. package/src/i18n/fr.ts +39 -0
  71. package/src/i18n/he.ts +39 -0
  72. package/src/i18n/it.ts +39 -0
  73. package/src/i18n/ja.ts +39 -0
  74. package/src/i18n/ko.ts +39 -0
  75. package/src/i18n/nb.ts +39 -0
  76. package/src/i18n/pl.ts +39 -0
  77. package/src/i18n/pt.ts +39 -0
  78. package/src/i18n/ru.ts +39 -0
  79. package/src/i18n/sv.ts +39 -0
  80. package/src/i18n/tr.ts +39 -0
  81. package/src/i18n/uk.ts +39 -0
  82. package/src/i18n/zh.ts +39 -0
  83. package/src/i18n.ts +78 -0
  84. package/src/mail/mail.ts +148 -0
  85. package/src/mail/providers.ts +444 -0
  86. package/src/metadata.ts +26 -8
  87. package/src/runtime/ajax.ts +97 -0
  88. package/src/runtime/authz.ts +1 -1
  89. package/src/runtime/availability.ts +37 -0
  90. package/src/runtime/context.ts +46 -6
  91. package/src/runtime/data-export.ts +94 -0
  92. package/src/runtime/data-items.ts +194 -0
  93. package/src/runtime/devbar.ts +182 -0
  94. package/src/runtime/engine.ts +26 -1
  95. package/src/runtime/feedback.ts +128 -0
  96. package/src/runtime/items.ts +8 -0
  97. package/src/runtime/processes.ts +83 -2
  98. package/src/runtime/regions.ts +8 -0
  99. package/src/runtime/render.ts +33 -7
  100. package/src/runtime/rest.ts +4 -0
  101. package/src/runtime/routes.ts +59 -5
  102. package/src/runtime/search.ts +252 -0
  103. package/src/runtime/url-region.ts +93 -0
  104. package/src/security.ts +11 -1
  105. package/src/server.ts +2 -0
  106. package/src/session.ts +8 -2
  107. package/src/workingcopy.ts +2 -2
@@ -7,26 +7,27 @@ 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-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-12 (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
 
14
14
  | Area | ✅ | 🟡 | ❌ | ➖ | In short |
15
15
  |---|---:|---:|---:|---:|---|
16
- | App Builder and development | 16 | 0 | 0 | 0 | Page Designer with drag-and-drop and a code editor, wizards, search, where used, an Advisor, a CLI with one file per component, page locks and comments, supporting objects, working copies with a three-way merge, theme/library/boilerplate apps with subscriptions; App Builder AI (pages, SQL and table descriptions) |
17
- | Regions | 19 | 1 | 3 | 0 | All everyday regions; sixteen chart types with drill-down; calendars with week/day/list views and drag and drop; faceted search, smart filters and a region display selector; interactive reports with breaks, aggregates, highlights, compute, group by, pivot, chart view and saved reports; maps (with vector tiles) and trees; template components; row ranges, lazy loading and region caching for large tables |
18
- | Items | 12 | 0 | 1 | 0 | All common items, file upload (several files per item), rich text and Markdown editors, star rating, combobox, date range, QR code, password reveal |
19
- | Logic and processing | 12 | 1 | 4 | 1 | Core APEX model complete with computations, conditional branches, build options and menu buttons, download, chain and workflow processes; JavaScript from static application files in dynamic actions; region, item, dynamic action and process plug-ins |
20
- | Security | 20 | 0 | 1 | 0 | On par or stricter (CSP without `unsafe-inline`); OIDC, SAML and LDAP; header authentication behind a proxy; database accounts; custom authentication |
21
- | User interface | 10 | 2 | 0 | 0 | Universal Theme-like and responsive; a Theme Roller with style variants and conditional, dynamic styles; about 1,700 icons with Font APEX-like modifiers |
22
- | Globalization | 5 | 1 | 1 | 0 | One translated app like 26.1; number format masks and automatic time zone; twenty-two built-in languages |
23
- | Data and integration | 9 | 0 | 2 | 2 | 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 |
16
+ | App Builder and development | 16 | 1 | 0 | 0 | Page Designer with drag-and-drop and a code editor, wizards, search, where used, an Advisor, a CLI with one file per component, page locks and comments, supporting objects, working copies with a three-way merge, theme/library/boilerplate apps with subscriptions; App Builder AI (pages, SQL and table descriptions) |
17
+ | Regions | 22 | 0 | 1 | 0 | All everyday regions, a search region over search configurations and a URL region; sixteen chart types with drill-down; calendars with week/day/list views and drag and drop; faceted search, smart filters and a region display selector; interactive reports with breaks, aggregates, highlights, compute, group by, pivot, chart view and saved reports; maps (with vector tiles) and trees; template components; row ranges, lazy loading and region caching for large tables |
18
+ | Items | 13 | 0 | 0 | 0 | All common items, file upload (several files per item), rich text and Markdown editors, star rating, combobox, date range, QR code, password reveal, display image and geocoded address |
19
+ | Logic and processing | 17 | 0 | 0 | 1 | User preferences and application settings; all dynamic action events and actions, Ajax callbacks and an error handling function; Core APEX model complete with computations, conditional branches, build options and menu buttons, download, chain and workflow processes; JavaScript from static application files in dynamic actions; region, item, dynamic action and process plug-ins |
20
+ | Security | 21 | 0 | 0 | 0 | A session timeout warning; On par or stricter (CSP without `unsafe-inline`); OIDC, SAML and LDAP; header authentication behind a proxy; database accounts; custom authentication |
21
+ | User interface | 11 | 1 | 0 | 0 | Universal Theme-like and responsive; a Theme Roller with style variants and conditional, dynamic styles; about 1,700 icons with Font APEX-like modifiers |
22
+ | Globalization | 6 | 1 | 0 | 0 | One translated app like 26.1 with dynamic translations of table values; number format masks and automatic time zone; twenty-two built-in languages |
23
+ | Data and integration | 11 | 0 | 1 | 2 | `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
- | Administration | 4 | 1 | 3 | 0 | Workspaces that group applications and developers (not a tenant boundary); Top SQL per app; debug messages per request; an install/upgrade log |
26
- | **Total** | **113** | **6** | **15** | **3** | 137 APEX features compared: 82% available, 4% partial |
25
+ | Administration | 7 | 2 | 0 | 0 | Application availability and Run only, automatic backups, user feedback; a developer toolbar with a session state viewer and debug per session; Workspaces that group applications and developers (not a tenant boundary); Top SQL per app; debug messages per request; an install/upgrade log |
26
+ | **Total** | **130** | **5** | **2** | **3** | 140 APEX features compared: 93% available, 4% partial |
27
27
 
28
28
  (Counts are of the rows in the tables below. A review on 2026-10-06 added 18 rows for APEX features that were
29
- not compared before, so the share available dropped without anything being removed.)
29
+ not compared before, and one on 2026-10-12 added two more (property help, application availability), so the share
30
+ available dropped without anything being removed.)
30
31
 
31
32
  ## App Builder and development
32
33
 
@@ -37,13 +38,14 @@ not compared before, so the share available dropped without anything being remov
37
38
  | Create page wizards | ✅ | Report and form, interactive grid, form, cards, calendar, chart, map, faceted search and master-detail (stacked grids) from any table or view, with defaults from the catalog (columns, key, dates, positions, foreign keys), an optional modal form page and a navigation entry; also from SQL (`meta.generate_page`). No side-by-side or drill-down master-detail, no wizard for smart filters or trees |
38
39
  | Page Designer | ✅ | IDE-style window (dark or light): component tree, a layout canvas with drag and drop (with keyboard and button alternatives) and a gallery of regions, items and buttons, a filterable property editor; undo/redo; panes become tabs on phones. Settings forms for report, grid, chart, cards, calendar, faceted search, smart filters, display selector, map, tree and template component regions. A code editor for SQL, PL/pgSQL, JSON and HTML with highlighting and autocomplete of tables, columns and `:ITEM` binds (no extra libraries). Drag and drop needs a mouse; on touch screens the Arrange buttons move components |
39
40
  | Shared components | ✅ | Navigation menu, **lists** (static entries with nesting, badges, conditions, authorization and build options, or a query; for list regions, the navigation menu and the navigation bar), authorization schemes, build options, lists of values, application items and processes, access control, globalization, template components and plug-ins, web credentials, REST data sources, data load definitions, supporting objects |
40
- | Export / import | ✅ | `meta.export_app()` / `meta.import_app()`: portable JSON, also in the builder |
41
+ | Export / import | ✅ | `meta.export_app()` / `meta.import_app()`: portable JSON, also in the builder (new applications; `pgkiln import --replace` and the MCP `import_app` update one in place, live for every user at the commit). (sprint 51) **Checked imports**: `pgkiln import --check` (`--dry-run`, `--force`), the MCP import (by default) and the builder's import run the Advisor inside the import's transaction (SQL planned as the application's role: missing tables, columns, functions, types, grants; references) and refuse on errors, so nothing changes; APEX doesn't check. The version an import replaces is [backed up](guide/03-builder.md#backups) first ([chapter 18](guide/18-cli.md#checking-before-an-import)) |
41
42
  | APEXlang: human-readable, diffable app files; static IDs (26.1) | ✅ | `pgkiln export --format dir`: one JSON file per component with sorted keys, SQL and HTML in sibling files, references by static id instead of database ids; `pgkiln import --replace` updates an app in place, `pgkiln diff` compares ([chapter 18](guide/18-cli.md)). (0.31) **`--format text`**: the same files as YAML (a strict subset any YAML tool reads) with the SQL and templates inline, read back losslessly ([text files](guide/18-cli.md#text-files-apexlang)); regions have a stored **Static ID** (exported as their key, rendered as `data-static-id`), other components are named by their stored names. The syntax is YAML rather than APEXlang's own, so APEXlang files don't import |
42
43
  | Working copies, merge, team development | ✅ | **Working copies** of an application ([chapter 3](guide/03-builder.md#working-copies)): a second app on the same schema and data, compared three ways per component (settings, each shared component, page, region, item, …) with the main app as it was when copied; changes on one side merge, conflicts are chosen per component with a line diff; merge into the main app or refresh the copy, keeping users, sessions, saved reports, secrets and automation switches; locks respected. Conflicts are resolved per component, not per property |
43
44
  | Application lock (26.1), page locks, comments | ✅ | Page and application locks, enforced on the server for every builder change; the owner or an administrator unlocks, and an administrator breaking a lock is logged. Developer comments per page and per app ([chapter 3](guide/03-builder.md)) |
44
45
  | Static application files | ✅ | Shared Components → **Static application files** ([chapter 3](guide/03-builder.md#static-application-files)): JavaScript, CSS, JSON, images and fonts uploaded or written in the builder, served at `/a/<alias>/static/<name>` with long caching per version, loaded by every page or by one page (APEX's *JavaScript/CSS File URLs*), exported with the application (as files in a directory export). No HTML; the CSP stays `script-src 'self'` |
45
46
  | Supporting objects (install scripts) | ✅ | Install, upgrade and deinstall scripts travel with the export (JSON and directory formats), never run on import; reviewed and run from the builder as the app's role, in one transaction, with a result per statement ([chapter 3](guide/03-builder.md#supporting-objects)) |
46
47
  | Theme, library and boilerplate application types (26.1) | ✅ | An application type in Settings ([chapter 3](guide/03-builder.md#application-types-and-subscriptions)): a **theme** app offers its theme (colours, navigation, Theme Roller styles) and template components, a **library** app its lists of values, authorization schemes, build options, template components and lists; other apps **subscribe** (the component is copied), see whether they are in sync, **refresh** one or all, and the master **publishes** to its subscribers (locked apps skipped). A **boilerplate** app is a *Start from* choice in Create application. Subscriptions are not exported; no subscriptions to pages or plug-ins other than template components |
48
+ | Property help in the Page Designer, component reference | 🟡 | Help text under most properties in the Page Designer (175 of 266 fields; the obvious ones such as *Title* and *Sequence* have none), and a guide section per region type, item type and button with the columns its SQL must return ([chapter 4](guide/04-pages-and-regions.md#region-types), [5](guide/05-items.md), [6](guide/06-processing.md#buttons)). (sprint 51) A region's *Attributes (JSON)* help shows its own type's keys with a link to its section of the guide. **Missing:** APEX's Help pane for the *selected* property |
47
49
  | Advisor | ✅ | Per app: every SQL fragment planned (EXPLAIN, as the app's role, rolled back) for syntax, unknown objects, types and grants; PL/pgSQL blocks compiled; references to missing pages, items, lists of values, schemes and layouts; PL/pgSQL functions with `plpgsql_check` when installed. Plus the security checklist |
48
50
  | Builder search, "where used" | ✅ | Search over every page and component (names, SQL, settings, help); "Used in" under items, pages, lists of values, schemes and report layouts. No search and replace |
49
51
  | AI assistant, pages from natural language, describe tables for LLMs (26.1) | ✅ | **App Builder AI** (administrators choose the builder's AI service): SQL Workshop → AI writes SQL from a question (shown in an editor, never run automatically), explains a query or an error, and describes tables and columns for LLMs (notes, optionally `COMMENT ON`, with AI drafts from names, types and keys only); **Create pages with AI** turns a description into proposed pages that the developer edits and confirms ([chapter 3](guide/03-builder.md)). The model never sees table rows |
@@ -57,7 +59,7 @@ not compared before, so the share available dropped without anything being remov
57
59
  | Interactive report | ✅ | Search, column filters, sort, rows per page, control break, aggregates (with subtotals), highlight, saved private and public reports, computed columns, group by, pivot, chart view, row selection into a page item, CSV, Excel (typed cells) and PDF download, print, reset, reflow on phones. a maximum row count (`max_rows`), natural-language control (*Ask in your own words*, 26.1) and row selection that stays across pages. Not possible: flashback queries (PostgreSQL has none; use an audit or temporal table) |
58
60
  | Interactive grid | ✅ | Inline edit, add and delete rows, lists of values, required columns, per-row errors, all-or-nothing save, signed row keys, search and paging; **aggregates** over the whole result (developer and user defined), **frozen columns**, column **reorder/resize/hide** (Actions → Columns, or drag and drop), per-user layouts and **saved grid reports** (private and public), **master-detail** (signed row selection, details refreshed in place), a **row actions menu** (edit, duplicate, delete, links) and **copy/paste** of cell ranges (tab-separated, spreadsheet compatible) ([chapter 4](guide/04-pages-and-regions.md)) |
59
61
  | Interactive grid views: single row view, chart view, group by | ❌ | The grid shows rows only; the interactive report has chart view and group by |
60
- | Form (automatic row processing) | 🟡 | Fetch, insert, update, delete, in a page or a modal dialog. Detects rows deleted meanwhile. **Missing:** lost update detection (APEX compares a checksum of the row as fetched before it saves; pgkiln saves over a row someone else changed meanwhile) |
62
+ | Form (automatic row processing) | ✅ | Fetch, insert, update, delete, in a page or a modal dialog. Detects rows deleted meanwhile. (sprint 50) **Lost update detection** (APEX: *Prevent Lost Updates* and *Lock Row*): the page carries a checksum of the row's form columns (`meta.row_version`, independent of time zone and date format, as the app's role); *Save* and *Delete* lock the row and refuse when it changed meanwhile; off per form with `{"lost_update": false}` ([chapter 4](guide/04-pages-and-regions.md#form)) |
61
63
  | Charts | ✅ | Bar, column, stacked, line, area, combination (columns + lines), scatter, bubble, donut, pie, gauge, funnel, radar, **Gantt** (start/end, progress, milestones, dependencies, a today line, a time axis from hours to years), **pyramid** (area-proportional segments, or two series back to back) and **polar** (polar area); multi-series, tooltips, data table, palette checked for colour-vision deficiency; drill-down links on chart marks (checksummed, only to pages the user may open). Drawn on the server as SVG without inline styles. **Missing:** other Oracle JET types (e.g. stock, box plot, range), editing a Gantt by drag and drop |
62
64
  | Cards and metric cards (26.1 metric card template) | ✅ | Cards from SQL, with a KPI "metric" style |
63
65
  | Calendar | ✅ | Month, week, day and list views (agenda list on phones); create on click (a checksummed link with the slot); drag and drop to move events through the developer's move SQL, run as the app's role (CSRF, a *who may drag* authorization, only events the user sees). Works without JavaScript; dragging adds on top ([chapter 4](guide/04-pages-and-regions.md#calendar)) |
@@ -73,8 +75,8 @@ not compared before, so the share available dropped without anything being remov
73
75
  | Pagination of large tables (row ranges, maximum row count) | ✅ | Reports and grids page in the database; `"pagination": "range"` shows APEX's "row ranges X to Y" without a total (it reads one row more for *Next*); `max_rows` is a maximum row count (the total is counted over at most max+1 rows: "of more than N"; downloads are capped too); page numbers and sizes are clamped on the server. Cards (500), charts (1000), dynamic content (1000) and lists of values (5000) have configurable row limits. Keyset ("seek") paging on an indexed sort (`"keyset"`), with signed positions |
74
76
  | Lazy loading of regions | ✅ | `"lazy": true` on report, chart, cards, dynamic, tree and template component regions: a placeholder, fetched after the page shows (page, condition and authorization re-checked); without JavaScript a link shows the region ([chapter 4](guide/04-pages-and-regions.md#large-tables)) |
75
77
  | Region caching (per user, per session, for a duration) | ✅ | `"cache": {"scope": "user" \| "session" \| "all", "seconds": N}` keeps rendered regions in server memory, keyed by app, region, roles, language, the query string and the item values the region uses; a page submit empties it. CSRF tokens and per-user links are never shared. Per server process |
76
- | Search configurations and the search region (22.2) | ❌ | One search box over several sources (tables, lists, REST data sources) with a result template per source. Faceted search and smart filters search one source |
77
- | URL region | ❌ | Another site's page in the region. Would need `frame-src` for chosen hosts in the CSP |
78
+ | Search configurations and the search region (22.2) | ✅ | (sprint 50) Shared Components → **Search configurations**: a table, a query (binds allowed) or a list, the searchable columns, and each result's title, subtitle, description, badge, icon and link. A **search** region searches the ones it names with one field (or a page item): every word in one of the columns, as the app's role with the text as a parameter; results grouped per configuration with the words marked; searches as you type, works without JavaScript; exported; checked by the Advisor ([chapter 4](guide/04-pages-and-regions.md#search-search-region)). No Oracle Text, no REST data sources or APEX-application search as sources, no custom result templates |
79
+ | URL region | ✅ | (sprint 50) A **url** region frames another site's page (or one of this server) in a sandboxed iframe: the origin is written out (an item can never choose the host), `&ITEM.` values after it are URL-encoded, and the page's CSP gets `frame-src` for exactly the origins of its visible URL regions; height, sandbox flags and full screen in the attributes; an *Open in a new tab* link ([chapter 4](guide/04-pages-and-regions.md#url-url-region)) |
78
80
  | Template components and template directives | ✅ | Shared Components → Template components: `#PLACEHOLDERS#` (always escaped), `{if}`, `{case}` and `{loop}` directives, custom attributes, a wrapper; as a region type and as report column templates, with a preview. Templates are checked against an allow-list (no scripts, styles, event handlers or `javascript:` links) ([chapter 4](guide/04-pages-and-regions.md#template-components)) |
79
81
 
80
82
  ## Items
@@ -93,7 +95,7 @@ not compared before, so the share available dropped without anything being remov
93
95
  | Rich text / markdown editor | ✅ | `richtext` (HTML rebuilt from an allow-list on the server when saved and shown, pasted HTML cleaned in the browser) and `markdown` (rendered on the server, HTML typed in it shown as text); a toolbar with JavaScript, a plain text field without ([chapter 5](guide/05-items.md)) |
94
96
  | Star rating, QR code, combobox (tags), date range | ✅ | `rating` (radio buttons drawn as stars), `qrcode` (SVG drawn on the server, no dependency), `combobox` (free text with list-of-values suggestions, tags, colon-separated), `daterange` (`from:to`); all work without JavaScript and are checked on the server |
95
97
  | Password reveal toggle (24.2) | ✅ | `{"reveal": true}` on password items; the value is never sent back to the page |
96
- | Display image, geocoded address | ❌ | No item that shows an image from a column or URL (a display item with HTML, or a file item's preview, comes close); no address item checked against a geocoder |
98
+ | Display image, geocoded address | ✅ | (sprint 53) `image` items show a picture from an https URL, a path or a BLOB from a query (served as the application's role, sandboxed); `address` items check the text against the installation's Nominatim-compatible geocoder (`GEOCODER_URL`) and put the chosen address's position into another item |
97
99
 
98
100
  ## Logic and processing
99
101
 
@@ -107,11 +109,11 @@ not compared before, so the share available dropped without anything being remov
107
109
  | Page processes | ✅ | SQL / PL/pgSQL, form DML, grid DML, data loading (`data_load`), **invoke API** (a REST data source or URL, response values into items), **download** (a file from a query; several rows become one zip; on submit or on load), **execution chains** (child processes with their own conditions, nested, optionally run in the background with a status view), **workflow** (start, terminate, retry), **Generate text with AI** (text or structured output into items) |
108
110
  | Branches | ✅ | Before header and after processing, to a page (with items) or a URL inside the app, *When button pressed*, server-side conditions (SQL, exists, item null/equals, request); the button's target page stays the fallback ([chapter 6](guide/06-processing.md#branches)); a PL/pgSQL function returning a path in the app, and a page of another application (with signed items) |
109
111
  | Dynamic actions | ✅ | Show, hide, enable, disable, set value (SQL), execute SQL, refresh region or item, alert, submit, set focus, add/remove class, show success/error message and clear errors (26.1); the **Dialog Closed** event (per dialog page, with the dialog's message). **Execute JavaScript**: calls a function a static application file registered with `pgkiln.actions.register` (no inline code: the CSP stays strict) ([chapter 7](guide/07-dynamic-actions.md#execute-javascript)); dynamic action plug-ins |
110
- | Dynamic action events | 🟡 | Change, click, page load and Dialog Closed. **Missing:** After Refresh, Selection Change (grid, report, cards), Get/Lose Focus, Key Release, Before Page Submit, custom events |
111
- | Dynamic action actions: confirm, close/cancel dialog, clear, open/close region, download, print, current position, share | ❌ | Buttons have a `confirm` question, dialog pages close through a branch, and *Execute JavaScript* can do the rest with an app's own code; none are built-in actions yet |
112
- | Ajax callbacks (On Demand processes, `apex.server.process`) | ❌ | Application and page processes run after sign-in, before a page, on load and on submit only. JavaScript can't call a named process and get JSON back; plug-ins and *Execute SQL* / *Set Value* actions cover some cases |
113
- | Error handling function | ❌ | APEX lets an app rewrite every error message in one PL/SQL function. pgkiln shows its own message with a reference number; `RAISE … USING COLUMN` targets a field |
114
- | User preferences, application settings (`APEX_UTIL.SET_PREFERENCE`, `APEX_APP_SETTING`) | ❌ | Item values kept per user across sessions, and named settings an administrator changes after deployment. Application items last one session; use a table |
112
+ | Dynamic action events | ✅ | Change, click, page load, Dialog Closed and (sprint 52) Get/Lose Focus, Key Release, After Refresh (a refreshed, lazy or master-detail region), Selection Change (report row selection, a grid's master row), Before Page Submit and custom events (`pgkiln.trigger(name, value)`); the actions of one event run in sequence order ([chapter 7](guide/07-dynamic-actions.md#events)) |
113
+ | Dynamic action actions: confirm, close/cancel dialog, clear, open/close region, download, print, current position, share | ✅ | (sprint 52) Confirm (No stops the actions after it, and a submit), Close and Cancel Dialog, Clear, Open/Close Region, Download (a download process of the page), Print, Get Current Position, Share (the share sheet, or the link copied) ([chapter 7](guide/07-dynamic-actions.md#actions)) |
114
+ | Ajax callbacks (On Demand processes, `apex.server.process`) | ✅ | (sprint 52) Page and application processes with point *ajax*, called with `pgkiln.server.process(name, {items, x01 … x10})`: SQL as the app's role with its authorization and condition, JSON rows back, items it sets set on the page ([chapter 7](guide/07-dynamic-actions.md#ajax-callbacks)) |
115
+ | Error handling function | ✅ | (sprint 52) `schema.function(jsonb) returns jsonb` (Settings → Errors and sessions): every message users see (raised, constraint, unexpected with its reference) can be rewritten, as the app's role with a time limit ([chapter 6](guide/06-processing.md#error-handling)) |
116
+ | User preferences, application settings (`APEX_UTIL.SET_PREFERENCE`, `APEX_APP_SETTING`) | ✅ | (sprint 53) `meta.get/set/remove_preference`, and items with `{"persist": "user"}` keep their value per user across sessions; application settings with valid values and *required*, `meta.get/set_app_setting`, exported with the application and kept on upgrade |
115
117
  | APEX PL/SQL APIs | ✅ | `meta.app_user()`, `meta.has_role()`, `meta.v()`, `meta.page_url()`, `meta.message()`, `meta.html_escape()`, password functions, `meta.debug()`; **`meta.web_request()` / `meta.web_request_source()` + `meta.web_response()`** (APEX_WEB_SERVICE: queued and made by the server, right after the page process that queued it or by the scheduler after commit, through the allow-list/SSRF checks and the app's web credentials; responses kept 24 h) and **`meta.parse_data()` / `meta.parse_data_columns()`** (APEX_DATA_PARSER for CSV/TSV and JSON in SQL, same names and types as the data loader) ([chapter 9](guide/09-reference.md)). (070) **XML and Excel** in `meta.parse_data` (as the data loader reads them; Excel files that pgkiln received: uploads and web responses), **APEX_ZIP** (`meta.zip_add`/`zip_finish`/`zip_agg` build zips in SQL, `meta.zip_entries`/`zip_entry` read them), **BOOLEAN** state (`meta.v_boolean`), and a mapping from APEX_JSON to PostgreSQL's JSON functions ([chapter 9](guide/09-reference.md#zip-files-in-sql)). A synchronous HTTP call inside one statement needs the `http` extension ([chapter 15](guide/15-extensions.md)); `meta.web_request` is queued by design |
116
118
  | Declarative menu buttons, button badges (26.1) | ✅ | Menu buttons with links and submit requests (a hidden button can't be reached through a menu), works without JavaScript; badges as text with `&ITEM.` or from SQL ([chapter 6](guide/06-processing.md#menu-buttons-and-badges)) |
117
119
  | Plug-ins | ✅ | **Region, item, dynamic action and process plug-ins** with their own code ([chapter 4](guide/04-pages-and-regions.md#plug-ins-with-their-own-code)): one `pgkiln-plugin/2` file with custom attributes, JavaScript and CSS (static application files, registered with `pgkiln.plugins.register`; the CSP stays strict), a template component for regions, a PL/pgSQL function for processes and install SQL that a developer reviews and runs; Shared Components → Plug-ins, `pgkiln plugin build|install`, four examples. Template component plug-ins (`pgkiln-plugin/1`) as before. Authentication and authorization plug-ins: custom authentication and SQL authorization schemes cover them |
@@ -141,7 +143,7 @@ not compared before, so the share available dropped without anything being remov
141
143
  | LDAP and SAML authentication | ✅ | LDAP / Active Directory (search + bind, StartTLS/LDAPS, groups → roles) and SAML 2.0 (signed assertions, SP metadata), next to local passwords and OpenID Connect |
142
144
  | Database accounts, HTTP-header authentication | ✅ | HTTP header variable (`header`): the user from a header set by a reverse proxy or SSO gateway, trusted only from proxy addresses in `PGKILN_AUTH_HEADER_PROXIES`, session bound to the header value, optional automatic accounts, sign-out URL; database accounts (`database`): a PostgreSQL login role and its password, checked by PostgreSQL through a short-lived connection, only listed roles or members of a role ([chapter 8](guide/08-security.md)) |
143
145
  | Custom authentication | ✅ | A PL/pgSQL function or body checks the user name and password as the app's database role, plus post-authentication code; throttling and the activity log as for other types ([chapter 8](guide/08-security.md)) |
144
- | Session timeout warning | ❌ | APEX warns before an idle session ends and offers to extend it; pgkiln sends the user to sign in after the idle time (forms sent offline by a PWA are kept) |
146
+ | Session timeout warning | ✅ | (sprint 52) A dialog before the idle time or the maximum length ends the session (default 2 minutes, per application), with *Stay signed in*; after the end, sign in and come back to the page ([chapter 8](guide/08-security.md#session-timeout-warning)) |
145
147
  | Persistent authentication ("remember me") | ✅ | Per app, 1–365 days; rotating one-time tokens, revoked on sign-out, new password, deactivation or removed access; "Sign out on all devices" |
146
148
 
147
149
  ## User interface
@@ -150,7 +152,7 @@ not compared before, so the share available dropped without anything being remov
150
152
  |---|---|---|
151
153
  | Universal Theme look and layout | ✅ | Header, side/top navigation, breadcrumbs, 12-column grid, region templates |
152
154
  | Region templates (Carousel, Hero, Inline Dialog/Popup/Drawer, Wizard Container, Title Bar, Buttons Container, Login) | 🟡 | Standard, plain and collapsible; dialog and drawer **pages**. **Missing:** the other templates, among them inline dialogs and drawers (a region opened on the same page) and a wizard progress bar |
153
- | Warn on unsaved changes | 🟡 | The interactive grid asks before leaving with unsaved rows. **Missing:** the page attribute that does this for every form |
155
+ | Warn on unsaved changes | ✅ | (sprint 50) A page attribute: the browser asks before the user leaves the page (links, redirect buttons, other forms, closing a dialog, closing or reloading the tab) while an item differs from the value it was shown with, also after a submit that failed; submitting doesn't ask; items opt out with `{"warn_unsaved": false}`; `pgkiln.isChanged()` (APEX: `apex.page.isChanged()`); on for the form pages the wizards make. The interactive grid keeps its own check ([chapter 4](guide/04-pages-and-regions.md#warn-on-unsaved-changes)). No per-button "do not check" |
154
156
  | Responsive: phone, tablet, desktop | ✅ | Tested at 390, 768, 1024 and 1440px on every change (`npm run test:e2e`) |
155
157
  | Modal dialog pages | ✅ | Full screen on phones |
156
158
  | Dark mode and user-chosen theme style | ✅ | Automatic (follows the device), light or dark per app; users may switch, saved on the account; plus a choice of the app's style variants |
@@ -170,7 +172,7 @@ not compared before, so the share available dropped without anything being remov
170
172
  | Language from browser, preference or session | ✅ | Browser, user preference or primary; `?lang=`; right-to-left languages |
171
173
  | Date and timestamp format masks | ✅ | Per app or per language |
172
174
  | Built-in runtime messages in ~34 languages | 🟡 | Twenty-two: English, Dutch, German, French, Spanish, Italian, Portuguese, Polish, Swedish, Danish, Norwegian, Finnish, Czech, Turkish, Greek, Russian, Ukrainian, Japanese, Chinese (simplified), Korean, Arabic and Hebrew (right to left), each with its date formats and currency; other languages via text messages with the same names |
173
- | Dynamic translations (`APEX_LANG.LANG`: translated data values, e.g. list of values entries) | ❌ | Translations cover the app's own texts and text messages, not values from tables; use a translation table in the query |
175
+ | Dynamic translations (`APEX_LANG.LANG`: translated data values, e.g. list of values entries) | ✅ | (sprint 53) Shared Components → Dynamic translations; `meta.lang(text)` in a query returns the value in the session's language (base language fallback); exported with the application |
174
176
  | Number format masks, automatic time zone | ✅ | Oracle-style number masks (`999G999G990D00`, `FML…`, `0000`, `%`, `S`/`MI`/`PR`, `EEEE`, `X`, `RN`) on report, grid and cards columns, charts and number/display items, in the language's separators with the app's currency; Automatic Time Zone (browser, My account, app or database), `timestamptz` shown in it ([chapter 14](guide/14-globalization.md)) |
175
177
 
176
178
  ## Data and integration
@@ -185,18 +187,19 @@ not compared before, so the share available dropped without anything being remov
185
187
  | Large downloads without buffering (ORDS streams) | ✅ | CSV and Excel downloads stream from a database cursor (1,000 rows at a time, a streaming Excel writer) up to `DOWNLOAD_MAX_ROWS` (default 1,000,000), so memory stays flat. Report PDFs read their rows from a cursor in batches of 500 (`PDF_MAX_ROWS`, default 5,000, at most 100,000); REST collection handlers stream a chunked JSON array from a cursor |
186
188
  | REST data sources, web credentials (26.1: OAuth refresh tokens, password flow) | ✅ | Shared Components → REST data sources: JSON endpoints with path, query, header and body parameters, a row selector, typed columns and a response cache feed reports, cards, charts, calendars, maps, trees, template components and shared lists of values as SQL over `rest`. **Write-back**: insert, update, delete and fetch operations (path and JSON body templates after the source's URL) used by forms and interactive grids. **Synchronisation** into a local table (merge on key columns with optional delete, replace, append) on demand, on a cron schedule or from SQL (`meta.request_rest_sync`), as the app's role, with a run log. Web credentials: basic, API-key header, bearer and OAuth2 client credentials, password and refresh-token grants (refresh tokens stored encrypted and rotated), secrets encrypted and write-only. Outgoing calls only to an allow-list of hosts, with SSRF checks ([chapter 19](guide/19-rest-data-sources.md)). **Missing:** XML/SOAP, the OAuth2 authorization code flow (consent in the browser) |
187
189
  | Printing, document generator (PDF) | ✅ | **Document templates**: a query (with JSON columns for lines) fills an HTML template with Mustache-style tags, drawn as PDF with a report layout; buttons and links download them. Report PDF with **report layouts** and a print stylesheet on every page. No Word/Excel templates or DOCX/XLSX output |
188
- | `APEX_DATA_EXPORT` (a query to CSV, XLSX, PDF, HTML or JSON from PL/SQL) | ❌ | The download process, report downloads and Unload Data do this from the UI; there is no SQL function that returns the file |
190
+ | `APEX_DATA_EXPORT` (a query to CSV, XLSX, PDF, HTML or JSON from PL/SQL) | ✅ | (sprint 53) `meta.data_export(query, format, options)` returns CSV, JSON, XML or HTML as `bytea` with the caller's privileges; the download process's `{"export": …}` sends a query's rows as CSV, JSON, XML, HTML, Excel or PDF |
189
191
  | SQL Workshop utilities: schema comparison, generate DDL | ❌ | The object browser shows definitions; use `pg_dump --schema-only` or `migra` |
190
192
  | Data Reporter: self-service reports for business users (26.1) | ✅ | A **Data Reporter** region ([chapter 4](guide/04-pages-and-regions.md#data_reporter-data-reporter)): the developer offers tables and views with chosen columns, labels and format masks; signed-in users pick columns, filter, group with totals (count, sum, average, minimum, maximum), sort and chart, and save reports privately or shared with the app's users. Runs as the app's role (grants and RLS apply); works without JavaScript and fits phones. One source per report (offer a view to combine tables); no downloads from a reporter yet |
191
193
  | JSON sources, duality views (24.2) | ➖ | PostgreSQL `jsonb` works in any SQL region, form or grid source |
192
194
  | Remote servers / database links | ➖ | `postgres_fdw` or `dblink` |
195
+ | E-mail: `APEX_MAIL`, the Send E-Mail process, e-mail templates | ✅ | (sprint 50) `meta.send_mail`, `meta.send_mail_template`, `meta.add_mail_attachment` and `meta.mail_status`, queued in the caller's transaction and sent by the server after the commit with retries; the **send_email** process; Shared Components → **E-mail templates** (`#NAME#` escaped in HTML, `#NAME!RAW#`; exported). Further than APEX (SMTP with a password only, through `UTL_SMTP`): **mail services** for SMTP with a password or **OAuth2** (XOAUTH2, e.g. Exchange Online after the end of basic authentication), **Microsoft 365 through Graph**, **Amazon SES**, **Resend, Postmark, SendGrid and Mailgun**, or log only; encrypted write-only secrets, allowed senders, a service, From address and daily limit per application, a mail log with retry and cancel ([chapter 6](guide/06-processing.md#sending-e-mail)). No bounce or delivery webhooks, no mail in workflows other than from SQL steps |
193
196
 
194
197
  ## Workflow, automation and AI
195
198
 
196
199
  | APEX | pgkiln | Notes |
197
200
  |---|---|---|
198
- | Approvals and task list | ✅ | Task definitions (approval / action, owner roles and users, business administrators, priority, due date, details page), `meta.create_task` from application SQL, a task list region (claim, approve/reject/complete with comment, release, delegate, cancel, history), completion SQL in the same transaction. **Missing:** e-mail notifications (pgkiln sends no mail), vacation rules, expiry/escalation policies |
199
- | Workflow (26.1: parallel flows, multi-tenancy) | ✅ | Workflow definitions of task, SQL, switch, wait, **invoke API** (a REST data source or URL through the invoke-API code, response values and the HTTP status into variables, retryable faults, no transaction open during the call) and end steps with variables, started from application SQL, run by the server (NOTIFY + polling) as the app's role; console region (terminate, retry a faulted step); diagram in the builder. **Parallel branches** (split, then a join that waits for all or for the first branch) and **versions** (development, active, inactive; running instances keep theirs) ([chapter 6](guide/06-processing.md#workflows)). (0.31) **Tenants**: `meta.set_tenant()` (APEX: `APEX_SESSION.SET_TENANT_ID`); workflows, their tasks, background chains, the task list, the console and every action follow the session's tenant ([chapter 6](guide/06-processing.md#tenants)). No e-mail activity, by design (pgkiln sends no mail; queue mail in a table) |
201
+ | Approvals and task list | ✅ | Task definitions (approval / action, owner roles and users, business administrators, priority, due date, details page), `meta.create_task` from application SQL, a task list region (claim, approve/reject/complete with comment, release, delegate, cancel, history), completion SQL in the same transaction. **Missing:** built-in e-mail notifications (send them with `meta.send_mail` from the completion SQL or an automation), vacation rules, expiry/escalation policies |
202
+ | Workflow (26.1: parallel flows, multi-tenancy) | ✅ | Workflow definitions of task, SQL, switch, wait, **invoke API** (a REST data source or URL through the invoke-API code, response values and the HTTP status into variables, retryable faults, no transaction open during the call) and end steps with variables, started from application SQL, run by the server (NOTIFY + polling) as the app's role; console region (terminate, retry a faulted step); diagram in the builder. **Parallel branches** (split, then a join that waits for all or for the first branch) and **versions** (development, active, inactive; running instances keep theirs) ([chapter 6](guide/06-processing.md#workflows)). (0.31) **Tenants**: `meta.set_tenant()` (APEX: `APEX_SESSION.SET_TENANT_ID`); workflows, their tasks, background chains, the task list, the console and every action follow the session's tenant ([chapter 6](guide/06-processing.md#tenants)). No *Send E-Mail* activity: send mail with `meta.send_mail` from an SQL step |
200
203
  | Automations (scheduled) | ✅ | Shared Components → Automations: cron schedules with time zones, once or per row of a query, **several ordered actions** with their own conditions, **error handling** (stop, skip the row and continue, or disable; row errors in the run history), roles, run history and Run now, **on-demand runs from SQL** with `meta.run_automation()` (like `APEX_AUTOMATION.EXECUTE`, synchronous in the caller's transaction), safe with several servers ([chapter 6](guide/06-processing.md#automations)) |
201
204
  | AI assistant, natural-language reports (NL2IR), AI agents and tools (26.1) | ✅ | Region type **AI assistant**: a conversation per session, context queries (RAG over developer queries, run as the app's role, read-only), and **tools** the model may call: SQL with bound arguments checked against declared parameters (read-only unless marked as writing, row limit, timeout) and REST data sources, each optionally behind an authorization scheme. **Natural-language report filters**: an "Ask in your own words" box turns a question into the report's normal filters, search and sort, limited to its visible columns ([chapter 4](guide/04-pages-and-regions.md)). Agents are defined per region (not as shared components); answers are not streamed. `pgvector` covers semantic search on the data side |
202
205
  | *Generate Text with AI* process, structured outputs (26.1) | ✅ | **AI services** (Workspace utilities, administrators): Claude through `@anthropic-ai/sdk` or OpenAI through `openai`, encrypted write-only keys (or `ANTHROPIC_API_KEY` / `OPENAI_API_KEY`), per-app access with daily request and token limits, a usage log. Page process `ai_generate` (text into an item, or structured output into several items with a schema built from the items or your own) and a dynamic action that runs it without a page submit; `meta.ai_generate` / `ai_result` / `ai_available` from SQL ([chapter 6](guide/06-processing.md)). Prompts, item values included, go to the chosen provider |
@@ -208,18 +211,22 @@ not compared before, so the share available dropped without anything being remov
208
211
  |---|---|---|
209
212
  | Developer accounts | ✅ | |
210
213
  | 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 |
211
- | Debug messages | ✅ | Debug levels 1–9 per app; `meta.debug(level, text)` and `meta.debug_enabled(level)` from application SQL (APEX_DEBUG); timed entries per request (page steps, regions, processes, branches, errors, SQL notices); Activity → **Debug messages** viewer per page view with filters and the slowest step highlighted; retention 1–90 days; password item values are never recorded ([chapter 6](guide/06-processing.md)). **Missing:** switching debug on per user or session (see the developer toolbar below), debug entries for background jobs and REST requests |
212
- | Developer toolbar, session state viewer | ❌ | APEX shows developers a toolbar on every page of the running app (App Builder, edit this page, session state, debug on/off, Quick Edit). pgkiln has *Run* links from the builder only |
213
- | Feedback (users send feedback from a page, developers answer) | ❌ | Build it as a page with a table, or as an approval task |
214
- | Automatic application backups, page groups | ❌ | APEX keeps the last exports of every application and lets developers group pages. Export the app (or keep its files in git with `pgkiln export --format text`) |
214
+ | Debug messages | ✅ | Debug levels 1–9 per app; `meta.debug(level, text)` and `meta.debug_enabled(level)` from application SQL (APEX_DEBUG); timed entries per request (page steps, regions, processes, branches, errors, SQL notices); Activity → **Debug messages** viewer per page view with filters and the slowest step highlighted; retention 1–90 days; password item values are never recorded ([chapter 6](guide/06-processing.md)). (sprint 50) Debug for **one session** from the developer toolbar, the application staying out of debug. **Missing:** debug entries for background jobs and REST requests |
215
+ | Developer toolbar, session state viewer | ✅ | (sprint 50) Developers signed in to the builder see a toolbar on the pages of their applications in the same browser: App Builder, the application, **Edit page** (Page Designer), **Session** (the session state viewer: user, roles, session, language, time zone, debug level, this page's items, application items and other pages' items; passwords never shown; clear the page's items) and **Debug** for this session only. A separate random token (cookie path `/a`, HttpOnly) of a live builder session of a developer of the application's workspace ([chapter 3](guide/03-builder.md#developer-toolbar)). **Missing:** Quick Edit (pick a component on the page), Theme Roller from the page |
216
+ | Feedback (users send feedback from a page, developers answer) | ✅ | (sprint 51) With *Users can send feedback* on, the navigation bar's **Feedback** link opens a page for a comment, idea or problem about the page (optional rating), with the user's earlier feedback and the developers' answers; developers read, filter, set a status and answer under Application → Feedback ([chapter 3](guide/03-builder.md#feedback)). No screenshots, no e-mail to developers |
217
+ | Automatic application backups, page groups | 🟡 | (sprint 51) **Backups**: before every import that replaces an application (CLI, MCP, working copy merge, restore), daily when it changed, and by hand; the newest 25 (configurable) are kept; download and restore from the builder ([chapter 3](guide/03-builder.md#backups)). **Missing:** page groups |
218
+ | Application availability (Available, Developers only, Restricted access, Unavailable; build status *Run only*) | ✅ | (sprint 51) Available, available to developers only (a builder session in the same browser), restricted to named users, or unavailable with a message, for pages, file downloads, REST modules and PostgREST; build status **Run only** refuses builder changes as if the application were locked, while `pgkiln import --replace` still deploys. Installation settings: not exported, kept by an import ([chapter 3](guide/03-builder.md#availability-and-build-status)) |
215
219
  | Monitoring (top SQL) | ✅ | Activity per app; Top SQL per app's database role from `pg_stat_statements` (sortable, resettable) |
216
220
  | Workspaces (multi-tenant) | 🟡 | Workspaces group applications and developers: the builder shows and opens only the applications of a developer's workspaces (administrators: all), a current workspace with a switcher, new and imported applications go into it, administrators add workspaces, choose their developers and move applications ([chapter 3](guide/03-builder.md#workspaces)). **Missing:** isolation between tenants (the SQL Workshop and application code run with installation-wide rights; use separate installations), per-workspace user accounts, schemas and workspace administrators |
217
221
 
218
222
  ## Different on purpose
219
223
 
220
- - **No e-mail.** pgkiln doesn't queue or send mail, and has no "forgot password" link (APEX apps
221
- don't have one out of the box either). Mail is an operational subsystem (SMTP, retries,
222
- deliverability) that teams usually already have; connect to it from your own schema.
224
+ - **Mail services instead of the instance's SMTP server.** APEX sends mail through `UTL_SMTP` with
225
+ a user name and password only (no OAuth2), so Microsoft 365 after the end of basic authentication
226
+ needs a relay, and providers such as Amazon SES or Resend only work through their SMTP gateways.
227
+ pgkiln sends through SMTP with a password or OAuth2, Microsoft Graph, Amazon SES or a provider's
228
+ HTTP API, chosen per application (sprint 50; the earlier "no e-mail" decision was reversed). There is
229
+ still no built-in "forgot password" link (APEX apps don't have one out of the box either).
223
230
  - **PostgREST instead of ORDS**, and no web listener at all: the pgkiln server talks to
224
231
  PostgreSQL directly.
225
232
  - **Row level security instead of VPD**, and one set of policies for the UI and the API.
@@ -250,6 +257,9 @@ Small but real differences, for teams comparing the two:
250
257
  - The theme follows the device's light/dark setting automatically, and the choice is saved per user.
251
258
  - A built-in *My account* page (own password, theme, language).
252
259
  - One RLS policy set protects both the web UI and the REST API.
260
+ - An import can be checked before it commits (`pgkiln import --check`): SQL that names a missing
261
+ table or column refuses the deployment instead of failing at run time.
262
+ - E-mail through SMTP with OAuth2, Microsoft Graph, Amazon SES and HTTP APIs, not only SMTP with a password.
253
263
 
254
264
  ## Roadmap (proposed priority)
255
265
 
@@ -270,6 +280,16 @@ report filters, App Builder AI and blueprints.
270
280
  detection, Ajax callbacks and the missing dynamic action events and actions first, as developers coming
271
281
  from APEX use them every day; then warn on unsaved changes, the session timeout warning, the developer
272
282
  toolbar and the region templates; the rest after.
283
+ 4. ~~Lost update detection, warn on unsaved changes, the search and URL regions, the developer toolbar and
284
+ e-mail~~ (done in sprint 50).
285
+ 5. ~~Safer imports: a check before an import commits, backups, application availability~~ (done in sprint 51,
286
+ with feedback).
287
+ 6. ~~Page behaviour: Ajax callbacks, dynamic action actions and events, an error handling function, the
288
+ session timeout warning~~ (done in sprint 52).
289
+ 7. ~~Data and settings: user preferences and application settings, `APEX_DATA_EXPORT`, dynamic
290
+ translations, display image and geocoded address items~~ (done in sprint 53).
291
+ 8. The last two ❌ rows: interactive grid views (single row view, chart view, group by), then schema
292
+ comparison and DDL generation in SQL Workshop; then the 🟡 rows (region templates first).
273
293
 
274
294
  Sources: [APEX 26.1 new features](https://docs.oracle.com/en/database/oracle/apex/26.1/htmrn/new-features.html),
275
295
  [What's new in APEX 24.2](https://apex.oracle.com/en/platform/features/whats-new-242/),
@@ -171,6 +171,7 @@ which is read at startup; real environment variables take precedence.
171
171
  | `SCHEDULER_INTERVAL_S` | `30` | How often the automation scheduler looks for due runs |
172
172
  | `BACKGROUND_PROCESSES` | on | `off` stops this server from running [background execution chains](06-processing.md#execution-chains) (another server runs them) |
173
173
  | `PROCESS_JOB_INTERVAL_S` | `10` | How often a server looks for queued background chains (besides being woken by `NOTIFY`) |
174
+ | `GEOCODER_URL`, `GEOCODER_KEY` | *(none)* | A Nominatim-compatible search API for [geocoded address items](05-items.md#display-image-and-geocoded-address), e.g. your own Nominatim; `GEOCODER_KEY` is sent as `key` (LocationIQ). Without it address items are plain text items |
174
175
  | `PDF_FONT`, `PDF_FONT_BOLD` | *(none)* | TrueType fonts for report PDFs, for text beyond Western European (e.g. `DejaVuSans.ttf`) |
175
176
  | `ANTHROPIC_API_KEY` | *(none)* | Default API key of [AI services](03-builder.md#ai-services) with the provider Claude that have no key of their own |
176
177
  | `OPENAI_API_KEY` | *(none)* | Default API key of AI services with the provider OpenAI that have no key of their own |
@@ -226,8 +226,10 @@ keeps a blueprint in the list (`meta.blueprint`, with the application last creat
226
226
  ### Importing
227
227
 
228
228
  **Import** (a tile, or `/builder/import`): paste the JSON of an export and optionally give a new
229
- alias. A directory export (one file per component) is imported with `pgkiln import`
230
- ([chapter 18](18-cli.md)). Imported apps keep the database role
229
+ alias. **Check the application before importing** (ticked) runs the [Advisor](#advisor) on the
230
+ imported application before anything is saved: errors (a missing table, column or function, a wrong
231
+ type, a missing grant) refuse the import and are listed. A directory export (one file per component)
232
+ is imported with `pgkiln import` ([chapter 18](18-cli.md#checking-before-an-import)). Imported apps keep the database role
231
233
  of the export; check it under **Settings**, and create users under **Shared Components**. An
232
234
  application with [supporting objects](#supporting-objects) opens on their page after the import:
233
235
  they are **not** run until you choose to.
@@ -434,6 +436,89 @@ Page properties:
434
436
 
435
437
  Chapters 4–7 describe every component type and property.
436
438
 
439
+ ## Developer toolbar
440
+
441
+ While you are signed in to the builder, the pages of your applications show the **developer
442
+ toolbar** at the bottom left when you run them in the same browser (APEX: the Runtime Developer
443
+ Toolbar). It isn't shown to anyone else, nor inside dialogs, and it can be folded away. It has:
444
+
445
+ | Entry | Does |
446
+ |---|---|
447
+ | **App Builder** | Back to the builder |
448
+ | **Application *n*** | The application's page in the builder |
449
+ | **Edit page *n*** | This page in the Page Designer |
450
+ | **Session** | The **session state viewer**: the user, roles, session id, language, time zone and debug level; the values of this page's items, the application items and the items of other pages in the session. A password item's value is never shown. *Clear the items of page n* empties this page's items in the session (APEX: Clear Cache) |
451
+ | **Debug** | Records [debug messages](06-processing.md#debug-messages) for **this session only**, at the chosen level, while the application itself stays out of debug (*Application (n)* when the application has a level of its own). *View debug* opens the recorded requests |
452
+
453
+ How it knows you: signing in to the builder gives the browser a second, separate random token for
454
+ the applications' pages (the cookie `pgkiln_devbar`, path `/a`, HttpOnly). A page shows the toolbar
455
+ when that token belongs to a live builder session of a developer who may open the application (an
456
+ administrator, or a member of its workspace). The token does nothing else; signing out of the
457
+ builder ends it.
458
+
459
+ ## Backups
460
+
461
+ **Backups** (in an application's header; APEX: Application Backups) are exports of the application
462
+ that this installation keeps:
463
+
464
+ - one **before every import that replaces it** (`pgkiln import --replace`, the MCP server, a working
465
+ copy's merge, a restore), with who did it;
466
+ - one **a day** when the application changed since its newest backup (the scheduler);
467
+ - the ones made with **Back up now** (with a note).
468
+
469
+ The newest *Backups to keep* (default 25; 0: none at all) are kept. Each can be **downloaded** (the
470
+ JSON export, to import elsewhere or keep in git) and **restored**: a restore is an import over the
471
+ application, so the version it replaces becomes the newest backup and the restore can be undone the
472
+ same way. Backups belong to the installation: they are not exported, and an import over the
473
+ application keeps them. Restores are logged in the activity log (`backup_restored`).
474
+
475
+ ## Availability and build status
476
+
477
+ **Availability** (in an application's header; APEX: Application Availability and Build Status) says
478
+ who may use the running application:
479
+
480
+ | Status | Who |
481
+ |---|---|
482
+ | Available | Everyone who may sign in (the default) |
483
+ | Available to developers only | Developers signed in to the builder in the same browser (they see the [developer toolbar](#developer-toolbar)); others see the message |
484
+ | Restricted | The users named (case-insensitive) and developers; others sign in and are told the application is not available to their account |
485
+ | Unavailable | Nobody: every page, and the sign-in page, shows the message (HTTP 503) |
486
+
487
+ The **message** (for example *"We are upgrading; back at 14:00."*) replaces a standard text in the
488
+ user's language. Pages, file downloads, REST modules and the PostgREST API follow the status;
489
+ automations, workflows, background jobs and queued mail keep running.
490
+
491
+ **Build status** *Run only* makes the builder refuse every change to the application (pages, shared
492
+ components, settings, restores) as if it were locked, until it is set back to *Run and build* here.
493
+ `pgkiln import --replace` still deploys it, so production can be Run only while releases come from
494
+ git. Availability and build status belong to the installation: exports leave them out, a new import
495
+ is *Available* and *Run and build*, and an import over the application keeps them. Changes are
496
+ logged in the activity log (`availability`). A badge in the application's header shows a status
497
+ other than *Available* and *Run and build*.
498
+
499
+ A deployment with a maintenance window:
500
+
501
+ ```sh
502
+ # Availability: Unavailable, "Back at 14:00" (the builder, or SQL on meta.app)
503
+ psql -f migrations/042_orders.sql # the database changes
504
+ pgkiln import apps/sales --replace --check # the application, checked
505
+ # Availability: Available
506
+ ```
507
+
508
+ ## Feedback
509
+
510
+ Users tell the developers what they think, from the running application (APEX: Feedback). Switch it
511
+ on under Application → Activity → **Feedback** (*Users can send feedback*): the navigation bar gets a
512
+ **Feedback** link that opens a page about the page the user was on. They choose *Comment*, *Idea* or
513
+ *Problem*, an optional rating (1–5 stars) and write up to 4000 characters; below the form they see
514
+ their earlier feedback with its status and your answer. The page's own access rules apply, and a
515
+ session sends at most 10 a hour.
516
+
517
+ On the builder's **Feedback** page you read it (newest first, filtered by status and kind; with the
518
+ user, page, rating and browser), set its status (*Open*, *In progress*, *Done*, *Declined*) and write
519
+ an answer the user sees. Answering is allowed while the application is locked or Run only. The
520
+ setting travels with the export; the feedback itself belongs to the installation.
521
+
437
522
  ## Working copies
438
523
 
439
524
  APEX's working copies: a second application to change in isolation, then merge back. On an
@@ -498,6 +583,8 @@ Components used by the whole application:
498
583
  | **Data load definitions** | A target table, file format (CSV, Excel, JSON, XML with its row element) and column mapping with transformations, for SQL Workshop → Load Data and the `data_load` process ([chapter 16](16-files.md#data-load-definitions)) |
499
584
  | **Lists** | Named sets of links (static entries with nesting, badges, conditions and authorization, or a query) for list regions, the navigation menu and the navigation bar ([chapter 4](04-pages-and-regions.md#list-lists)) |
500
585
  | **Supporting objects** | Install, upgrade and deinstall scripts that travel with the export ([below](#supporting-objects)) |
586
+ | **E-mail templates** | Subject, HTML and plain text with `#PLACEHOLDERS#` for `meta.send_mail_template` and the Send e-mail process ([chapter 6](06-processing.md#e-mail-templates)) |
587
+ | **Search configurations** | What a search region searches: a table, a query or a list, the columns searched, and the title, subtitle, description, badge, icon and link of each result ([chapter 4](04-pages-and-regions.md#search-search-region)) |
501
588
 
502
589
  ### Application types and subscriptions
503
590
 
@@ -682,6 +769,35 @@ texts needs `pg_read_all_stats` for the owner role, and resetting needs execute
682
769
  tokens against their daily limits, and the last 100 AI requests (time, page, user, service, model,
683
770
  source, tokens, duration, status). Prompts and answers are not logged.
684
771
 
772
+ ## Mail services
773
+
774
+ Workspace utilities → **Mail services** (administrators): how the applications of this
775
+ installation send [e-mail](06-processing.md#sending-e-mail). **Add service** first asks for the
776
+ provider (SMTP with a password or OAuth2, Microsoft 365 through Graph, Amazon SES, Resend, Postmark,
777
+ SendGrid, Mailgun, or *log only*), then shows that provider's settings only; on a service's page,
778
+ *Provider → Change* switches it. A service has the provider's settings, a secret (password, client secret, API key or secret access
779
+ key: stored encrypted with `PGKILN_SECRET_KEY`, never shown again, never exported), the **allowed
780
+ senders** (addresses, or `@domain`) and a default From address. On a service's page:
781
+
782
+ - **Applications**: which applications send through it (one service per application), each with
783
+ its From address (one of the allowed senders) and an optional limit per day;
784
+ - **Check before saving** (at the end of the form, also while adding a service): *Test connection*
785
+ checks the settings as filled in without sending anything (SMTP: connect, TLS and sign in;
786
+ Microsoft 365: an Entra token; Amazon SES: the account, with its sending quota and whether it is
787
+ still in the sandbox; Resend, Postmark, SendGrid, Mailgun: a read-only call with the key, which also
788
+ shows a key that may not send). *Send test mail* sends one message to the address you give, from an
789
+ allowed sender. An empty secret field uses the stored secret; nothing is saved;
790
+ - **Recent mail** of its applications.
791
+
792
+ Applications → Activity → **Mail** (developers) shows an application's service, today's count
793
+ against its limit and the mail of the last 30 days with its status and the provider's answer;
794
+ **Send again** queues a failed or cancelled mail again, **Cancel** stops a queued one.
795
+
796
+ **Microsoft 365.** Register an application in Microsoft Entra with a client secret. For the Graph
797
+ provider grant it the application permission *Mail.Send*; for SMTP with OAuth2 the permission
798
+ *SMTP.SendAsApp* and register its service principal in Exchange Online. In both cases limit it to the
799
+ sending mailboxes (an application access policy or RBAC for Applications).
800
+
685
801
  ## AI services
686
802
 
687
803
  Workspace utilities → **AI services** (administrators only; APEX: *Generative AI services*) lists the