pgkiln 0.38.0 → 0.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SECURITY.md +2 -0
- package/db/migrations/093_workspace_preferences.sql +34 -0
- package/db/migrations/094_task_vacation_expiry.sql +182 -0
- package/docs/apex-feature-parity.md +6 -6
- package/docs/guide/03-builder.md +43 -1
- package/docs/guide/04-pages-and-regions.md +21 -5
- package/docs/guide/06-processing.md +27 -1
- package/docs/guide/12-development.md +10 -4
- package/docs/guide/13-rest-api.md +3 -1
- package/examples/hr/hr_56_more_charts.sql +57 -0
- package/examples/hr/hr_57_task_policies.sql +18 -0
- package/package.json +1 -1
- package/public/app.css +25 -0
- package/public/sw.js +2 -1
- package/src/app.ts +2 -0
- package/src/automations.ts +6 -0
- package/src/builder/components.ts +7 -0
- package/src/builder/home.ts +3 -2
- package/src/builder/region-settings.ts +3 -0
- package/src/builder/sql-utilities.ts +278 -0
- package/src/builder/sql.ts +3 -1
- package/src/builder/ui.ts +16 -3
- package/src/builder/workspace-backups.ts +78 -0
- package/src/builder/workspaces.ts +83 -1
- package/src/cli/replace.ts +2 -0
- package/src/i18n/ar.ts +25 -0
- package/src/i18n/cs.ts +25 -0
- package/src/i18n/da.ts +25 -0
- package/src/i18n/de.ts +25 -0
- package/src/i18n/el.ts +25 -0
- package/src/i18n/es.ts +25 -0
- package/src/i18n/fi.ts +25 -0
- package/src/i18n/fr.ts +25 -0
- package/src/i18n/he.ts +25 -0
- package/src/i18n/it.ts +25 -0
- package/src/i18n/ja.ts +25 -0
- package/src/i18n/ko.ts +25 -0
- package/src/i18n/nb.ts +25 -0
- package/src/i18n/pl.ts +25 -0
- package/src/i18n/pt.ts +25 -0
- package/src/i18n/ru.ts +25 -0
- package/src/i18n/sv.ts +25 -0
- package/src/i18n/tr.ts +25 -0
- package/src/i18n/uk.ts +25 -0
- package/src/i18n/zh.ts +25 -0
- package/src/i18n.ts +50 -0
- package/src/runtime/charts.ts +154 -5
- package/src/runtime/rest.ts +8 -2
- package/src/runtime/tasks.ts +62 -4
- package/src/session.ts +5 -0
- package/src/workflow.ts +6 -4
package/SECURITY.md
CHANGED
|
@@ -70,6 +70,8 @@ first version (MVP). Every finding below has a regression test in
|
|
|
70
70
|
| Workspaces (0.29.0) | Every builder request under `/apps/:id` or `/pages/:pid` (GET and POST), a working copy's main application, a boilerplate and the code editor's application are checked against the developer's workspaces in `developer()` and answer 404 outside them; lists are filtered by the current workspace. Switching needs CSRF and membership; managing workspaces needs an administrator and CSRF; names are escaped; subscriptions only reach theme and library applications of the same workspace. Workspace tables are closed to the runtime role. **A shared workspace is not a tenant boundary:** its SQL Workshop runs as the owner and its application code on the shared runtime connection; isolate a workspace for that (below). |
|
|
71
71
|
| Isolated workspaces (sprint 60) | The boundary is the PostgreSQL login (`session_user`, which SQL can't change): an isolated workspace's applications run on its own run login and its developers' SQL on its own developer login (`src/workspace-db.ts`; passwords derived from `PGKILN_SECRET_KEY`, never stored), so `RESET ROLE` or `set_config('role', …)` only reach that login. The run login has `pgkiln_app_code` (the runtime role's rights in `meta`, kept in step after every migration by `meta.sync_app_code_grants()`, checked by a test) and the workspace's roles; the developer login only the workspace's roles. Row-level security on every `meta` table the runtime reads keys on the login (`meta.visible_apps()`), both ways: isolated workspaces don't see others, the shared runtime doesn't see isolated ones; the owner isn't affected. `meta.app_id()` and the eight functions that take an application id (`meta.checked_app`) refuse an application the login may not see. A workspace's database roles are an administrator's list (`meta.workspace_role`): an application there may only run as one of them, a role belongs to one workspace, and superusers, roles with CREATEROLE/BYPASSRLS/REPLICATION and pgkiln's own roles are refused; memberships follow by triggers (`meta.workspace_sync_roles()`). A new application gets a new role and a new or own schema. Every builder tool that runs a developer's SQL uses the workspace's developer login (`workshopDb`, `devDbForApp`); the import check plans the imported SQL on it, outside the import's owner transaction. Saved scripts, runs, blueprints and generators are per workspace. **Not covered:** administrators and developers who also belong to a shared workspace (owner rights there), the `pg_catalog` (definitions are readable by every login), PostgREST (one authenticator), identity providers, LDAP, mail and AI services (installation-wide). |
|
|
72
72
|
| Builder screens like APEX's (sprint 61) | The sign-in page's workspace is checked after the password (only the developer's workspaces; a wrong one answers like a wrong password, failures are throttled and logged as before); *Remember workspace and username* is an HttpOnly cookie for `/builder` holding no secret, read defensively and escaped; the redirect after sign-in is a `/builder` path only. Workspace message and banner: administrators and the workspace's administrators, CSRF, plain text escaped, the banner colour from a fixed list. Utilization: the same. SQL Workshop home: your own recent commands only (by id and username), the schema checked against the schemas the session's connection may use (and set as a parameter of `set_config`). Application groups: every query bound to the current workspace; groups and applications of other workspaces are ignored. App Gallery: keys are names from `examples/gallery/gallery.json`, never paths; sample apps (shipped SQL as the owner, demo accounts with known passwords) are for administrators only; starter apps go through the blueprint review and its signed create step. Cross application reports: fixed SQL per topic, the workspace id as a parameter. |
|
|
73
|
+
| Workspace preferences, extension links, Manage backups (sprint 62) | Preferences and links: administrators and the workspace's administrators, CSRF, logged. The SQL Workshop preference is checked in `developer()` for every `/builder/sql` GET and POST before a route runs, so no SQL Workshop route can skip it; it is not a sandbox (a developer of several workspaces uses it in another; isolation is the boundary). RESTful services off: the module lookup answers 404 before authentication or any handler SQL. Extension links: only `http://`/`https://` URLs without spaces, quotes or angle brackets (checked in Node and by a CHECK constraint), escaped, opened with `rel="noopener noreferrer"`. Manage backups: only the current workspace's applications, through the existing `meta.backup_app`. SQL Workshop utilities: fixed catalogue SQL chosen by a key from a fixed list (own-property lookup), run read only with a statement timeout on the SQL Workshop's connection (an isolated workspace's developer login sees only its roles' schemas); the Database Monitor shows other sessions' query texts, so it is for administrators only and cancels nothing. |
|
|
74
|
+
| Approval vacation rules and expiration (sprint 64) | A vacation rule is always the signed-in user's own (`meta.app_user()` in a security-definer function; no user field is read from the form); its table is closed to the runtime roles; the delegate's rights are computed in `meta.task_rights` on every call and only for tasks the user owns by name or is assigned (never role ownership), so they end with the rule. Dates are checked as dates; CSRF and an in-app `next`. The expiry tick runs as the owner from the scheduler only (no grant). |
|
|
73
75
|
| Drawers, built-in template components, Theme Roller additions (0.29.0) | Dialog positions and sizes, base styles, dark-mode colours, item and report-column template options only reach the page from fixed lists (checked when saved and again when rendered: a hand-edited value is ignored); the browser gets dialog shapes as JSON values from those lists. Built-in template components pass the same template checks as plug-ins; *Copy into this application* takes a static id from the fixed list, needs CSRF and the application in the developer's workspace, and never overwrites the application's own component. |
|
|
74
76
|
| Report row selection across pages (0.29.0) | `POST …/report/<id>/select` needs the CSRF token, page access and a visible report region whose `selection` names the item (and the item visible); it only changes that item's session state; values are bounded (5000, 400 characters, no `:`) and treated as user input, like a submit; output is escaped. |
|
|
75
77
|
| Instance settings (0.29.0) | Administrators only, with CSRF; only whole numbers within each setting's range are stored (a bad stored value falls back to the environment variable or default); the configuration overview never shows secrets (connection strings, keys: only whether they are set); changes are logged.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
-- =====================================================================
|
|
2
|
+
-- 093: workspace preferences and extension links (APEX: Administration →
|
|
3
|
+
-- Manage Service → Set Workspace Preferences, Manage Extension Links)
|
|
4
|
+
--
|
|
5
|
+
-- sql_workshop false: the SQL Workshop (SQL Commands, Object Browser,
|
|
6
|
+
-- scripts, data loading, Quick SQL, query builder, DDL and
|
|
7
|
+
-- compare, AI) is refused while the workspace is current
|
|
8
|
+
-- rest_services false: the REST modules of the workspace's applications
|
|
9
|
+
-- answer 404 at run time (/a/<alias>/rest/...)
|
|
10
|
+
--
|
|
11
|
+
-- meta.workspace_link: links to other tools (monitoring, a wiki, a ticket
|
|
12
|
+
-- system) shown in the builder's Extensions menu while the workspace is current.
|
|
13
|
+
--
|
|
14
|
+
-- Administrators and the workspace's administrators set them.
|
|
15
|
+
-- Installation data, not exported.
|
|
16
|
+
-- =====================================================================
|
|
17
|
+
alter table meta.workspace
|
|
18
|
+
add column sql_workshop boolean not null default true,
|
|
19
|
+
add column rest_services boolean not null default true;
|
|
20
|
+
comment on column meta.workspace.sql_workshop is 'Workspace preference (093): false refuses the SQL Workshop while the workspace is current.';
|
|
21
|
+
comment on column meta.workspace.rest_services is 'Workspace preference (093): false turns off the REST modules of the workspace''s applications.';
|
|
22
|
+
|
|
23
|
+
create table meta.workspace_link (
|
|
24
|
+
id serial primary key,
|
|
25
|
+
workspace_id int not null references meta.workspace on delete cascade,
|
|
26
|
+
label text not null check (label ~ '^\S(.{0,58}\S)?$'),
|
|
27
|
+
url text not null check (url ~ '^https?://[^\s<>"]+$' and length(url) <= 2000),
|
|
28
|
+
description text check (length(description) <= 500),
|
|
29
|
+
position int not null default 0,
|
|
30
|
+
unique (workspace_id, label)
|
|
31
|
+
);
|
|
32
|
+
revoke all on meta.workspace_link from public;
|
|
33
|
+
comment on table meta.workspace_link is 'Extension links (093): a workspace''s links to other tools, in the builder''s Extensions menu. Not exported.';
|
|
34
|
+
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
-- =====================================================================
|
|
2
|
+
-- 094: approvals: vacation rules, and expiry, renewal and escalation of
|
|
3
|
+
-- overdue tasks (APEX: Task Definition → Vacation Rule, Expiration Policy)
|
|
4
|
+
--
|
|
5
|
+
-- Vacation rules: a user of an application names a delegate and a period
|
|
6
|
+
-- (meta.set_vacation_rule from the task list). While the rule is active the
|
|
7
|
+
-- delegate may act on the tasks the user may act on as a named owner
|
|
8
|
+
-- (owner_users) or as the actual owner, checked live in meta.task_rights:
|
|
9
|
+
-- when the rule ends, so does the delegate's access. Role owners are not
|
|
10
|
+
-- passed on: the role's other members are there for that.
|
|
11
|
+
--
|
|
12
|
+
-- Expiration policy per task definition (null: overdue tasks stay open):
|
|
13
|
+
-- expire an overdue task ends with state 'expired' (no outcome)
|
|
14
|
+
-- renew its due date moves on by "due in" (up to max_renewals times,
|
|
15
|
+
-- default 3), then it expires
|
|
16
|
+
-- escalate once: escalate_role becomes a potential owner, the priority 1,
|
|
17
|
+
-- the task unassigned with a new due date; overdue again: expired
|
|
18
|
+
-- meta.task_expire_tick() applies it (the server's scheduler, every minute).
|
|
19
|
+
-- A workflow waiting for a task that expires goes on with the outcome
|
|
20
|
+
-- "expired" (or ends, like a cancelled task, without an "expired" branch).
|
|
21
|
+
-- =====================================================================
|
|
22
|
+
|
|
23
|
+
alter table meta.task_definition
|
|
24
|
+
add column expiration text check (expiration in ('expire', 'renew', 'escalate')),
|
|
25
|
+
add column max_renewals int check (max_renewals between 1 and 100),
|
|
26
|
+
add column escalate_role text check (escalate_role ~ '^\S{1,100}$');
|
|
27
|
+
comment on column meta.task_definition.expiration is 'Expiration policy (094): expire, renew or escalate an overdue task; null: it stays open.';
|
|
28
|
+
|
|
29
|
+
alter table meta.task
|
|
30
|
+
add column renewals int not null default 0,
|
|
31
|
+
add column escalated_at timestamptz;
|
|
32
|
+
alter table meta.task drop constraint task_state_check;
|
|
33
|
+
alter table meta.task add constraint task_state_check check (state in ('unassigned', 'assigned', 'completed', 'cancelled', 'expired'));
|
|
34
|
+
alter table meta.task_event drop constraint task_event_event_check;
|
|
35
|
+
alter table meta.task_event add constraint task_event_event_check
|
|
36
|
+
check (event in ('created', 'claimed', 'released', 'delegated', 'approved', 'rejected', 'completed', 'cancelled', 'commented', 'closed',
|
|
37
|
+
'expired', 'renewed', 'escalated'));
|
|
38
|
+
|
|
39
|
+
-- ---------------------------------------------------------------- vacation rules
|
|
40
|
+
create table meta.task_vacation (
|
|
41
|
+
app_id int not null references meta.app on delete cascade,
|
|
42
|
+
username text not null check (username = lower(username) and length(username) between 1 and 100),
|
|
43
|
+
delegate_to text not null check (delegate_to = lower(delegate_to) and length(delegate_to) between 1 and 100),
|
|
44
|
+
starts_at timestamptz not null,
|
|
45
|
+
ends_at timestamptz not null,
|
|
46
|
+
created_at timestamptz not null default now(),
|
|
47
|
+
primary key (app_id, username),
|
|
48
|
+
check (delegate_to <> username),
|
|
49
|
+
check (ends_at > starts_at)
|
|
50
|
+
);
|
|
51
|
+
create index on meta.task_vacation (app_id, delegate_to);
|
|
52
|
+
revoke all on meta.task_vacation from public;
|
|
53
|
+
comment on table meta.task_vacation is 'Vacation rules (094): while active, delegate_to acts on the user''s tasks. User data, not exported.';
|
|
54
|
+
|
|
55
|
+
/** The users (lower case) of this application whose active vacation rule names the current user. */
|
|
56
|
+
create function meta.acting_for() returns text[]
|
|
57
|
+
language sql stable security definer set search_path = meta, pg_catalog as $$
|
|
58
|
+
select coalesce(array_agg(v.username order by v.username), '{}')
|
|
59
|
+
from task_vacation v
|
|
60
|
+
where v.app_id = meta.app_id() and v.delegate_to = lower(meta.app_user()) and now() >= v.starts_at and now() < v.ends_at
|
|
61
|
+
$$;
|
|
62
|
+
|
|
63
|
+
create function meta.set_vacation_rule(p_delegate text, p_from timestamptz, p_until timestamptz) returns void
|
|
64
|
+
language plpgsql security definer set search_path = meta, pg_catalog as $$
|
|
65
|
+
declare
|
|
66
|
+
v_user text := lower(meta.app_user());
|
|
67
|
+
v_to text := lower(btrim(coalesce(p_delegate, '')));
|
|
68
|
+
v_from timestamptz := coalesce(p_from, now());
|
|
69
|
+
begin
|
|
70
|
+
if v_user is null or v_user = 'nobody' then
|
|
71
|
+
raise exception 'Sign in to set a vacation rule.';
|
|
72
|
+
end if;
|
|
73
|
+
if v_to = '' or length(v_to) > 100 or v_to ~ '\s' then
|
|
74
|
+
raise exception 'Name the user who takes over your tasks.';
|
|
75
|
+
end if;
|
|
76
|
+
if v_to = v_user then
|
|
77
|
+
raise exception 'You cannot delegate your tasks to yourself.';
|
|
78
|
+
end if;
|
|
79
|
+
if p_until is null or p_until <= v_from or p_until <= now() then
|
|
80
|
+
raise exception 'The vacation rule ends after it starts, and in the future.';
|
|
81
|
+
end if;
|
|
82
|
+
if p_until > v_from + interval '1 year' then
|
|
83
|
+
raise exception 'A vacation rule lasts at most a year.';
|
|
84
|
+
end if;
|
|
85
|
+
insert into task_vacation (app_id, username, delegate_to, starts_at, ends_at)
|
|
86
|
+
values (meta.app_id(), v_user, v_to, v_from, p_until)
|
|
87
|
+
on conflict (app_id, username) do update
|
|
88
|
+
set delegate_to = excluded.delegate_to, starts_at = excluded.starts_at, ends_at = excluded.ends_at, created_at = now();
|
|
89
|
+
end
|
|
90
|
+
$$;
|
|
91
|
+
|
|
92
|
+
create function meta.clear_vacation_rule() returns void
|
|
93
|
+
language sql security definer set search_path = meta, pg_catalog as $$
|
|
94
|
+
delete from task_vacation where app_id = meta.app_id() and username = lower(meta.app_user());
|
|
95
|
+
$$;
|
|
96
|
+
|
|
97
|
+
/** The current user's vacation rule in this application (none: no row). */
|
|
98
|
+
create function meta.vacation_rule() returns table (delegate_to text, starts_at timestamptz, ends_at timestamptz, active boolean)
|
|
99
|
+
language sql stable security definer set search_path = meta, pg_catalog as $$
|
|
100
|
+
select v.delegate_to, v.starts_at, v.ends_at, now() >= v.starts_at and now() < v.ends_at
|
|
101
|
+
from task_vacation v
|
|
102
|
+
where v.app_id = meta.app_id() and v.username = lower(meta.app_user()) and v.ends_at > now()
|
|
103
|
+
$$;
|
|
104
|
+
|
|
105
|
+
revoke all on function meta.acting_for(), meta.set_vacation_rule(text, timestamptz, timestamptz), meta.clear_vacation_rule(), meta.vacation_rule() from public;
|
|
106
|
+
grant execute on function meta.acting_for(), meta.set_vacation_rule(text, timestamptz, timestamptz), meta.clear_vacation_rule(), meta.vacation_rule() to public;
|
|
107
|
+
|
|
108
|
+
-- Same as 072, plus: the delegates of users on vacation act for them (named owners and actual owners).
|
|
109
|
+
create or replace function meta.task_rights(t meta.task) returns meta.task_rights
|
|
110
|
+
language plpgsql stable security definer set search_path = meta, pg_catalog as $$
|
|
111
|
+
declare
|
|
112
|
+
v_user text := lower(meta.app_user());
|
|
113
|
+
v_for text[] := meta.acting_for();
|
|
114
|
+
d meta.task_definition;
|
|
115
|
+
r meta.task_rights;
|
|
116
|
+
v_open boolean := t.state in ('unassigned', 'assigned');
|
|
117
|
+
v_mine boolean := lower(t.actual_owner) = v_user or lower(t.actual_owner) = any (v_for);
|
|
118
|
+
begin
|
|
119
|
+
select * into d from task_definition where id = t.definition_id;
|
|
120
|
+
r.is_initiator := lower(t.initiator) = v_user;
|
|
121
|
+
r.is_owner := exists (select 1 from unnest(t.owner_users) u where lower(u) = v_user or lower(u) = any (v_for))
|
|
122
|
+
or exists (select 1 from unnest(t.owner_roles) x where meta.has_role(x));
|
|
123
|
+
r.is_admin := d.admin_role is not null and meta.has_role(d.admin_role);
|
|
124
|
+
r.may_see := t.app_id = meta.app_id() and v_user <> 'nobody'
|
|
125
|
+
and t.tenant_id is not distinct from meta.tenant_id()
|
|
126
|
+
and (r.is_initiator or r.is_owner or r.is_admin or coalesce(v_mine, false));
|
|
127
|
+
-- an initiator may not decide on their own request (unless the definition allows it)
|
|
128
|
+
r.may_act := r.may_see and v_open and (d.initiator_can_complete or not r.is_initiator)
|
|
129
|
+
and (coalesce(v_mine, false) or (t.state = 'unassigned' and r.is_owner));
|
|
130
|
+
r.may_claim := r.may_see and t.state = 'unassigned' and r.is_owner and (d.initiator_can_complete or not r.is_initiator);
|
|
131
|
+
r.may_release := r.may_see and t.state = 'assigned' and coalesce(v_mine, false);
|
|
132
|
+
r.may_delegate := r.may_see and v_open and (coalesce(v_mine, false) or r.is_admin);
|
|
133
|
+
r.may_cancel := r.may_see and v_open and (r.is_initiator or r.is_admin);
|
|
134
|
+
return r;
|
|
135
|
+
end
|
|
136
|
+
$$;
|
|
137
|
+
|
|
138
|
+
-- ---------------------------------------------------------------- expiration
|
|
139
|
+
create function meta.task_expire_tick() returns int
|
|
140
|
+
language plpgsql security definer set search_path = meta, pg_catalog as $$
|
|
141
|
+
declare
|
|
142
|
+
x record;
|
|
143
|
+
n int := 0;
|
|
144
|
+
v_due interval;
|
|
145
|
+
begin
|
|
146
|
+
for x in
|
|
147
|
+
select t.id, t.due_at, t.renewals, t.escalated_at, t.owner_roles, d.expiration, d.max_renewals, d.escalate_role, d.due_in
|
|
148
|
+
from task t join task_definition d on d.id = t.definition_id
|
|
149
|
+
where t.state in ('unassigned', 'assigned') and t.due_at < now() and d.expiration is not null
|
|
150
|
+
order by t.due_at
|
|
151
|
+
limit 500
|
|
152
|
+
for update of t skip locked
|
|
153
|
+
loop
|
|
154
|
+
v_due := case when x.due_in is not null then x.due_in::interval end;
|
|
155
|
+
if x.expiration = 'renew' and v_due is not null and x.renewals < coalesce(x.max_renewals, 3) then
|
|
156
|
+
update task set due_at = greatest(x.due_at + v_due, now() + v_due), renewals = renewals + 1 where id = x.id;
|
|
157
|
+
insert into task_event (task_id, username, event, detail)
|
|
158
|
+
values (x.id, 'system', 'renewed', format('%s of %s', x.renewals + 1, coalesce(x.max_renewals, 3)));
|
|
159
|
+
elsif x.expiration = 'escalate' and x.escalated_at is null then
|
|
160
|
+
update task
|
|
161
|
+
set owner_roles = case when x.escalate_role is null or x.escalate_role = any (owner_roles) then owner_roles
|
|
162
|
+
else array_append(owner_roles, lower(x.escalate_role)) end,
|
|
163
|
+
priority = 1, state = 'unassigned', actual_owner = null, escalated_at = now(),
|
|
164
|
+
due_at = case when v_due is not null then now() + v_due end
|
|
165
|
+
where id = x.id;
|
|
166
|
+
insert into task_event (task_id, username, event, detail) values (x.id, 'system', 'escalated', x.escalate_role);
|
|
167
|
+
else
|
|
168
|
+
update task set state = 'expired', completed_at = now() where id = x.id;
|
|
169
|
+
insert into task_event (task_id, username, event) values (x.id, 'system', 'expired');
|
|
170
|
+
end if;
|
|
171
|
+
n := n + 1;
|
|
172
|
+
end loop;
|
|
173
|
+
return n;
|
|
174
|
+
end
|
|
175
|
+
$$;
|
|
176
|
+
revoke all on function meta.task_expire_tick() from public;
|
|
177
|
+
|
|
178
|
+
-- Same as 022, plus: an expired task wakes its workflow too.
|
|
179
|
+
drop trigger task_wakes_workflow on meta.task;
|
|
180
|
+
create trigger task_wakes_workflow after update of state on meta.task
|
|
181
|
+
for each row when (new.workflow_id is not null and new.state in ('completed', 'cancelled', 'expired') and old.state is distinct from new.state)
|
|
182
|
+
execute function meta.task_wakes_workflow();
|
|
@@ -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-13 (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-13 (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
|
|
|
@@ -64,7 +64,7 @@ application reports, Manage Service), so the share available dropped without any
|
|
|
64
64
|
| 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)) |
|
|
65
65
|
| Interactive grid views: single row view, chart view, group by | ✅ | (sprint 54) **Single row view**: one row of the search as a form with first/previous/next/last and *Add row*, from the Actions or row actions menu, saved by the grid's own process with the same checks; **group by** and **chart** set up in the Actions menu over every row of the search, as for the interactive report; `views` limits them; Save comes back to the same search, page and view ([chapter 4](guide/04-pages-and-regions.md#grid-interactive-grid)). No pivot view on grids (the interactive report has one), no editing in the single row view of columns the grid doesn't show |
|
|
66
66
|
| 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)) |
|
|
67
|
-
| 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.
|
|
67
|
+
| 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); (sprint 63) **range** (floating columns from low to high), **box plot** (from one value per row or five statistics) and **stock** (candlesticks from open, high, low and close); 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. sunburst, treemap, timeline, picto), editing a Gantt by drag and drop |
|
|
68
68
|
| Cards and metric cards (26.1 metric card template) | ✅ | Cards from SQL, with a KPI "metric" style |
|
|
69
69
|
| 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)) |
|
|
70
70
|
| Faceted search | ✅ | Checkbox, range (predefined, or a custom from/to on numbers and dates), star rating and search facets with live counts that honour the other facets; exclude on checkbox facets (26.1). Values travel as query parameters, never as SQL text. **Missing:** facet charts |
|
|
@@ -183,7 +183,7 @@ application reports, Manage Service), so the share available dropped without any
|
|
|
183
183
|
|
|
184
184
|
| APEX | pgkiln | Notes |
|
|
185
185
|
|---|---|---|
|
|
186
|
-
| SQL Workshop: SQL commands, object browser | ✅ | (sprint 61) A **home page** like APEX's: tiles, recently created tables, your recent SQL commands and the workspace's recent scripts, and the session's **default schema** (first in the search path of SQL Commands and Scripts). The object browser shows columns, RLS policies, grants, data and function source |
|
|
186
|
+
| SQL Workshop: SQL commands, object browser | ✅ | (sprint 61) A **home page** like APEX's: tiles, recently created tables, your recent SQL commands and the workspace's recent scripts, and the session's **default schema** (first in the search path of SQL Commands and Scripts). The object browser shows columns, RLS policies, grants, data and function source. (sprint 62) **Utilities** like APEX's: the tools on one page, **Object Reports** (tables without a primary key, unindexed foreign keys, row-level security without policies or not enabled, PUBLIC grants, unused indexes, largest tables, missing comments), **About Database** and a **Database Monitor** of sessions and blocked queries for administrators. **Missing:** a recycle bin (PostgreSQL has none), user interface defaults (pgkiln's wizards read the catalog and comments) |
|
|
187
187
|
| RESTful services (ORDS) | ✅ | [PostgREST](https://postgrest.org) next to pgkiln: `api` schema, the same RLS as the UI, per-app API role, tokens in the builder, a pre-request check, and **OAuth clients** (client credentials, like ORDS `oauth.create_client`) so tokens renew themselves |
|
|
188
188
|
| REST handler editor, REST-enabled SQL | ✅ | **REST modules** in the builder: handlers (method, path with parameters, SQL as collection, item or statements, roles, public) served by pgkiln with bearer tokens and an OpenAPI description; plus PostgREST for schema-wide APIs. **Missing:** REST-enabled SQL (rarely desirable) |
|
|
189
189
|
| SQL scripts, query builder, Quick SQL | ✅ | **SQL Scripts**: saved, upload/download, a result per statement, stop or continue on errors, optionally one transaction, run history. **Quick SQL** (a subset: tables, child tables, types, the main column directives, `/auditcols`, settings, views). A graphical **query builder**: tables as boxes on a canvas (dragged, placed where left), joins along foreign keys or drawn from column to column (inner or left), column functions with automatic `group by`, conditions, sort, open in SQL Commands; without JavaScript the same as forms ([chapter 3](guide/03-builder.md#sql-workshop)) |
|
|
@@ -202,7 +202,7 @@ application reports, Manage Service), so the share available dropped without any
|
|
|
202
202
|
|
|
203
203
|
| APEX | pgkiln | Notes |
|
|
204
204
|
|---|---|---|
|
|
205
|
-
| 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)
|
|
205
|
+
| 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. (sprint 64) **Vacation rules** (a stand-in acts on a user's tasks while the rule is active, checked on every request) and **expiration policies** (expire, renew up to N times, escalate to a role once; a waiting workflow goes on with the outcome `expired`). **Missing:** built-in e-mail notifications (send them with `meta.send_mail` from the completion SQL or an automation) |
|
|
206
206
|
| 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 |
|
|
207
207
|
| 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)) |
|
|
208
208
|
| 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 |
|
|
@@ -214,12 +214,12 @@ application reports, Manage Service), so the share available dropped without any
|
|
|
214
214
|
| APEX | pgkiln | Notes |
|
|
215
215
|
|---|---|---|
|
|
216
216
|
| Developer accounts, workspace sign-in | ✅ | (sprint 61) The builder's sign-in page like APEX's: workspace (optional; it becomes the current one, a wrong one answers like a wrong password), username, password with a Show button, *Remember workspace and username*, a link to Administration |
|
|
217
|
-
| Workspace message, environment banner, workspace utilization (Manage Service) | ✅ | (sprint 61) An **Administration** menu in the icon rail; administrators and workspace administrators set a **workspace message** (on the App Builder home) and an **environment banner** (a coloured label on every builder page of the workspace), and see **workspace utilization** (applications, pages, page views, users, static files, schema storage) ([chapter 3](guide/03-builder.md#workspace-message-and-environment-banner)). **
|
|
217
|
+
| Workspace message, environment banner, workspace utilization, preferences and extension links (Manage Service) | ✅ | (sprint 61) An **Administration** menu in the icon rail; administrators and workspace administrators set a **workspace message** (on the App Builder home) and an **environment banner** (a coloured label on every builder page of the workspace), and see **workspace utilization** (applications, pages, page views, users, static files, schema storage) ([chapter 3](guide/03-builder.md#workspace-message-and-environment-banner)). (sprint 62) **Workspace preferences**: the SQL Workshop and the applications' RESTful services (REST modules) on or off per workspace; **extension links** in an Extensions menu of the rail ([chapter 3](guide/03-builder.md#workspace-preferences)). **Missing:** the account login controls of APEX's preferences (pgkiln's password policy and sign-in throttling are installation-wide) |
|
|
218
218
|
| 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 |
|
|
219
219
|
| 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 |
|
|
220
220
|
| 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) **Quick edit** (sprint 59: click a region, item or button to open it in the Page Designer) 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:** Theme Roller from the page |
|
|
221
221
|
| 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 |
|
|
222
|
-
| 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)). (sprint 58) **Page groups**: Shared Components → Page groups, a page's *Page group*, the page list by group with a filter ([chapter 3](guide/03-builder.md#page-groups)) |
|
|
222
|
+
| 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)); (sprint 62) Workspace utilities → **Manage backups** across the workspace's applications, with a backup of all of them at once. (sprint 58) **Page groups**: Shared Components → Page groups, a page's *Page group*, the page list by group with a filter ([chapter 3](guide/03-builder.md#page-groups)) |
|
|
223
223
|
| 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)) |
|
|
224
224
|
| Monitoring (top SQL) | ✅ | Activity per app; Top SQL per app's database role from `pg_stat_statements` (sortable, resettable) |
|
|
225
225
|
| 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)). (sprint 60) **Isolated workspaces** are a tenant boundary: the applications run on a PostgreSQL login of the workspace's own and its developers' SQL Workshop on another, with row-level security on pgkiln's tables, so SQL that resets its role can't reach other workspaces' applications, data, sessions or accounts; **workspace database roles** (APEX: workspace schemas) assigned by administrators; **workspace administrators** who manage their workspace's developers; SQL scripts, blueprints and sample data per workspace ([isolated workspaces](guide/03-builder.md#isolated-workspaces)). **Missing:** user directories per workspace (accounts are installation-wide, visible to the workspaces whose applications they use), developers created by a workspace administrator |
|
package/docs/guide/03-builder.md
CHANGED
|
@@ -69,6 +69,29 @@ Banner): a **message** (plain text, up to 2000 characters) shown to the workspac
|
|
|
69
69
|
and an **environment banner**: a label of up to 40 characters in one of eight colours, shown at the top of every
|
|
70
70
|
builder page while the workspace is current.
|
|
71
71
|
|
|
72
|
+
### Workspace preferences
|
|
73
|
+
|
|
74
|
+
Administrators and the workspace's administrators set them on the workspace's page (Administration menu →
|
|
75
|
+
*Workspace preferences*; APEX: Set Workspace Preferences):
|
|
76
|
+
|
|
77
|
+
- **Enable the SQL Workshop**: off, every SQL Workshop page (SQL Commands, the Object Browser, SQL scripts, Load and
|
|
78
|
+
Unload Data, Quick SQL, the query builder, Sample Data, DDL, Compare, AI) answers *403* while the workspace is
|
|
79
|
+
current, for every developer including administrators; the rail and Workspace utilities no longer show it. A
|
|
80
|
+
developer who belongs to another workspace can still use it there. Turn it off for a workspace whose developers
|
|
81
|
+
should build applications only, for example a shared workspace, where the SQL Workshop runs as pgkiln's owner.
|
|
82
|
+
- **Enable RESTful services**: off, the [REST modules](13-rest-api.md#rest-modules-in-the-builder) of the workspace's applications answer
|
|
83
|
+
*404* at `/a/<alias>/rest/…` (also their OpenAPI description); they can still be edited, and they come back
|
|
84
|
+
when it is turned on again. PostgREST is not affected.
|
|
85
|
+
|
|
86
|
+
Both are on by default (migration 093) and are not exported.
|
|
87
|
+
|
|
88
|
+
### Extension links
|
|
89
|
+
|
|
90
|
+
Links to the other tools a workspace's developers use (monitoring, a wiki, a ticket system; APEX: Manage Extension
|
|
91
|
+
Links), added on the workspace's page by administrators and the workspace's administrators: a label, an `http://` or
|
|
92
|
+
`https://` URL, an optional description and an order. While the workspace is current an **Extensions** icon in the
|
|
93
|
+
rail opens them, each in a new tab (`rel="noopener noreferrer"`).
|
|
94
|
+
|
|
72
95
|
### Workspace utilization
|
|
73
96
|
|
|
74
97
|
Administration menu → **Workspace utilization** (`/builder/workspaces/<id>/utilization`; APEX: Workspace
|
|
@@ -529,7 +552,7 @@ out, other keys are kept, columns the query no longer returns stay listed so you
|
|
|
529
552
|
| Region | Settings form |
|
|
530
553
|
|---|---|
|
|
531
554
|
| `grid` | Rows per page; whether users may add, change and delete rows; per column its heading, shown, read-only, required and "Edit as" (a shared list of values); aggregates in the footer, frozen columns, the Actions menu, saved and public grid reports, the row actions menu (edit link, duplicate, delete) and master-detail (the master's column and item, the detail's item and column) |
|
|
532
|
-
| `chart` | Chart type (also Gantt, pyramid and
|
|
555
|
+
| `chart` | Chart type (also Gantt, pyramid, polar, range, box plot and stock, with the columns each expects), the text when there are no rows, the gauge's range and thresholds, and the drill-down link (page and items, `#column#` and `#series#`); lists the query's columns |
|
|
533
556
|
| `cards` | Cards or KPI tiles, the text when there are no rows, and the link (page and items) |
|
|
534
557
|
| `calendar` | The views and the one shown first, the hours of the week and day views, the edit link of each event, the create-on-click link (`#start#`, `#end#`, `#date#`), and drag and drop (the SQL with `:EVENT_ID`, `:NEW_START`, `:NEW_END`, the key column, who may drag); warns when the query lacks `start_date` or `title` |
|
|
535
558
|
| `facets` | The report region it filters and a search field on/off; per column of that report: facet on/off, label, type (checkboxes, ranges, star rating), values shown, exclude, ranges (`..1000; 1000..3000 = Middle; 3000..`), from/to and order |
|
|
@@ -592,6 +615,12 @@ application, so the version it replaces becomes the newest backup and the restor
|
|
|
592
615
|
same way. Backups belong to the installation: they are not exported, and an import over the
|
|
593
616
|
application keeps them. Restores are logged in the activity log (`backup_restored`).
|
|
594
617
|
|
|
618
|
+
Workspace utilities → **Manage backups** (`/builder/backups`; APEX: Manage Backups) shows the backups of
|
|
619
|
+
every application of the current workspace on one page: how many, how many are kept, the newest and
|
|
620
|
+
whether the application changed since, and their size, with a link to each application's Backups.
|
|
621
|
+
**Back up now** there makes a backup of every application of the workspace that keeps backups (by
|
|
622
|
+
default only of those changed since their newest backup), with a note.
|
|
623
|
+
|
|
595
624
|
## Availability and build status
|
|
596
625
|
|
|
597
626
|
**Availability** (in an application's header; APEX: Application Availability and Build Status) says
|
|
@@ -1097,6 +1126,19 @@ you sign out. Tasks link to Quick SQL, blueprints, table descriptions, sample da
|
|
|
1097
1126
|
has (commented out), columns whose identity or generation differs, and types, domains and
|
|
1098
1127
|
sequences that differ. The same from the command line (`pgkiln ddl`, `pgkiln compare`,
|
|
1099
1128
|
[chapter 18](18-cli.md)) and for AI agents (`generate_ddl`, `compare_schemas`).
|
|
1129
|
+
- **Utilities** (`/builder/sql/utilities`; APEX: SQL Workshop → Utilities): tiles for Load and Unload Data, Sample
|
|
1130
|
+
Data, the Query Builder, DDL and Compare, and three pages of their own. Each runs in a read-only transaction with a
|
|
1131
|
+
15-second statement timeout, on the SQL Workshop's connection (an isolated workspace's developers see only the
|
|
1132
|
+
schemas of its roles):
|
|
1133
|
+
- **Object Reports**: tables without a primary key, foreign keys without an index (with the `create index` to
|
|
1134
|
+
add), row-level security without policies, tables without row-level security (and to whom they are granted),
|
|
1135
|
+
privileges granted to PUBLIC, unused indexes, the largest tables and tables without a comment; each object links
|
|
1136
|
+
to the Object Browser. pgkiln's own `meta` schema and the system's are left out.
|
|
1137
|
+
- **About Database**: the PostgreSQL version, database size, uptime, a few settings (encoding, time zone,
|
|
1138
|
+
connections, memory, row security), the installed extensions and the schemas with their size.
|
|
1139
|
+
- **Database Monitor** (administrators only): the client sessions of this database from `pg_stat_activity`, active
|
|
1140
|
+
first, with their state, wait event, running time, the sessions that block them and the query (as far as the
|
|
1141
|
+
owner may read other roles' statistics). Read only: it cancels nothing.
|
|
1100
1142
|
|
|
1101
1143
|
Because the SQL Workshop runs as the owner, restrict who gets a developer account.
|
|
1102
1144
|
|
|
@@ -137,7 +137,7 @@ database only checks the shape (at most 12 names of lower case letters, digits a
|
|
|
137
137
|
| [`report`](#report-interactive-report) | Read-only table from a SELECT, with search, filters, sorting, control break, aggregates, highlights, computed columns, group by, pivot and chart views, row selection, saved reports, paging and CSV/Excel/PDF download |
|
|
138
138
|
| [`grid`](#grid-interactive-grid) | Editable table on one database table, with aggregates, frozen, movable and resizable columns, saved grid reports, a row actions menu, master-detail, copy/paste of cells, and single row, group by and chart views |
|
|
139
139
|
| [`form`](#form) | Fields for one row of a table, with automatic fetch and save |
|
|
140
|
-
| [`chart`](#chart) | Bar, column, stacked, line, area, combo, scatter, bubble, donut, pie, gauge, funnel, radar, Gantt, pyramid or
|
|
140
|
+
| [`chart`](#chart) | Bar, column, stacked, line, area, combo, scatter, bubble, donut, pie, gauge, funnel, radar, Gantt, pyramid, polar, range, box plot or stock chart from a SELECT, with drill-down links |
|
|
141
141
|
| [`cards`](#cards) | Cards or KPI tiles from a SELECT |
|
|
142
142
|
| [`calendar`](#calendar) | Month, week, day and list views of dated rows, with create on click and drag and drop |
|
|
143
143
|
| [`facets`](#facets-faceted-search) | Checkbox, range and star filters with counts and a search field for a report |
|
|
@@ -506,7 +506,7 @@ Attributes:
|
|
|
506
506
|
|
|
507
507
|
| Key | Meaning |
|
|
508
508
|
|---|---|
|
|
509
|
-
| `kind` | `bar` (default), `column`, `stacked`, `line`, `area`, `combo`, `scatter`, `bubble`, `donut`, `pie`, `gauge`, `funnel`, `radar`, `gantt`, `pyramid` or `
|
|
509
|
+
| `kind` | `bar` (default), `column`, `stacked`, `line`, `area`, `combo`, `scatter`, `bubble`, `donut`, `pie`, `gauge`, `funnel`, `radar`, `gantt`, `pyramid`, `polar`, `range`, `boxplot` or `stock` |
|
|
510
510
|
| `link` | Drill-down: `{"page": 2, "items": {"P2_DEPTNO": "#deptno#"}}` makes every data point a link (see below) |
|
|
511
511
|
| `gauge` | For `gauge`: `{"min": 0, "max": 120, "warning": 80, "critical": 100}` (all optional) |
|
|
512
512
|
| `format_mask` | A number format mask for the values in labels, tips and the data table, e.g. `"FML999G990"` (see [number formats](14-globalization.md#number-formats)) |
|
|
@@ -528,6 +528,9 @@ Attributes:
|
|
|
528
528
|
| `gantt` | tasks over time | **label, start, end** (dates or timestamps; an empty end, or one equal to the start, is a milestone ◆), then optional columns **by name**: `progress` (0 to 100, the filled part of the bar), `task_id` and `depends_on` (the ids a task waits for: `3`, `3,4` or an array). A time axis in hours, days, weeks, months or years, a dashed line for now (in the session's time zone, like the timestamps the query returns), and elbow lines from the end of each predecessor to the start of the task. Rows without a start are left out |
|
|
529
529
|
| `pyramid` | levels of a hierarchy, or two groups compared per band | **one series**: a triangle cut into segments from the top (the first row) down, each segment's **area** in proportion to its value (≤ 8; more fold into "Other"). **Two series**: back-to-back bars (a population pyramid), the first series to the left, both on one scale; negative values count as their size |
|
|
530
530
|
| `polar` | values per period or direction (months, weekdays) | a polar area chart: **one equal sector per row** (up to 24) clockwise from 12 o'clock, the radius in proportion to the value on rings from zero; several series share a row's sector |
|
|
531
|
+
| `range` | a span per category (lowest and highest, from and to) | **low and high** columns (in either order): a floating column from one to the other; each further pair of columns is another range per row (up to four, with a legend). The axis doesn't have to start at zero |
|
|
532
|
+
| `boxplot` | the spread of values per group | **one value column with a row per observation** (the label repeats; the statistics are computed per label, in the order the labels first appear, like `percentile_cont`; empty values are left out), or **five columns** per row: minimum, first quartile, median, third quartile and maximum. A whisker from minimum to maximum, a box between the quartiles and a line at the median; the data table shows the five statistics (and the tip the number of values) |
|
|
533
|
+
| `stock` | prices over time | **open, high, low and close** columns in that order (any names): a candle per row, filled green when it closed at or above its opening and red when below, with a wick from low to high. The axis doesn't have to start at zero |
|
|
531
534
|
|
|
532
535
|
A stacked chart, a combination of columns and a line, and a scatter plot:
|
|
533
536
|
|
|
@@ -573,7 +576,7 @@ select initcap(job) as job,
|
|
|
573
576
|
from hr.emp group by job order by 1
|
|
574
577
|
```
|
|
575
578
|
|
|
576
|
-
Gantt, pyramid and
|
|
579
|
+
Gantt, pyramid, polar, range, box plot and stock charts (HR page 32 "Project plan"):
|
|
577
580
|
|
|
578
581
|
```sql
|
|
579
582
|
-- gantt: progress, task_id and depends_on by name; deptno only for the link
|
|
@@ -593,13 +596,25 @@ select b.band as "Salary",
|
|
|
593
596
|
select to_char(make_date(2000, m, 1), 'Mon') as month, count(e.empno) as "Hires"
|
|
594
597
|
from generate_series(1, 12) m left join hr.emp e on extract(month from e.hiredate) = m
|
|
595
598
|
group by m order by m
|
|
599
|
+
|
|
600
|
+
-- range: lowest and highest salary per department (deptno only for the link)
|
|
601
|
+
select d.dname as "Department", min(e.sal) as "Lowest", max(e.sal) as "Highest", d.deptno
|
|
602
|
+
from hr.dept d join hr.emp e on e.deptno = d.deptno group by d.deptno, d.dname order by d.dname
|
|
603
|
+
|
|
604
|
+
-- box plot: one row per employee; a box per job
|
|
605
|
+
select e.job as "Job", e.sal as "Salary" from hr.emp e where e.active order by e.job
|
|
606
|
+
|
|
607
|
+
-- stock: open, high, low and close per day
|
|
608
|
+
select to_char(day, 'DD Mon') as "Day", open as "Open", high as "High", low as "Low", close as "Close"
|
|
609
|
+
from sales.share_price order by day
|
|
596
610
|
```
|
|
597
611
|
|
|
598
612
|
A Gantt chart reads dates as their wall clock (a `timestamptz` in the session's time zone), shows a
|
|
599
613
|
time only when it is not midnight, and has its own data table (label, start, end, progress,
|
|
600
614
|
dependencies). Its rows count toward the chart's row limit (`max_rows`, default 1000).
|
|
601
615
|
|
|
602
|
-
Up to 8 series; two or more get a legend.
|
|
616
|
+
Up to 8 series; two or more get a legend. When an axis has many labels, only some are shown, and in a
|
|
617
|
+
narrow chart (a region of a few columns, a phone) every other one of those. Every chart has hover/focus **tooltips** and a
|
|
603
618
|
**Data table** toggle (the accessible alternative). Colours come from a palette checked for
|
|
604
619
|
colour-vision deficiency, in light and dark mode; the gauge's status colours are reserved for
|
|
605
620
|
status and always come with an icon and a label. Charts resize with the screen.
|
|
@@ -619,7 +634,8 @@ Columns that only the link refers to (here `deptno`) are **not drawn** as a seri
|
|
|
619
634
|
can return a key next to the label. What links: bars, columns and stacked segments (per series),
|
|
620
635
|
line and area points, scatter dots and bubbles, gauge dials, funnel stages, radar axis labels, pie
|
|
621
636
|
and donut slices and their legend entries (not "Other"), Gantt bars and milestones (the whole row:
|
|
622
|
-
`#series#` is empty), pyramid segments and bars,
|
|
637
|
+
`#series#` is empty), pyramid segments and bars, polar sectors and their labels, range columns (per pair of
|
|
638
|
+
series when there are several), boxes (the first row of their label) and candles (the whole row). The marks are for the mouse; from the
|
|
623
639
|
keyboard the **data table** has the same links (the labels, or each value when there are several
|
|
624
640
|
series), and so do the radar and polar labels and the donut and pyramid legends.
|
|
625
641
|
|
|
@@ -827,6 +827,7 @@ application ask someone to approve, reject or complete something, and act on the
|
|
|
827
827
|
| Business administrator (role) | Sees every task of this definition, delegates and cancels them |
|
|
828
828
|
| The person who requested it may complete it | Off by default: nobody approves their own request |
|
|
829
829
|
| Priority, Due in | 1 (urgent) – 5 (low); e.g. `2 days`. Overdue tasks are marked |
|
|
830
|
+
| When overdue, Maximum renewals, Escalation role | The expiration policy ([below](#overdue-tasks-expire-renew-escalate)); empty: overdue tasks stay open |
|
|
830
831
|
| Details page, Details item | The subject links to this page, setting the item to the record key |
|
|
831
832
|
| On completion (SQL) | Runs as the application's role when the task is approved, rejected or completed (below) |
|
|
832
833
|
|
|
@@ -858,6 +859,14 @@ user may do:
|
|
|
858
859
|
|
|
859
860
|
Every step is in the task's history.
|
|
860
861
|
|
|
862
|
+
**Vacation rules** (APEX: vacation rules): a task list of *my tasks* has a **Vacation rule** section where users name
|
|
863
|
+
the user who stands in for them, from one day until another (at most a year ahead). While the rule is active, the
|
|
864
|
+
stand-in may act on, claim, release and delegate the tasks the user may act on as a **named owner** (the users given
|
|
865
|
+
to `meta.create_task`) or as the **actual owner**, and sees them in their own task list; the decision is recorded under
|
|
866
|
+
the stand-in's name. The rule is checked on every request, so the stand-in's access ends with it. Owners by **role**
|
|
867
|
+
are not passed on (the role's other members are there for that). From SQL: `meta.set_vacation_rule(delegate, from,
|
|
868
|
+
until)`, `meta.clear_vacation_rule()` and `meta.vacation_rule()` (the signed-in user's own rule).
|
|
869
|
+
|
|
861
870
|
**4. On completion**, the definition's SQL runs **as the application's role, in the same
|
|
862
871
|
transaction** as the decision, with these binds: `:TASK_ID`, `:DETAIL_PK`, `:OUTCOME`
|
|
863
872
|
(`APPROVED`, `REJECTED` or `COMPLETED`), `:COMMENT`, `:APPROVER`, `:INITIATOR`, and the task
|
|
@@ -872,6 +881,22 @@ When a record is decided somewhere else (for example with buttons on its own pag
|
|
|
872
881
|
open tasks so they don't linger: `select meta.close_tasks('EXPENSE_APPROVAL', :P5_ID::text,
|
|
873
882
|
'approved')` (no completion SQL runs).
|
|
874
883
|
|
|
884
|
+
#### Overdue tasks: expire, renew, escalate
|
|
885
|
+
|
|
886
|
+
A task definition with *Due in* can say what happens to a task that is still open after its due date (APEX:
|
|
887
|
+
expiration policy). The server checks every minute:
|
|
888
|
+
|
|
889
|
+
| When overdue | What happens |
|
|
890
|
+
|---|---|
|
|
891
|
+
| (empty) | Nothing: the task stays open and is marked overdue |
|
|
892
|
+
| `expire` | The task ends with the state **expired** and no outcome; the completion SQL doesn't run |
|
|
893
|
+
| `renew` | The due date moves on by *Due in*, up to *Maximum renewals* times (default 3); then it expires |
|
|
894
|
+
| `escalate` | Once: the *Escalation role* becomes a potential owner, the priority 1, the task unassigned (its actual owner loses it) with a new due date; overdue again, it expires |
|
|
895
|
+
|
|
896
|
+
Each step is in the task's history, by `system`. A [workflow](#workflows) waiting for a task that expires goes on with
|
|
897
|
+
the outcome `expired` (`"next": {"approved": "…", "expired": "…"}`); without an `expired` branch it ends, like a
|
|
898
|
+
workflow whose task is cancelled.
|
|
899
|
+
|
|
875
900
|
**SQL API** (application code; `meta.app_user()` is the acting user):
|
|
876
901
|
|
|
877
902
|
| Function | |
|
|
@@ -889,7 +914,8 @@ reminds owners of overdue tasks; or put a task list on the home page.
|
|
|
889
914
|
|
|
890
915
|
**Example:** in the HR sample application, a leave request creates a `LEAVE_APPROVAL` task for the
|
|
891
916
|
employee's manager; *My tasks* (page 14) approves or rejects it through `hr.decide_leave`, the same
|
|
892
|
-
function as the leave request page's buttons, and a request decided there closes its task.
|
|
917
|
+
function as the leave request page's buttons, and a request decided there closes its task. A leave request nobody
|
|
918
|
+
decides on within two days escalates to the administrators; managers going on holiday set a vacation rule on page 14.
|
|
893
919
|
|
|
894
920
|
## Workflows
|
|
895
921
|
|
|
@@ -64,7 +64,7 @@ src/
|
|
|
64
64
|
sqlscript.ts SQL scripts: splitScript() (statements, line numbers, psql commands), runScript() (stop/continue, transaction, savepoints)
|
|
65
65
|
quicksql.ts Quick SQL: shorthand parser and PostgreSQL DDL generator (unit tested)
|
|
66
66
|
xlsx.ts Excel writer for report downloads and Unload Data (typed cells, streamed through fflate's Zip)
|
|
67
|
-
automations.ts cron parser, next run in a time zone, scheduler, running automations (the actions run
|
|
67
|
+
automations.ts cron parser, next run in a time zone, scheduler (also meta.task_expire_tick, 094), running automations (the actions run
|
|
68
68
|
in PL/pgSQL: meta.automation_execute, shared with meta.run_automation; migration 044)
|
|
69
69
|
html.ts auto-escaping html`` templates
|
|
70
70
|
richtext.ts rich text and Markdown items: allow-list HTML sanitiser, Markdown renderer
|
|
@@ -119,7 +119,7 @@ src/
|
|
|
119
119
|
(report.ts: paging with row ranges and max_rows, keyset paging (keysetPlan, seekCondition, signed r<id>_k), pagerNav, streamed CSV/Excel downloads with a cursor;
|
|
120
120
|
items.ts: lovOptions, searchLov/lovLookup for popup LOVs, served by POST /a/:alias/:page/lov/:item/search in routes.ts)
|
|
121
121
|
region-cache.ts region caching (keys per scope, CSRF placeholder, invalidation on submit) and lazy regions (GET …/region/:id is in routes.ts)
|
|
122
|
-
charts.ts server-rendered charts (SVG and CSS classes): bar … radar, gauges, Gantt (time axis, dependencies), pyramid, polar, drill-down marks, data table
|
|
122
|
+
charts.ts server-rendered charts (SVG and CSS classes): bar … radar, gauges, Gantt (time axis, dependencies), pyramid, polar, range, box plot (quantile, boxes), stock, drill-down marks, data table
|
|
123
123
|
calendar.ts calendar region: month/week/day/list views, create links, drag and drop (moveEvent, moveCalendarEvent;
|
|
124
124
|
the route POST …/calendar/:id/move is in routes.ts)
|
|
125
125
|
links.ts page links with checksums; fillItems() fills #column# in link items
|
|
@@ -143,7 +143,7 @@ src/
|
|
|
143
143
|
template-components.ts template components: template language (allow-list, directives, escaping), plug-in files, report column templates
|
|
144
144
|
builtin-components.ts built-in template components (ut_avatar, ut_badge, ut_comments, ut_media_list, ut_metric_card, ut_timeline)
|
|
145
145
|
template-region.ts template_component region
|
|
146
|
-
tasks.ts task list region and task actions (approvals)
|
|
146
|
+
tasks.ts task list region and task actions (approvals); (094) the vacation rule panel and route
|
|
147
147
|
data-reporter.ts Data Reporter region (migration 057): sources from the region's config, checkDef (offered columns, whitelists),
|
|
148
148
|
reportQuery/chartQuery, the list and editor (GET form), save/delete routes (meta.save_data_report)
|
|
149
149
|
workflows.ts workflow console region and its actions
|
|
@@ -187,6 +187,8 @@ src/
|
|
|
187
187
|
forms.ts generic component property form (lookups, render, save)
|
|
188
188
|
backups.ts Application → Backups (migration 082): list, back up now, download, restore (replaceApp), keep N;
|
|
189
189
|
backupTick() for the scheduler's daily backups of changed applications
|
|
190
|
+
workspace-backups.ts Workspace utilities → Manage backups (sprint 62): the backups of every application of the current
|
|
191
|
+
workspace, back them all up (only the changed ones by default)
|
|
190
192
|
availability.ts Application → Availability (migration 083): status, message, users, build status (Run only is
|
|
191
193
|
enforced by locks.ts blockingLock); availabilityBadge() in the application header
|
|
192
194
|
feedback.ts Application → Feedback (migration 084): the setting, the list with filters, status and answers
|
|
@@ -213,6 +215,8 @@ src/
|
|
|
213
215
|
search.ts app search, "where used" (appEntries, search, whereUsed, usedInPanel)
|
|
214
216
|
advisor.ts Advisor: EXPLAIN every SQL fragment, reference checks, plpgsql_check
|
|
215
217
|
ddl-tools.ts SQL Workshop → DDL and Compare (src/ddl.ts)
|
|
218
|
+
sql-utilities.ts SQL Workshop → Utilities (sprint 62): the tools' tiles, OBJECT_REPORTS (fixed catalogue SQL over the
|
|
219
|
+
connection's usable schemas), About Database, Database Monitor (administrators); read only, with a timeout
|
|
216
220
|
login-page.ts Application settings → Login page and Forgot password; Create a login page (page 9999)
|
|
217
221
|
top-sql.ts Top SQL per app role from pg_stat_statements
|
|
218
222
|
diagnostics.ts Activity → Debug messages (level, list, one request's entries, purge); Workspace utilities →
|
|
@@ -240,6 +244,8 @@ src/
|
|
|
240
244
|
workspaces.ts workspaces (064): loadWorkspaces/appAllowed (checked in ui.ts developer() for every /apps/:id and /pages/:pid
|
|
241
245
|
request), the current workspace (session state __WS), placeApp, the switcher, Workspace utilities → Workspaces;
|
|
242
246
|
(090) isolation and the workspace's database roles, workshopDb (the SQL Workshop's connection)
|
|
247
|
+
(093) workspace preferences (sql_workshop: checked in ui.ts developer() for /builder/sql…;
|
|
248
|
+
rest_services: checked in runtime/rest.ts) and extension links (the rail's Extensions menu in shell())
|
|
243
249
|
locks.ts page and application locks (blockingLock, checked in ui.ts developer() for every builder POST; appOfPath), developer comments, administrators
|
|
244
250
|
blueprints.ts Create → From a blueprint: list, JSON editor, AI draft, review (signed with the session), create in one transaction
|
|
245
251
|
ai-builder.ts App Builder AI (migration 062): the builder's AI service (meta.builder_ai), SQL Workshop → AI (SQL from a
|
|
@@ -281,7 +287,7 @@ test/
|
|
|
281
287
|
page-logic.test.ts download, chain (background jobs) and workflow processes, function/app branches, dialog_closed (HR page 28)
|
|
282
288
|
code-editor.test.ts code editor: completions scoped to the app's role, the check, marked fields
|
|
283
289
|
builder-home.test.ts App Builder home: search, sort, views, Recent, Create/Import pages, dashboard, utilities
|
|
284
|
-
charts.test.ts chart markup per kind (geometry as classes), gauges, Gantt time axis and dependencies, pyramid, polar, drill-down links
|
|
290
|
+
charts.test.ts chart markup per kind (geometry as classes), gauges, Gantt time axis and dependencies, pyramid, polar, range, box plot, stock, drill-down links
|
|
285
291
|
calendar.test.ts calendar views, create links, moving events (pure and over HTTP)
|
|
286
292
|
rest-sources.test.ts REST data sources, web credentials, SSRF checks, invoke_api (mock service + HR page 23)
|
|
287
293
|
workflow-invoke.test.ts workflow invoke_api steps: the call between transactions, faults, retry, lease, Advisor, export (mock service)
|