pgkiln 0.47.0 → 0.48.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.
@@ -0,0 +1,19 @@
1
+ -- ---------------------------------------------------------------------
2
+ -- 109: pins on the SQL Workshop's Launchpad (sprint 96, Database Actions
3
+ -- DA-15: Pinned & Recently Visited). A developer pins a tool, a database
4
+ -- object or a saved worksheet; the home page lists them first. Per
5
+ -- developer and workspace, at most 24 (the builder refuses more). Only
6
+ -- builder paths (/builder/…) are kept. The builder reads and writes it as
7
+ -- the owner; installation data, not exported.
8
+ -- ---------------------------------------------------------------------
9
+ create table meta.builder_pin (
10
+ id bigint generated always as identity primary key,
11
+ username text not null,
12
+ workspace_id int not null default 1 references meta.workspace on delete cascade,
13
+ href text not null check (href ~ '^/builder/' and length(href) <= 400),
14
+ label text not null check (length(label) between 1 and 120),
15
+ icon text not null default 'bookmark' check (icon ~ '^[a-z0-9-]{1,40}$'),
16
+ at timestamptz not null default now(),
17
+ unique (username, workspace_id, href)
18
+ );
19
+ comment on table meta.builder_pin is 'The SQL Workshop Launchpad''s pins per developer and workspace (109); installation data, not exported';
@@ -0,0 +1,23 @@
1
+ -- ---------------------------------------------------------------------
2
+ -- 110: SQL Workshop charts (sprint 97, Database Actions DA-6: Charts).
3
+ -- A chart is a SELECT with how to draw it: the chart type, the label
4
+ -- column and the value columns. The worksheet's Chart tab saves one; SQL
5
+ -- Workshop → Charts lists them and shows the ones on the dashboard. Shared
6
+ -- by the workspace's developers, like SQL Scripts. The builder runs the
7
+ -- SELECT read-only with the workshop's connection when it draws a chart.
8
+ -- Installation data, not exported.
9
+ -- ---------------------------------------------------------------------
10
+ create table meta.sql_chart (
11
+ id int generated always as identity primary key,
12
+ workspace_id int not null default 1 references meta.workspace on delete cascade,
13
+ name text not null check (length(name) between 1 and 120),
14
+ sql text not null check (length(sql) between 1 and 20000),
15
+ kind text not null default 'bar' check (kind in ('bar', 'column', 'line', 'area', 'donut', 'pie', 'scatter', 'stacked')),
16
+ label_col text not null default '',
17
+ value_cols text[] not null default '{}',
18
+ on_dashboard boolean not null default true,
19
+ created_by text,
20
+ updated_at timestamptz not null default now(),
21
+ unique (workspace_id, name)
22
+ );
23
+ comment on table meta.sql_chart is 'SQL Workshop charts: a SELECT drawn as a chart (110); installation data, not exported';
@@ -0,0 +1,24 @@
1
+ -- ---------------------------------------------------------------------
2
+ -- 111: the SQL Workshop's Data Modeler (sprint 98, Database Actions
3
+ -- DA-10: relational diagrams). A diagram is a named picture of some
4
+ -- tables and views of one schema: which objects it shows and where each
5
+ -- box stands. objects is a jsonb array of {"name", "x", "y"} (the
6
+ -- object's name in the schema, the box's position). The objects are only
7
+ -- names: the columns, keys and foreign keys are read from the catalog
8
+ -- whenever the diagram is shown, so a diagram never goes stale. Per
9
+ -- workspace, shared by its developers. The builder reads and writes it
10
+ -- as the owner; installation data, not exported.
11
+ -- ---------------------------------------------------------------------
12
+ create table meta.sql_diagram (
13
+ id bigint generated always as identity primary key,
14
+ workspace_id int not null default 1 references meta.workspace on delete cascade,
15
+ name text not null check (length(name) between 1 and 120),
16
+ schema_name text not null check (length(schema_name) between 1 and 63),
17
+ objects jsonb not null default '[]' check (jsonb_typeof(objects) = 'array' and jsonb_array_length(objects) <= 500),
18
+ created_by text not null,
19
+ created_at timestamptz not null default now(),
20
+ updated_by text,
21
+ updated_at timestamptz not null default now(),
22
+ unique (workspace_id, name)
23
+ );
24
+ comment on table meta.sql_diagram is 'The SQL Workshop Data Modeler''s diagrams per workspace (111); installation data, not exported';
@@ -0,0 +1,49 @@
1
+ -- ---------------------------------------------------------------------
2
+ -- 113: AutoREST (sprint 100, Database Actions DA-11 part 1; ORDS: REST ›
3
+ -- Enable on a table or view). SQL Workshop › RESTful Services publishes a
4
+ -- table or view through an application of the workspace:
5
+ --
6
+ -- /a/<alias>/autorest/<object>/ GET (paged, filters), POST
7
+ -- /a/<alias>/autorest/<object>/<key> GET, PUT, DELETE (tables with a primary key)
8
+ -- /a/<alias>/autorest/openapi.json the OpenAPI description of them all
9
+ --
10
+ -- The application decides how a request runs: its database role (never the
11
+ -- object's owner, a superuser or a role that bypasses row level security,
12
+ -- checked when the object is enabled and at every request), its tokens and
13
+ -- OAuth clients (App › REST API), its accounts' roles (meta.has_role) and
14
+ -- its availability. Without a bearer token an object answers 401 unless the
15
+ -- developer chose "public" for it explicitly.
16
+ --
17
+ -- The builder writes the rows as the owner; the runtime reads them.
18
+ -- Installation data like the application's OAuth clients: not exported (an
19
+ -- in-place import keeps them); the application's own REST modules are what
20
+ -- travels with an export.
21
+ -- ---------------------------------------------------------------------
22
+ create table meta.rest_object (
23
+ id int generated always as identity primary key,
24
+ app_id int not null references meta.app on delete cascade,
25
+ schema_name text not null check (length(schema_name) between 1 and 63),
26
+ object_name text not null check (length(object_name) between 1 and 63),
27
+ -- the URL segment: /a/<alias>/autorest/<alias>/
28
+ alias text not null check (alias ~ '^[a-z][a-z0-9_-]{0,62}$' and alias <> 'openapi.json'),
29
+ methods text[] not null default '{GET}' check (methods <@ '{GET,POST,PUT,DELETE}'::text[] and cardinality(methods) > 0),
30
+ -- token: a bearer token of the application (default); public: no token needed, meta.app_user() = nobody
31
+ auth text not null default 'token' check (auth in ('token', 'public')),
32
+ -- the caller needs one of these application roles (meta.has_role); empty: any caller the auth allows
33
+ roles text[] not null default '{}',
34
+ page_size int not null default 25 check (page_size between 1 and 500),
35
+ enabled boolean not null default true,
36
+ created_by text,
37
+ created_at timestamptz not null default now(),
38
+ updated_at timestamptz not null default now(),
39
+ unique (app_id, alias),
40
+ unique (app_id, schema_name, object_name)
41
+ );
42
+ revoke all on meta.rest_object from public;
43
+ grant select on meta.rest_object to pgkiln_runtime;
44
+ -- isolated workspaces (090): a workspace's logins see the rows of their own applications only
45
+ alter table meta.rest_object enable row level security;
46
+ create policy workspace on meta.rest_object
47
+ using ((select meta.isolation_off()) or app_id in (select meta.visible_apps()))
48
+ with check ((select meta.isolation_off()) or app_id in (select meta.visible_apps()));
49
+ comment on table meta.rest_object is 'AutoREST (113): tables and views published through an application at /a/<alias>/autorest/<alias>/; installation data, not exported';
@@ -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-16 (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-16 (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
 
@@ -348,15 +348,15 @@ AI and row level security badges.
348
348
  | Query Result grid (paging, download, sharing) | 500 rows (All rows: 10,000) with row numbers, numbers right-aligned, sort, a value dialog, copy, Download as CSV, JSON, XML, Excel or SQL inserts (sprint 92); no sharing links | ✅ |
349
349
  | SQL History, DBMS Output | SQL History per developer with status, rows, time, search and run again; Notices with their time (sprint 92) | ✅ |
350
350
  | Worksheets saved as files, tabs | Save, Save as, Rename, Download as SQL Scripts, a Files tab, worksheet tabs that survive a reload (sprint 93) | ✅ |
351
- | Create Chart from a query, Charts | Charts in applications only | ❌ |
351
+ | Create Chart from a query, Charts | The worksheet's Chart tab (Ctrl+F11) and SQL Workshop → Charts with a dashboard (sprint 97); no page made from a chart yet | ✅ |
352
352
  | Object context menu, table properties dialog, Quick DDL | An object's menu (sprint 94): Open in a panel, Quick DDL to the worksheet or a file, Load data, Add index / trigger / policy, Drop with its dependents; **Table Properties** (sprint 95): columns, keys, foreign keys, checks, indexes, comment, RLS, partitioning, DDL preview, Apply in one transaction, use as template | ✅ |
353
353
  | Format, Convert Case, Find and replace, bind variables | Format (Ctrl+F7), Convert case, find and replace, Go to line, comment lines, `:NAME` and `&NAME.` asked for before a run (sprint 93); no guided tour | ✅ |
354
- | Data Modeler (relational diagrams) | Query Builder joins only | ❌ |
355
- | REST (modules, AutoREST) | Consumes REST (catalogs, sources); the application REST API | 🟡 |
354
+ | Data Modeler (relational diagrams) | SQL Workshop → Data Modeler (sprint 98): diagrams per schema, boxes with columns and keys, foreign key lines with crow's feet, positions saved, zoom, fit, auto layout, mini-map, SVG / PNG export, DDL of the shown objects, a data dictionary | ✅ |
355
+ | REST (modules, AutoREST) | SQL Workshop → RESTful Services (sprint 100): a table or view published through an application with GET (paging, filters, search, order), item GET, POST, PUT, DELETE as the app role with its tokens and RLS, OpenAPI; custom modules, templates and handlers are application REST modules (Shared Components), not yet managed from the SQL Workshop | 🟡 |
356
356
  | Scheduling | pgkiln's own jobs and automations | ❌ |
357
- | Database Users | Application users and developers; roles in SQL | ❌ |
357
+ | Database Users | Administration → Database users (sprint 99): roles with sign-in, attributes, expiry, memberships and owned objects; create and edit with the SQL reviewed (password masked, a SCRAM verifier) and applied in one transaction; drop with reassign or drop owned; pgkiln's roles protected. PostgreSQL has no created date or quota | ✅ |
358
358
  | Real Time SQL Monitor | Database Monitor (sessions) and Top SQL per application role | 🟡 |
359
- | Launchpad, Search Database (Ctrl+K) | The SQL Workshop home | 🟡 |
359
+ | Launchpad, Search Database (Ctrl+K) | The SQL Workshop home as a Launchpad (sprint 96): pinned and recently visited, Development / Administration / Monitoring tabs; Search (Ctrl+K) for tools, applications, pages and database objects; no guided walk-through | ✅ |
360
360
  | Data Pump | Application backups and Unload Data | 🟡 |
361
361
  | Liquibase | Schema Comparison | 🟡 |
362
362
  | JavaScript (MLE) | ➖ Not planned: PostgreSQL has plv8 as an extension | ➖ |
@@ -183,7 +183,7 @@ Every builder page has the same frame, modelled on an IDE:
183
183
  pages of an application); at the bottom the **Administration** menu (Workspace utilities; for administrators of the
184
184
  current workspace *Manage service*: [workspace message and environment banner](#workspace-message-and-environment-banner),
185
185
  [workspace utilization](#workspace-utilization) and the workspace's page; Manage users and groups, Developers,
186
- Monitor activity, Change my password), Help, and your account menu (the circle with your initials) with the
186
+ Monitor activity, [Database users](#database-users) for administrators, Change my password), Help, and your account menu (the circle with your initials) with the
187
187
  **builder theme** (*Dark*, the default; *Light*; or *System*, which follows the operating system),
188
188
  Change password and Sign out. The theme is remembered on this device, also after signing out;
189
189
  it only changes the builder, not your applications.
@@ -1254,7 +1254,18 @@ session's **schema** (APEX: the default schema): it goes first in the search pat
1254
1254
  you sign out. Tasks link to Quick SQL, blueprints, table descriptions, sample data and Generate DDL.
1255
1255
 
1256
1256
  (sprint 75) The tools are tabs: Home, SQL Worksheet, Object Browser, SQL Scripts and Utilities; **More** opens the
1257
- others (Quick SQL, Query Builder, Load and Unload Data, Sample Data, DDL, Compare, AI), and the open one is a tab too.
1257
+ others (Quick SQL, Query Builder, Load and Unload Data, Sample Data, DDL, Compare, Data Modeler, AI), and the open one is a tab too.
1258
+
1259
+ (sprint 96; Database Actions: the Launchpad) The home page starts with **Pinned & recently visited**: the pages you
1260
+ pinned (a tool, a database object from the Object Browser, a saved worksheet from its file menu; at most 24, per
1261
+ workspace) and the SQL Workshop pages you opened last in this browser. Below, the tools are in three tabs,
1262
+ **Development**, **Administration** and **Monitoring**, each with a line about what it does and a pin; the **More**
1263
+ menu uses the same headings.
1264
+
1265
+ **Search** (**Ctrl/Cmd + K** on any builder page, or the field in the header) finds tools, applications, pages
1266
+ (by name or number) and database objects (tables, views, materialized views, functions and procedures) by name;
1267
+ the arrow keys and Enter open one. Applications and pages come from your workspace only; objects from the schemas
1268
+ the SQL Workshop's connection may use. Without JavaScript the header's field opens a page of results.
1258
1269
 
1259
1270
  - **SQL Worksheet** (`/builder/sql/worksheet`, sprint 91; Database Actions: SQL; was SQL Commands, whose address
1260
1271
  `/builder/sql/commands` opens the same page): one screen with a **navigator** on the left, the **editor** with a
@@ -1271,6 +1282,8 @@ others (Quick SQL, Query Builder, Load and Unload Data, Sample Data, DDL, Compar
1271
1282
  function and the trigger) and **Add policy** (row level security on, a policy to fill in); **Drop…** writes the
1272
1283
  DROP statement with a comment that lists what depends on the object (views, foreign keys…). Nothing runs: you
1273
1284
  review the statement and run it.
1285
+ (sprint 100) Tables and views also have **REST › Enable / Disable**: it opens the object's page in **RESTful
1286
+ Services** when it is published, or the Enable form for it (below).
1274
1287
  - (sprint 95) **Table Properties** (a table's **Edit…**, **Use as template**, the Object Browser's *Edit table* and
1275
1288
  its *Table (form)* tile): a form with **Columns** (name, type, primary key, not null, default, identity,
1276
1289
  comment; move them up or down for a new table, remove them), **Unique keys**, **Foreign keys** (the table it refers
@@ -1299,6 +1312,12 @@ others (Quick SQL, Query Builder, Load and Unload Data, Sample Data, DDL, Compar
1299
1312
  width, and the step's conditions (filter, index and join conditions, sort keys). Autotrace adds the actual time,
1300
1313
  rows, loops and buffers, the time spent in the step itself, marks the **slowest step**, and flags estimates that
1301
1314
  are 10 times too high or too low (run `ANALYZE` on the table). **Text plan** shows it like psql.
1315
+ - (sprint 97) **Chart** (**Ctrl + F11**, or *Chart* above the Query Result) draws the last query with pgkiln's
1316
+ own charts: the first text or date column gives the labels, the number columns the values; change the type (bar,
1317
+ column, stacked bar, line, area, donut, pie, scatter), the label column or the values and it draws again. Name it
1318
+ and **Save chart**: SQL Workshop → **Charts** lists the saved charts (shared by the workspace) and draws the ones
1319
+ on its dashboard; a chart's page changes its settings, opens its query in the worksheet or deletes it. A saved
1320
+ chart's SELECT runs read-only with a 10 second timeout and at most 500 rows.
1302
1321
  - **Notices** lists the `RAISE NOTICE`, `INFO` and `WARNING` messages of the last run with their time.
1303
1322
  **SQL History** (sprint 92) lists your last 200 statements in this workspace with how they ended, their rows and
1304
1323
  time; running the same statement again counts on its row (*3×*). Search it, show only the ones that failed or
@@ -1383,6 +1402,27 @@ others (Quick SQL, Query Builder, Load and Unload Data, Sample Data, DDL, Compar
1383
1402
  The state is in the URL (tables in the order chosen, joins, functions and the tables' places), so
1384
1403
  a query can be bookmarked; everything except dragging works without JavaScript. Only names from
1385
1404
  the catalog and the fixed functions are used, and condition values are string literals.
1405
+ - **Data Modeler** (SQL Workshop → More → Data Modeler, `/builder/sql/modeler`): named relational
1406
+ **diagrams** of a schema's tables and views, kept per workspace and shared by its developers. Create
1407
+ one with a name, a schema and, optionally, the objects (`orders, customers`, `ord*`, or `*` for all);
1408
+ **Add objects to diagram** searches the schema (part of a name, a pattern with `*`, or `*`) and adds
1409
+ the ticked ones. Each object is a box with its columns, their types, `P` (primary key), `F` (foreign
1410
+ key), `U` (unique) and `*` for not null; a foreign key between two shown tables is a line from the
1411
+ referencing table (a crow's foot: many) to the referenced one (a bar: one), dashed with a circle
1412
+ when the foreign key may be empty. A box's name opens **Table Properties** (a view: the Object
1413
+ Browser). The toolbar: **Save** (Ctrl+S), **Undo** / **Redo** (Ctrl+Z, Ctrl+Y), **Zoom out** / **Zoom
1414
+ in** (or Ctrl+wheel), **Fit**, **Auto layout** (referenced tables to the left of the tables that
1415
+ reference them; undoable), a **Mini-map** (click or drag in it to move around), **SVG** and **PNG**
1416
+ exports of the diagram as shown, **Print**, **Generate DDL** (the CREATE statements of the shown
1417
+ objects with their keys, indexes, triggers, row level security, policies, comments and grants: to
1418
+ download or open in the SQL Worksheet) and **Data dictionary** (each object's columns with type,
1419
+ nullability, default, keys and comments, its constraints and what references it; to print, save as
1420
+ PDF from the print dialog, or download as an HTML file). Drag a box to move it, or focus it and use
1421
+ the arrow keys (Shift for bigger steps). The diagram keeps only the objects' names and positions
1422
+ (`meta.sql_diagram`): columns and keys are read from the catalog each time, so it never goes stale;
1423
+ an object dropped from the schema is reported and left out on the next save. Without JavaScript the
1424
+ diagram shows at its saved positions, and adding, removing, auto layout, Export SVG, DDL and the
1425
+ dictionary all work. Diagrams are installation data, not exported with applications.
1386
1426
  - **Load Data**: load a CSV, TSV, Excel, JSON or XML file into a new table (with inferred column
1387
1427
  types) or an existing one (append, merge by primary key, or replace), with a per-row error
1388
1428
  report, or with a saved **data load definition**; a mapping can be saved as one
@@ -1416,6 +1456,15 @@ others (Quick SQL, Query Builder, Load and Unload Data, Sample Data, DDL, Compar
1416
1456
  has (commented out), columns whose identity or generation differs, and types, domains and
1417
1457
  sequences that differ. The same from the command line (`pgkiln ddl`, `pgkiln compare`,
1418
1458
  [chapter 18](18-cli.md)) and for AI agents (`generate_ddl`, `compare_schemas`).
1459
+ - **RESTful Services** (`/builder/sql/rest`, sprint 100; Database Actions: REST › AutoREST): publish a table or
1460
+ view as REST endpoints. Choose the object (of a schema the SQL Workshop may use), the **application** it is
1461
+ published through, a URL name, the **methods** (GET: rows and one row; POST; PUT; DELETE; single rows need a primary
1462
+ key), **who may call it** (a bearer token of the application, or explicitly *public*), optional application
1463
+ **roles** and the page size. The application decides the rest: the statements run as its database role (never the
1464
+ object's owner, a superuser or a role that bypasses row level security), with its tokens and OAuth clients and its
1465
+ accounts' roles. The object's page checks the role's grants per method, row level security and (for a view)
1466
+ `security_invoker`, lists the endpoints with their URLs, and shows cURL and `fetch` examples and the OpenAPI link.
1467
+ Details in [chapter 13](13-rest-api.md#autorest-tables-and-views-from-the-sql-workshop).
1419
1468
  - **Utilities** (`/builder/sql/utilities`; APEX: SQL Workshop → Utilities): tiles for Load and Unload Data, Sample
1420
1469
  Data, the Query Builder, DDL and Compare, and three pages of their own. Each runs in a read-only transaction with a
1421
1470
  15-second statement timeout, on the SQL Workshop's connection (an isolated workspace's developers see only the
@@ -1429,9 +1478,46 @@ others (Quick SQL, Query Builder, Load and Unload Data, Sample Data, DDL, Compar
1429
1478
  - **Database Monitor** (administrators only): the client sessions of this database from `pg_stat_activity`, active
1430
1479
  first, with their state, wait event, running time, the sessions that block them and the query (as far as the
1431
1480
  owner may read other roles' statistics). Read only: it cancels nothing.
1481
+ - **Database Users** (administrators only; Administration menu → *Database users*, `/builder/db-users`; sprint 99,
1482
+ Database Actions: Database Users): see [Database users](#database-users).
1432
1483
 
1433
1484
  Because the SQL Workshop runs as the owner, restrict who gets a developer account.
1434
1485
 
1486
+ ### Database users
1487
+
1488
+ (sprint 99; Database Actions: Database Users) **Administration → Database users** (administrators only; also on the
1489
+ SQL Workshop's Launchpad under *Administration*) lists the PostgreSQL roles of the server (`pg_roles`; the predefined
1490
+ `pg_` roles are left out): whether they can sign in, superuser / create DB / create role / bypass RLS / replication,
1491
+ the connection limit, **valid until** (with *in N days* or *expired*), the roles they are a member of and what they own
1492
+ (schemas, objects in this database, objects elsewhere). PostgreSQL doesn't record when a role was created.
1493
+ The tiles on top filter the list: roles that can sign in, **passwords that expire within 30 days**, roles with
1494
+ **BYPASSRLS**, roles **without sign-in that own objects**, and pgkiln's own roles; a search field filters by name.
1495
+
1496
+ **Create database user** (or a role's page) is a form: name, *Can sign in* (LOGIN), the password (*No password* /
1497
+ *Set a password*; for an existing role *Keep*, *Set a new password* or *Remove*), **valid until** (a date; empty: no
1498
+ expiry), the connection limit, the roles it is a **member of** (group roles and the predefined roles; not pgkiln's own,
1499
+ superusers, login roles or the roles that reach the server's files), its **default schema** (the search path in this
1500
+ database: `ALTER ROLE … IN DATABASE … SET search_path`), a comment, and per schema **Usage** and **Create**,
1501
+ **Future tables** (default privileges, *read* or *read and write*, on what pgkiln's owner connection creates there) and
1502
+ **Existing tables** (a one-off grant or revoke on the tables there now). pgkiln's own schemas aren't offered.
1503
+
1504
+ **Review SQL** shows the statements (only what differs from what the catalog says now), with the password as
1505
+ `'********'`; the password itself is typed on that page (twice) and **Apply** runs the statements in one
1506
+ transaction: all or none, and the error with the statement that failed. Apply runs only what the review showed:
1507
+ when the form or the role changed in between, the review comes again. The masked statements go to the activity log
1508
+ (event `db_role`).
1509
+
1510
+ **Drop role…** lists what the role owns and warns about objects in other databases; it reassigns them to another role
1511
+ (`REASSIGN OWNED`) or, with a tick, drops them (`DROP OWNED`), revokes its privileges in this database and drops the
1512
+ role, again after showing the SQL.
1513
+
1514
+ pgkiln's **own roles** are marked *pgkiln* and are read only here: the owner and runtime connections (`DATABASE_URL`,
1515
+ `RUNTIME_DATABASE_URL`), every `pgkiln…` role (`pgkiln_runtime`, `pgkiln_app_code`, `pgkiln_authenticator`,
1516
+ `pgkiln_anon`, isolated workspaces' logins) and the bootstrap superuser. Roles **in use** by an application (parsing
1517
+ schema, REST API role) or an isolated workspace can be changed but not dropped. New names can't start with `pg_` or
1518
+ `pgkiln`. The owner connection needs `CREATEROLE` (and, on PostgreSQL 16 and later, ADMIN on roles it didn't create)
1519
+ for these changes; PostgreSQL's own error says so otherwise.
1520
+
1435
1521
  ## Export and import
1436
1522
 
1437
1523
  **Export** downloads the application as JSON: pages, all components, shared components and
@@ -511,6 +511,24 @@ refused ([chapter 16](16-files.md#data-loading)). The SQL Workshop (the SQL Work
511
511
  Quick SQL, Load Data, Unload Data, Sample Data) runs as the owner instead, so every developer can change any table: keep
512
512
  developer accounts to people you trust with the database.
513
513
 
514
+ The REST endpoints pgkiln serves (an application's REST modules and the tables and views published with **SQL
515
+ Workshop → RESTful Services**, AutoREST) run as the app role too, never as the owner: these grants, column grants
516
+ and the row level security below decide what an API caller may read and change. AutoREST refuses a role that owns
517
+ the published object or bypasses row level security, and an object answers only to a bearer token of its application
518
+ unless the developer chose *public* for it ([chapter 13](13-rest-api.md#autorest-tables-and-views-from-the-sql-workshop)).
519
+
520
+ ### Database users and their passwords
521
+
522
+ (sprint 99) Administrators create and change PostgreSQL roles in the builder (**Administration → Database users**,
523
+ [chapter 3](03-builder.md#database-users)). Passwords never reach PostgreSQL or a page in plain text: pgkiln hashes
524
+ a new password itself into a **SCRAM-SHA-256 verifier** (random salt, 4096 iterations, SASLprep, like psql's
525
+ `\password`) and the statement carries only that verifier, as a literal built with pg's `escapeLiteral`. The review
526
+ and the activity log show `PASSWORD '********'`; the password is typed on the review page, posted once with Apply and
527
+ not stored, echoed or logged. A server with `log_statement = ddl` logs the verifier, not the password. Every name is
528
+ quoted with `escapeIdentifier`, every value is checked (dates, numbers, schema names, grantable roles) and quoted.
529
+ The page is for administrators only (others get 403), every change needs the CSRF token, and pgkiln's own roles can't
530
+ be changed, dropped or granted from it, so the page can't take pgkiln's own connections away.
531
+
514
532
  ## Session state protection
515
533
 
516
534
  - **URL items**: on pages with protection *Arguments must have checksum* (the default), item
@@ -69,6 +69,7 @@ src/
69
69
  sqlscript.ts SQL scripts: splitScript() (statements, line numbers and offsets, psql commands), runScript() (stop/continue, transaction, savepoints)
70
70
  sqlworksheet.ts (sprint 91) the worksheet's runs: pickStatements() (at the cursor, a selection, all), runStatements() (a log per
71
71
  statement, psql command tags, notices, error line and column), explainStatement() (EXPLAIN / rolled-back ANALYZE)
72
+ datamodel.ts (sprint 98) Data Modeler diagrams: readModel() (catalog), boxSize(), fkPath() (crow's feet), autoLayout(), diagramSvg()
72
73
  tabledef.ts (sprint 95) a table as a definition: readTable(), checkTable(), tableSql() (CREATE, or ALTER from the catalog's version)
73
74
  sqlformat.ts (sprint 93) formatSql(): the worksheet's Format (clauses per line, keyword case; strings and comments kept)
74
75
  sqlplan.ts (sprint 92) EXPLAIN (FORMAT JSON) as a tree: parsePlan() (self time, slowest step, misestimates), planText()
@@ -86,6 +87,9 @@ src/
86
87
  mvt.ts Mapbox Vector Tile encoding for map layers served as tiles
87
88
  yamltext.ts the text style of the directory export: a strict YAML subset, written and read
88
89
  webclient.ts outgoing HTTP to web services: allow-list, address checks at connect time (SSRF), redirects, limits
90
+ dbroles.ts (sprint 99, DA-13) Database Users' SQL: roleSql (CREATE/ALTER ROLE, memberships, search path, schema
91
+ and default privileges: only what differs from the catalog), dropSql, checkRole/checkPassword,
92
+ scramVerifier (SCRAM-SHA-256, SASLprep) and the password slot (maskSql for review and log, withVerifier to run)
89
93
  secrets.ts secrets at rest (web credentials): AES-256-GCM with PGKILN_SECRET_KEY
90
94
  websources.ts web credentials (OAuth2 client credentials/password/refresh token grants, token cache, stored refresh
91
95
  tokens) and REST data sources: requests, JSON paths, typed rows, response cache, write-back operations
@@ -149,6 +153,9 @@ src/
149
153
  spatial.ts spatial filtering on the server: map area and distance parsing, PostGIS detection and SQL (ST_Intersects, ST_DWithin), lat/lng fallback (bounding box, haversine)
150
154
  pwa.ts Progressive Web App: manifest, service worker route, icons (PNG encoder), offline page
151
155
  rest.ts REST modules: handler checks, matching, bearer tokens, execution (collections stream from a cursor), OpenAPI
156
+ autorest.ts (sprint 100, migration 113) AutoREST: /a/:alias/autorest/<object>/ for the tables and views SQL Workshop →
157
+ RESTful Services published (meta.rest_object): caller() of rest.ts, SET ROLE to the app role, owner/BYPASSRLS
158
+ check, columns from the catalog (column grants), filters/q/order/paging, POST/PUT/DELETE by primary key, OpenAPI
152
159
  rest-sources.ts REST data sources in apps: regions and LOVs as SQL over "rest", the invoke_api process (items; the call is websources.ts invoke()),
153
160
  write-back of forms (fetch, form_dml) and grids (grid_dml) through the source's operations
154
161
  tree.ts tree region
@@ -221,6 +228,11 @@ src/
221
228
  errors.ts (sprint 86) the builder's HTML 404 and 500 pages for browsers (wantsHtml, a not-found handler and an onSend hook)
222
229
  arrange.ts page designer layout changes: move, column span, create from the gallery, undo / redo
223
230
  sql.ts SQL Workshop: the home and the session's schema
231
+ launchpad.ts (sprint 96) the SQL Workshop home's Launchpad (pins in meta.builder_pin, 109; tool groups), POST /builder/pins,
232
+ GET /builder/palette (the builder's search: JSON for Ctrl+K, a results page without JavaScript)
233
+ sql-charts.ts (sprint 97) charts of a query: chartSpec(), drawChart() (runtime/charts.ts, a PageCss in a nonce'd <style>), the
234
+ worksheet's Chart tab, SQL Workshop → Charts (meta.sql_chart, 110; read-only runs)
235
+ sql-tools.ts (sprint 96) SQL_TOOLS: every SQL Workshop tool with its group, tab and description (home, More menu, search)
224
236
  worksheet.ts (sprint 91) the SQL Worksheet (Database Actions' SQL; /sql/commands too): navigator (pickSchema, objects with
225
237
  columns, objectStatements), toolbar, output tabs, history (meta.sql_history, 108), plan trees, Run as an app's role, (sprint 93) Save / Rename / Download as SQL Scripts, bind and substitution values, POST /sql/worksheet/format; GET /sql/worksheet/navigator
226
238
  object-browser.ts (sprint 75) the Object Browser: objects by type, system objects hidden, a table in tabs, column actions as SQL to review
@@ -228,10 +240,15 @@ src/
228
240
  (one transaction) / Open in the worksheet
229
241
  object-actions.ts (sprint 94) an object's ⋯ menu (objectMenu) in the worksheet and the Object Browser: Quick DDL (objectDdl), Drop with
230
242
  dependents, Add index / trigger / policy as drafts; GET /sql/objects/action, /sql/objects/panel (Open in a panel)
243
+ data-modeler.ts (sprint 98) SQL Workshop → Data Modeler: /sql/modeler (diagrams, meta.sql_diagram, 111), /:id (SVG), /:id/objects, /layout,
244
+ /rename, /delete, /svg (export), /ddl (diagramDdl), /dictionary (data dictionary, ?download=1)
231
245
  scripts.ts SQL Workshop → SQL Scripts: editor, upload/download, run, results per statement, run history
232
246
  quicksql.ts SQL Workshop → Quick SQL page (preview, save as script, run)
233
247
  querybuilder.ts SQL Workshop → Query Builder: catalog, joins by foreign key or drawn, functions/group by, buildQuery() from the URL; the canvas is in builder.js
234
248
  users.ts user directory and identity providers
249
+ db-users.ts (sprint 99, DA-13) Administration → Database Users (/builder/db-users, administrators only): PostgreSQL
250
+ roles with highlights, create/edit (review the masked SQL, then Apply in one transaction), drop with
251
+ reassigning; pgkiln's own roles read-only, roles of applications and workspaces not dropped
235
252
  api.ts per-app REST API page (API role, tokens)
236
253
  globalization.ts translations, XLIFF/CSV, text messages
237
254
  dataload.ts SQL Workshop → Load Data (with definitions, save a mapping as one); data load definition spec (Shared Components)
@@ -259,6 +276,9 @@ src/
259
276
  form-designer.ts page designer: Form Designer settings (designers' scheme; sources: key, actions, offered columns, labels, lists of values)
260
277
  workingcopies.ts Working copies: list and create, compare with differences, merge or refresh with conflict choices, delete
261
278
  rest.ts REST module endpoints list and curl example (Shared Components)
279
+ autorest.ts (sprint 100) SQL Workshop → RESTful Services (/builder/sql/rest): publish a table or view through an
280
+ application of the workspace (checks: schema the workshop may use, app role not the owner), its page
281
+ (grants per method, RLS, security_invoker, endpoints, cURL/fetch, OpenAPI link), settings, disable
262
282
  workflows.ts workflow versions, diagram and instances (Shared Components)
263
283
  process-jobs.ts page designer: the Jobs tab of a background chain process
264
284
  template-spec.ts template component property form (Shared Components)
@@ -290,6 +310,8 @@ public/
290
310
  app.css theme (light/dark, responsive; --font, --font-size, --radius for style variants; template option classes to-*)
291
311
  app.js client runtime: dialogs (dialog_closed actions), popup LOVs, dynamic actions (focus, classes, messages), grids (add/duplicate rows, master-detail refresh, move/resize columns, copy/paste of cell ranges), menus, lazy regions, maps (Leaflet layers, marker clusters, heat layer, layer legend, area/distance filter) (no inline JS)
292
312
  code-editor.js, .css builder code editor: enhances <textarea data-code>, highlighting, suggestions (no dependencies)
313
+ palette.js (sprint 96) the builder's search dialog (Ctrl+K), recently visited SQL Workshop pages, the Launchpad's tabs
314
+ data-modeler.js, .css (sprint 98) the Data Modeler: drag boxes, undo/redo, save, zoom/fit, auto layout, mini-map, SVG/PNG export, print
293
315
  worksheet.js, .css (sprint 91) the SQL Worksheet: run keys with the cursor, output tabs, navigator swap and search, drag and drop, splitters;
294
316
  (92) grid sort, value dialog, history filter; (93) worksheet tabs in localStorage, Files, binds dialog, format, find, case
295
317
  builder.css builder only: IDE look (dark chrome, icon rail, panes), builder light/dark tokens
@@ -311,9 +333,12 @@ test/
311
333
  unload.test.ts Unload Data: CSV/JSON/XLSX/XML output, read back with Load Data, read-only and one-statement checks, streaming
312
334
  app-from-file.test.ts Create → From a file: proposed names and types, app + table + rows + pages, row errors, login, validation
313
335
  workshop.test.ts SQL scripts, Quick SQL pages, query builder, data load definitions (Load Data, the process, export)
336
+ sql-charts.test.ts (sprint 97) the worksheet's Chart tab, saving a chart, the Charts dashboard, a chart's page, read-only runs
337
+ launchpad.test.ts (sprint 96) Launchpad groups, pins (builder pages only, at most 24), the search (JSON and page)
314
338
  tabledef.test.ts (sprint 95) table definitions round trip: CREATE, read, ALTER, read again; mistakes
315
339
  table-editor.test.ts (sprint 95) the Table Properties page: preview, apply, a failing apply rolls back, template, worksheet
316
340
  object-actions.test.ts (sprint 94) object menus: Quick DDL, Drop with dependents, Add index / trigger / policy, the panel, not-found
341
+ data-modeler.test.ts (sprint 98) Data Modeler: "hr core" with its FK lines, saved positions, SVG, objects, DDL, dictionary, geometry
317
342
  worksheet.test.ts (sprint 91) the SQL Worksheet: statement at the cursor, Run Script log, plans, notices, history, navigator, Run as
318
343
  quicksql.test.ts Quick SQL parser and DDL generator
319
344
  xml.test.ts XML reader: rows, attributes, paths, refused DTDs and entities, limits
@@ -360,6 +385,7 @@ test/
360
385
  helpers.ts a cookie-keeping test browser
361
386
  e2e/responsive.test.ts browser tests at phone/tablet/desktop widths (Playwright)
362
387
  e2e/code-editor.test.ts the code editor in a browser: highlighting, keys, suggestions, touch, screen readers
388
+ e2e/data-modeler.test.ts (sprint 98) the Data Modeler in a browser: drag, save, reload, undo/redo, zoom, mini-map, exports, phone
363
389
  e2e/worksheet.test.ts (sprint 91) the SQL Worksheet in a browser: run keys, tabs, navigator, drag and drop, splitters, phone, no JavaScript
364
390
  e2e/items.test.ts sprint 26 item types in a browser: editors, tags, stars, dates, reveal; without JavaScript
365
391
  e2e/designer.test.ts page designer: panes per width, drag and drop, keyboard, Arrange buttons, builder theme
@@ -1,17 +1,17 @@
1
1
  # 13. REST APIs
2
2
 
3
- pgkiln offers two ways to expose data securely over REST (mobile apps, integrations, scripts),
3
+ pgkiln offers three ways to expose data securely over REST (mobile apps, integrations, scripts),
4
4
  which can be combined:
5
5
 
6
- | | [REST modules](#rest-modules-in-the-builder) | [PostgREST](#how-it-works) |
7
- |---|---|---|
8
- | What | Endpoints you define in the builder: a method, a path and the SQL | A separate service that turns a schema of views and functions into an API |
9
- | Served by | pgkiln itself, under `/a/<alias>/rest/<module>/` | PostgREST, next to pgkiln |
10
- | Runs as | the application's database role (like its pages) | a dedicated API role |
11
- | Good for | a handful of tailored endpoints, field apps, integrations | broad data access with filtering, sorting and embedding |
6
+ | | [REST modules](#rest-modules-in-the-builder) | [AutoREST](#autorest-tables-and-views-from-the-sql-workshop) | [PostgREST](#how-it-works) |
7
+ |---|---|---|---|
8
+ | What | Endpoints you define in the builder: a method, a path and the SQL | A table or view published as it is: rows, one row, insert, update, delete | A separate service that turns a schema of views and functions into an API |
9
+ | Served by | pgkiln itself, under `/a/<alias>/rest/<module>/` | pgkiln itself, under `/a/<alias>/autorest/<object>/` | PostgREST, next to pgkiln |
10
+ | Runs as | the application's database role (like its pages) | the application's database role | a dedicated API role |
11
+ | Good for | a handful of tailored endpoints, field apps, integrations | quick CRUD access to a table, prototypes, simple integrations | broad data access with filtering, sorting and embedding |
12
12
 
13
- Both use the same tokens (App → REST API: tokens and OAuth clients), the same accounts and the
14
- same row level security, and both publish an OpenAPI description.
13
+ All three use the same tokens (App → REST API: tokens and OAuth clients), the same accounts and the
14
+ same row level security, and all publish an OpenAPI description.
15
15
 
16
16
  ## REST modules in the builder
17
17
 
@@ -63,6 +63,71 @@ curl -X POST http://127.0.0.1:3100/a/hr/rest/v1/leave -H "Authorization: Bearer
63
63
  -H "Content-Type: application/json" -d '{"start_date": "2027-05-03", "end_date": "2027-05-04", "reason": "dentist"}'
64
64
  ```
65
65
 
66
+ ## AutoREST: tables and views from the SQL Workshop
67
+
68
+ **SQL Workshop → RESTful Services** (`/builder/sql/rest`; Database Actions: a table's *REST › Enable*, ORDS
69
+ AutoREST), or **REST › Enable / Disable** in a table's or view's ⋯ menu (SQL Worksheet navigator, Object Browser).
70
+ Choose:
71
+
72
+ | Setting | Meaning |
73
+ |---|---|
74
+ | Table or view | Any table, partitioned table, view, materialized view or foreign table of a schema the SQL Workshop may use (not `meta`) |
75
+ | Application | An application of the current workspace with a database role. It decides how requests run (below) and gives the URL |
76
+ | URL name | The segment in `/a/<alias>/autorest/<name>/`: lower case letters, digits, `_` and `-`; the object's name by default |
77
+ | Methods | `GET` (rows and one row), `POST` (insert), `PUT` (update), `DELETE`. `PUT` and `DELETE` need a primary key; a materialized view answers `GET` only |
78
+ | Who may call it | **A bearer token of the application** (the default), or **public**: anyone, without a token. Public is never implied: it is a choice on the form |
79
+ | Roles | Optional application roles; the caller needs one of them (`meta.has_role()`), else 403 |
80
+ | Page size | Rows per page without `?limit=` (1–500, default 25) |
81
+
82
+ The object's page shows the checks (the role is not the owner and doesn't bypass row level security; its grants per
83
+ method; row level security on or off; for a view whether it is `security_invoker`; the primary key; columns the role
84
+ may not read), the endpoints with their URLs, cURL and `fetch` examples, and the OpenAPI link. Its settings can be
85
+ changed, the object disabled (404) or removed (*Disable REST*). The table itself is never changed.
86
+
87
+ **Endpoints** (`/a/hr/autorest/dept/` for `hr.dept` published through `hr`):
88
+
89
+ | Request | Answer |
90
+ |---|---|
91
+ | `GET …/dept/` | `{"items": […], "offset": 0, "limit": 25, "has_more": true}`. `?limit=` (1–500) and `?offset=` page; `?<column>=<value>` keeps rows whose column equals the value (several are combined with AND); `?q=<text>` keeps rows where a text column contains the text (case-insensitive; `%` and `_` are literal); `?order=dname,deptno.desc` sorts (default: the primary key). An unknown parameter or column is a 400 |
92
+ | `GET …/dept/10` | The row as an object, or 404. A composite key is comma separated: `…/pair/1,x` (URL-encode a comma inside a value) |
93
+ | `POST …/dept/` | A JSON object of column values → 201 with the new row and a `Location` header. Columns left out get their defaults; an unknown column is a 400 |
94
+ | `PUT …/dept/10` | A JSON object of the columns to change → 200 with the row, or 404 (also when row level security hides it). Columns left out keep their values |
95
+ | `DELETE …/dept/10` | 204, or 404 |
96
+ | `GET /a/hr/autorest/openapi.json` | OpenAPI 3 of the application's published objects: without a token the public ones, with a valid token all of them; column types as JSON Schema |
97
+
98
+ A method that isn't enabled answers 405 with an `Allow` header. Errors are JSON `{"error": "…"}`, as for REST modules:
99
+ 400 for invalid input, a check or unique constraint, or a `raise exception`; 403 for a missing role or grant
100
+ (including column grants and a row level security `with check`).
101
+
102
+ **How a request runs.** As for [REST modules](#rest-modules-in-the-builder): the token is checked (signature, expiry,
103
+ the application, an active account with access or a client that isn't revoked) at every request; a browser session is
104
+ not accepted. The statement then runs in a transaction **as the application's database role**, with
105
+ `meta.app_user()` = the caller (`nobody` for a public object without a token), `meta.has_role()` reading the caller's
106
+ roles, and a 30-second statement timeout. So the role's grants, column grants and the table's row level security
107
+ apply exactly as on the application's pages. Columns the role may not select are left out of every answer and can't
108
+ be filtered or sorted on. AutoREST refuses, when the object is enabled and again at every request (after `SET ROLE`),
109
+ a role that owns the object or is a member of its owner (row level security doesn't apply to the owner), a superuser
110
+ and a role with `BYPASSRLS`. An application without a database role can't publish objects. Names come from the
111
+ catalog and are quoted; filter values, keys and bodies are query parameters, never SQL text.
112
+
113
+ The workspace preference *Enable RESTful services* turns AutoREST off with the REST modules (404), and the
114
+ application's availability applies too.
115
+
116
+ ```bash
117
+ TOKEN=… # App → REST API → Issue a token for king
118
+ curl "http://127.0.0.1:3100/a/hr/autorest/dept/?limit=2" -H "Authorization: Bearer $TOKEN"
119
+ # {"items":[{"deptno":10,"dname":"ACCOUNTING",…},{"deptno":20,…}],"offset":0,"limit":2,"has_more":true}
120
+ curl "http://127.0.0.1:3100/a/hr/autorest/dept/?limit=2" # 401: no token
121
+ ```
122
+
123
+ **Views.** A view without `security_invoker = true` runs with its owner's rights, so the row level security of the
124
+ tables beneath it does not apply to the caller; the page warns about it. Views have no primary key: they publish the
125
+ collection (`GET`, and `POST` when PostgreSQL can insert into the view).
126
+
127
+ **Export.** The published objects are installation data, like OAuth clients: they name objects of this database and
128
+ are not part of an application export; an in-place import (`pgkiln import --replace`) keeps them. Tailored endpoints
129
+ that travel with the application are [REST modules](#rest-modules-in-the-builder).
130
+
66
131
  ## PostgREST
67
132
 
68
133
  [PostgREST](https://postgrest.org) runs as a separate service **next to** pgkiln and turns
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pgkiln",
3
- "version": "0.47.0",
3
+ "version": "0.48.0",
4
4
  "description": "Open source low-code, SQL-driven application builder for PostgreSQL, inspired by Oracle APEX",
5
5
  "keywords": [
6
6
  "postgresql",
@@ -1032,3 +1032,25 @@ details.prop-group-more[open] > summary { margin-bottom: 8px; }
1032
1032
 
1033
1033
  /* (sprint 90, PD-4) a commented-out component in the tree (APEX: Comment Out): struck through and muted */
1034
1034
  .pd-node[data-commented] .pd-label { text-decoration: line-through; color: var(--muted); }
1035
+
1036
+ /* (sprint 99, DA-13) Administration → Database Users */
1037
+ .dbu-stats { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 0.6rem; }
1038
+ .dbu-stats a.stat { color: inherit; text-decoration: none; }
1039
+ .dbu-stats a.stat:hover, .dbu-stats a.stat:focus-visible { border-color: var(--accent); }
1040
+ .dbu-stats a.stat[aria-current="page"] { border-color: var(--accent); background: var(--accent-soft); }
1041
+ .dbu-search { display: flex; flex-wrap: wrap; gap: 0.4rem; align-items: center; }
1042
+ .dbu-search input { flex: 1 1 12rem; max-width: 24rem; }
1043
+ .dbu-members { max-height: 16rem; overflow: auto; }
1044
+ .dbu-schemas .te-c { text-align: center; width: 1%; white-space: nowrap; }
1045
+ .dbu-sql { white-space: pre-wrap; overflow-wrap: anywhere; }
1046
+ .dbu-list td { white-space: normal; overflow: visible; max-width: 24rem; }
1047
+ .dbu-list td .tag { margin: 0.1rem 0; }
1048
+ .dbu-facts { display: grid; grid-template-columns: max-content 1fr; gap: 0.35rem 1rem; margin: 0; }
1049
+ .dbu-facts dt { color: var(--muted); }
1050
+ .dbu-facts dd { margin: 0; min-width: 0; }
1051
+ @media (max-width: 640px) {
1052
+ .dbu-facts { grid-template-columns: 1fr; } .dbu-facts dd { margin-bottom: 0.4rem; }
1053
+ .dbu-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); } .dbu-stats a.stat { padding: 0.5rem 0.7rem; } .dbu-stats .stat b { font-size: 1.15rem; }
1054
+ }
1055
+ /* (sprint 100) RESTful Services: examples wrap instead of scrolling sideways */
1056
+ pre.wrap-pre { white-space: pre-wrap; overflow-wrap: anywhere; }