ekwo-os 0.7.0 → 0.8.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/dist/assets/expected-objects.json +117 -2
- package/dist/assets/migrations/20260922143000_a_version_anybody_signed_in_may_read.sql +52 -0
- package/dist/assets/migrations/20260922144500_a_balance_sheet_without_knowing_the_pack.sql +117 -0
- package/dist/assets/migrations/20260922160000_a_key_reaches_the_api.sql +265 -0
- package/dist/assets/migrations/20260922161500_the_version_answers_a_key_as_well.sql +42 -0
- package/dist/assets/migrations/20260922162500_reference_data_for_a_caller_this_installation_knows.sql +127 -0
- package/dist/assets/migrations/20260922171000_a_key_is_presented_in_a_read_only_transaction.sql +82 -0
- package/dist/assets/migrations/20260923093000_schema_version_0_8_0.sql +42 -0
- package/dist/assets/modules/assets/supabase/migrations/20260922162600_assets_reference_for_a_known_caller.sql +24 -0
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +40 -0
- package/dist/doctor.js.map +1 -1
- package/dist/schema.d.ts +1 -1
- package/dist/schema.js +1 -1
- package/package.json +3 -3
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"schemaVersion": "0.
|
|
3
|
-
"migration": "
|
|
2
|
+
"schemaVersion": "0.8.0",
|
|
3
|
+
"migration": "20260923093000",
|
|
4
4
|
"socle": {
|
|
5
5
|
"schema": "public",
|
|
6
6
|
"tables": [
|
|
@@ -3743,6 +3743,10 @@
|
|
|
3743
3743
|
"name": "amount_text_format",
|
|
3744
3744
|
"arguments": "p_rounding money_rounding"
|
|
3745
3745
|
},
|
|
3746
|
+
{
|
|
3747
|
+
"name": "api_key_company",
|
|
3748
|
+
"arguments": ""
|
|
3749
|
+
},
|
|
3746
3750
|
{
|
|
3747
3751
|
"name": "assert_may_close_year",
|
|
3748
3752
|
"arguments": ""
|
|
@@ -3931,6 +3935,10 @@
|
|
|
3931
3935
|
"name": "declaration_period_start",
|
|
3932
3936
|
"arguments": "p_period declaration_period, p_day date"
|
|
3933
3937
|
},
|
|
3938
|
+
{
|
|
3939
|
+
"name": "default_statement_code",
|
|
3940
|
+
"arguments": "p_company_id uuid, p_kind text, p_at date"
|
|
3941
|
+
},
|
|
3934
3942
|
{
|
|
3935
3943
|
"name": "disable_module",
|
|
3936
3944
|
"arguments": "p_company_id uuid, p_code text"
|
|
@@ -3999,6 +4007,10 @@
|
|
|
3999
4007
|
"name": "ec_sales_list",
|
|
4000
4008
|
"arguments": "p_company_id uuid, p_from date, p_to date, p_report_code text"
|
|
4001
4009
|
},
|
|
4010
|
+
{
|
|
4011
|
+
"name": "ekwo_pre_request",
|
|
4012
|
+
"arguments": ""
|
|
4013
|
+
},
|
|
4002
4014
|
{
|
|
4003
4015
|
"name": "ekwo_schema_version",
|
|
4004
4016
|
"arguments": ""
|
|
@@ -4095,6 +4107,10 @@
|
|
|
4095
4107
|
"name": "financial_statement",
|
|
4096
4108
|
"arguments": "p_company_id uuid, p_statement_code text, p_from date, p_to date"
|
|
4097
4109
|
},
|
|
4110
|
+
{
|
|
4111
|
+
"name": "financial_statement_of_kind",
|
|
4112
|
+
"arguments": "p_company_id uuid, p_kind text, p_from date, p_to date"
|
|
4113
|
+
},
|
|
4098
4114
|
{
|
|
4099
4115
|
"name": "fiscal_year_at",
|
|
4100
4116
|
"arguments": "p_company_id uuid, p_date date"
|
|
@@ -4151,6 +4167,10 @@
|
|
|
4151
4167
|
"name": "install_country_template",
|
|
4152
4168
|
"arguments": "p_company_id uuid, p_country character, p_language character, p_chart_code text"
|
|
4153
4169
|
},
|
|
4170
|
+
{
|
|
4171
|
+
"name": "installed_schema_version",
|
|
4172
|
+
"arguments": ""
|
|
4173
|
+
},
|
|
4154
4174
|
{
|
|
4155
4175
|
"name": "instance_has_no_admin",
|
|
4156
4176
|
"arguments": ""
|
|
@@ -4183,6 +4203,10 @@
|
|
|
4183
4203
|
"name": "is_instance_admin",
|
|
4184
4204
|
"arguments": ""
|
|
4185
4205
|
},
|
|
4206
|
+
{
|
|
4207
|
+
"name": "is_known_caller",
|
|
4208
|
+
"arguments": ""
|
|
4209
|
+
},
|
|
4186
4210
|
{
|
|
4187
4211
|
"name": "label_for",
|
|
4188
4212
|
"arguments": "p_name text, p_i18n jsonb, p_languages text[]"
|
|
@@ -4315,6 +4339,10 @@
|
|
|
4315
4339
|
"name": "prepare_filing",
|
|
4316
4340
|
"arguments": "p_company_id uuid, p_from date, p_to date, p_report_code text"
|
|
4317
4341
|
},
|
|
4342
|
+
{
|
|
4343
|
+
"name": "present_api_key",
|
|
4344
|
+
"arguments": "p_secret text"
|
|
4345
|
+
},
|
|
4318
4346
|
{
|
|
4319
4347
|
"name": "purge_audit_log",
|
|
4320
4348
|
"arguments": "p_before date"
|
|
@@ -6817,6 +6845,19 @@
|
|
|
6817
6845
|
"execute"
|
|
6818
6846
|
]
|
|
6819
6847
|
},
|
|
6848
|
+
{
|
|
6849
|
+
"name": "api_key_company",
|
|
6850
|
+
"arguments": "",
|
|
6851
|
+
"anon": [
|
|
6852
|
+
"execute"
|
|
6853
|
+
],
|
|
6854
|
+
"authenticated": [
|
|
6855
|
+
"execute"
|
|
6856
|
+
],
|
|
6857
|
+
"service_role": [
|
|
6858
|
+
"execute"
|
|
6859
|
+
]
|
|
6860
|
+
},
|
|
6820
6861
|
{
|
|
6821
6862
|
"name": "assert_may_close_year",
|
|
6822
6863
|
"arguments": "",
|
|
@@ -7281,6 +7322,17 @@
|
|
|
7281
7322
|
"execute"
|
|
7282
7323
|
]
|
|
7283
7324
|
},
|
|
7325
|
+
{
|
|
7326
|
+
"name": "default_statement_code",
|
|
7327
|
+
"arguments": "p_company_id uuid, p_kind text, p_at date",
|
|
7328
|
+
"anon": [],
|
|
7329
|
+
"authenticated": [
|
|
7330
|
+
"execute"
|
|
7331
|
+
],
|
|
7332
|
+
"service_role": [
|
|
7333
|
+
"execute"
|
|
7334
|
+
]
|
|
7335
|
+
},
|
|
7284
7336
|
{
|
|
7285
7337
|
"name": "disable_module",
|
|
7286
7338
|
"arguments": "p_company_id uuid, p_code text",
|
|
@@ -7441,6 +7493,19 @@
|
|
|
7441
7493
|
"execute"
|
|
7442
7494
|
]
|
|
7443
7495
|
},
|
|
7496
|
+
{
|
|
7497
|
+
"name": "ekwo_pre_request",
|
|
7498
|
+
"arguments": "",
|
|
7499
|
+
"anon": [
|
|
7500
|
+
"execute"
|
|
7501
|
+
],
|
|
7502
|
+
"authenticated": [
|
|
7503
|
+
"execute"
|
|
7504
|
+
],
|
|
7505
|
+
"service_role": [
|
|
7506
|
+
"execute"
|
|
7507
|
+
]
|
|
7508
|
+
},
|
|
7444
7509
|
{
|
|
7445
7510
|
"name": "ekwo_schema_version",
|
|
7446
7511
|
"arguments": "",
|
|
@@ -7684,6 +7749,17 @@
|
|
|
7684
7749
|
"execute"
|
|
7685
7750
|
]
|
|
7686
7751
|
},
|
|
7752
|
+
{
|
|
7753
|
+
"name": "financial_statement_of_kind",
|
|
7754
|
+
"arguments": "p_company_id uuid, p_kind text, p_from date, p_to date",
|
|
7755
|
+
"anon": [],
|
|
7756
|
+
"authenticated": [
|
|
7757
|
+
"execute"
|
|
7758
|
+
],
|
|
7759
|
+
"service_role": [
|
|
7760
|
+
"execute"
|
|
7761
|
+
]
|
|
7762
|
+
},
|
|
7687
7763
|
{
|
|
7688
7764
|
"name": "fiscal_year_at",
|
|
7689
7765
|
"arguments": "p_company_id uuid, p_date date",
|
|
@@ -7834,6 +7910,19 @@
|
|
|
7834
7910
|
"execute"
|
|
7835
7911
|
]
|
|
7836
7912
|
},
|
|
7913
|
+
{
|
|
7914
|
+
"name": "installed_schema_version",
|
|
7915
|
+
"arguments": "",
|
|
7916
|
+
"anon": [
|
|
7917
|
+
"execute"
|
|
7918
|
+
],
|
|
7919
|
+
"authenticated": [
|
|
7920
|
+
"execute"
|
|
7921
|
+
],
|
|
7922
|
+
"service_role": [
|
|
7923
|
+
"execute"
|
|
7924
|
+
]
|
|
7925
|
+
},
|
|
7837
7926
|
{
|
|
7838
7927
|
"name": "instance_has_no_admin",
|
|
7839
7928
|
"arguments": "",
|
|
@@ -7932,6 +8021,19 @@
|
|
|
7932
8021
|
"execute"
|
|
7933
8022
|
]
|
|
7934
8023
|
},
|
|
8024
|
+
{
|
|
8025
|
+
"name": "is_known_caller",
|
|
8026
|
+
"arguments": "",
|
|
8027
|
+
"anon": [
|
|
8028
|
+
"execute"
|
|
8029
|
+
],
|
|
8030
|
+
"authenticated": [
|
|
8031
|
+
"execute"
|
|
8032
|
+
],
|
|
8033
|
+
"service_role": [
|
|
8034
|
+
"execute"
|
|
8035
|
+
]
|
|
8036
|
+
},
|
|
7935
8037
|
{
|
|
7936
8038
|
"name": "label_for",
|
|
7937
8039
|
"arguments": "p_name text, p_i18n jsonb, p_languages text[]",
|
|
@@ -8294,6 +8396,19 @@
|
|
|
8294
8396
|
"execute"
|
|
8295
8397
|
]
|
|
8296
8398
|
},
|
|
8399
|
+
{
|
|
8400
|
+
"name": "present_api_key",
|
|
8401
|
+
"arguments": "p_secret text",
|
|
8402
|
+
"anon": [
|
|
8403
|
+
"execute"
|
|
8404
|
+
],
|
|
8405
|
+
"authenticated": [
|
|
8406
|
+
"execute"
|
|
8407
|
+
],
|
|
8408
|
+
"service_role": [
|
|
8409
|
+
"execute"
|
|
8410
|
+
]
|
|
8411
|
+
},
|
|
8297
8412
|
{
|
|
8298
8413
|
"name": "purge_audit_log",
|
|
8299
8414
|
"arguments": "p_before date",
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
-- Ekwo OS — the version of the schema, for somebody who is on no company yet.
|
|
2
|
+
--
|
|
3
|
+
-- A client of this schema has one question to ask before it draws anything:
|
|
4
|
+
-- is this installation new enough for the code I ship? The answer is
|
|
5
|
+
-- `instance.schema_version`, and the policy on that table admits members of
|
|
6
|
+
-- at least one company and instance administrators — for the reason written
|
|
7
|
+
-- in `20260911140000`: self sign-up is on by default on a Supabase project,
|
|
8
|
+
-- so a signed-in stranger is ordinary and the organisation's name, its country
|
|
9
|
+
-- and the day it was installed are not theirs to read.
|
|
10
|
+
--
|
|
11
|
+
-- A freshly created account is exactly that stranger. It signs in, reads no
|
|
12
|
+
-- row, and the client cannot tell an instance behind its schema from one
|
|
13
|
+
-- whose row it was never allowed to see. Both are silence, and the two call
|
|
14
|
+
-- for opposite behaviour: print `ekwo migrate`, or say nothing and carry on.
|
|
15
|
+
-- A web application meets this on its first screen, with an account whose
|
|
16
|
+
-- invitation has not arrived yet.
|
|
17
|
+
--
|
|
18
|
+
-- So the version leaves the table and becomes a question of its own.
|
|
19
|
+
-- `installed_schema_version()` is definer — it reads the singleton row past a
|
|
20
|
+
-- policy that was written about the rest of it — and it returns two fields
|
|
21
|
+
-- and no others: the version the migrations wrote, and the edition, which is
|
|
22
|
+
-- `community` or `cloud` and gates nothing anywhere in this repository.
|
|
23
|
+
-- Whoever the caller is, what they learn is what release this software is at.
|
|
24
|
+
-- Nothing about the customer comes with it.
|
|
25
|
+
--
|
|
26
|
+
-- **`anon` does not get it**, and the exception is not worth making. Decision
|
|
27
|
+
-- 0002 keeps the anonymous surface closed, and the list of what `anon` may
|
|
28
|
+
-- execute is the policy helpers, which answer about `auth.uid()` and therefore
|
|
29
|
+
-- say nothing, plus `shared_document()`, which somebody was handed a link to.
|
|
30
|
+
-- The version is not in that shape: nobody asks it before signing in — the
|
|
31
|
+
-- client asks it *after*, which is the moment the old answer went missing —
|
|
32
|
+
-- and granting it would hand an unauthenticated scanner the exact release an
|
|
33
|
+
-- installation runs, for a convenience nothing needs. A reader who needs it
|
|
34
|
+
-- signs in first.
|
|
35
|
+
|
|
36
|
+
create or replace function installed_schema_version()
|
|
37
|
+
returns table (schema_version text, edition text)
|
|
38
|
+
language sql
|
|
39
|
+
stable
|
|
40
|
+
security definer
|
|
41
|
+
set search_path = public, pg_temp
|
|
42
|
+
as $$
|
|
43
|
+
select i.schema_version, i.edition::text from instance i where i.id = 1;
|
|
44
|
+
$$;
|
|
45
|
+
|
|
46
|
+
comment on function installed_schema_version() is
|
|
47
|
+
'The schema version this installation runs, and its edition. Definer, so a signed-in account that is on no company yet can still tell an instance behind its schema from one it may not read the row of — which is the same silence otherwise. Nothing else of the instance row comes with it.';
|
|
48
|
+
|
|
49
|
+
revoke execute on all functions in schema public from public;
|
|
50
|
+
|
|
51
|
+
revoke execute on function installed_schema_version() from public, anon;
|
|
52
|
+
grant execute on function installed_schema_version() to authenticated, service_role;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
-- Ekwo OS — asking for a balance sheet without knowing which pack answers.
|
|
2
|
+
--
|
|
3
|
+
-- `financial_statement()` takes `p_statement_code`, and a code belongs to a
|
|
4
|
+
-- country pack: `BE-BNB-ABBR-BS`, `FR-2050`, the generic `IFRS-SME-BS`. A
|
|
5
|
+
-- client that knows which company it is looking at does not know that string,
|
|
6
|
+
-- and it must not learn it — writing `FR-2050` into an application is writing
|
|
7
|
+
-- a country into code, one screen at a time, which is the thing
|
|
8
|
+
-- `docs/decisions/0025` exists to stop.
|
|
9
|
+
--
|
|
10
|
+
-- `available_statements(company, at)` has been the way out since the day the
|
|
11
|
+
-- statements landed: it gives every scheme that company may ask for, with its
|
|
12
|
+
-- kind and whether its chart declares it. What was missing is the step after
|
|
13
|
+
-- it — going from *a balance sheet* to the one statement that answers, and
|
|
14
|
+
-- doing it the same way twice. Every caller that wanted one wrote its own
|
|
15
|
+
-- choice: take the first row, prefer `is_default`, prefer the country over the
|
|
16
|
+
-- generic. Three readers, three orders, and the day a pack carries two balance
|
|
17
|
+
-- sheets they disagree about which is the company's.
|
|
18
|
+
--
|
|
19
|
+
-- Two functions, and no new rule about accounting:
|
|
20
|
+
--
|
|
21
|
+
-- `default_statement_code(company, kind, at)` — the one scheme of that kind
|
|
22
|
+
-- this company reports on. The order is the pack's own preferences,
|
|
23
|
+
-- stated once: a statement the company's chart declares
|
|
24
|
+
-- (`chart_templates.statements`, which is what `is_default` marks) comes
|
|
25
|
+
-- first; then one of the company's country, because a national scheme is
|
|
26
|
+
-- what an administration reads; then the generic framework, which fits
|
|
27
|
+
-- any chart and is the fallback and never the first answer. `code`
|
|
28
|
+
-- settles a tie, so the answer does not depend on the order rows were
|
|
29
|
+
-- loaded in.
|
|
30
|
+
--
|
|
31
|
+
-- `financial_statement_of_kind(company, kind, from, to)` — the same table
|
|
32
|
+
-- `financial_statement()` returns, resolved that way, with the code it
|
|
33
|
+
-- chose in the first column. The code comes back because a reader has to
|
|
34
|
+
-- be able to say which scheme it is printing, and because the next call
|
|
35
|
+
-- — `unmapped_accounts()`, an XBRL export — takes the code.
|
|
36
|
+
--
|
|
37
|
+
-- The kind is the one the schema already has: `balance_sheet`,
|
|
38
|
+
-- `income_statement`, `allocation`, `cash_flow` — the vocabulary of
|
|
39
|
+
-- `statement_templates.kind`, not a new one. A company with no statement of
|
|
40
|
+
-- the kind asked for is told so, and told what it does have; a company that
|
|
41
|
+
-- installed no pack at all has the generic framework and so has both of the
|
|
42
|
+
-- two that are produced.
|
|
43
|
+
--
|
|
44
|
+
-- The date the validity is read at is `p_to`: a statement is the one that was
|
|
45
|
+
-- in force at the end of the period being reported, not the one in force
|
|
46
|
+
-- today. A scheme replaced last month still prints last year.
|
|
47
|
+
|
|
48
|
+
create or replace function default_statement_code(
|
|
49
|
+
p_company_id uuid,
|
|
50
|
+
p_kind text,
|
|
51
|
+
p_at date default null
|
|
52
|
+
)
|
|
53
|
+
returns text
|
|
54
|
+
language sql
|
|
55
|
+
stable
|
|
56
|
+
as $$
|
|
57
|
+
select s.code
|
|
58
|
+
from available_statements(p_company_id, p_at) s
|
|
59
|
+
where s.kind = p_kind
|
|
60
|
+
order by s.is_default desc, (s.country is null), s.code
|
|
61
|
+
limit 1;
|
|
62
|
+
$$;
|
|
63
|
+
|
|
64
|
+
comment on function default_statement_code(uuid, text, date) is
|
|
65
|
+
'The statement of a kind this company reports on: one its chart declares, else one of its country, else the generic framework. Null when it has none of that kind. The one place that choice is made, so two readers cannot disagree about which balance sheet is the company''s.';
|
|
66
|
+
|
|
67
|
+
create or replace function financial_statement_of_kind(
|
|
68
|
+
p_company_id uuid,
|
|
69
|
+
p_kind text,
|
|
70
|
+
p_from date,
|
|
71
|
+
p_to date
|
|
72
|
+
)
|
|
73
|
+
returns table (
|
|
74
|
+
statement_code text,
|
|
75
|
+
line_code text,
|
|
76
|
+
parent_code text,
|
|
77
|
+
name text,
|
|
78
|
+
sequence integer,
|
|
79
|
+
is_total boolean,
|
|
80
|
+
amount numeric,
|
|
81
|
+
xbrl_element text
|
|
82
|
+
)
|
|
83
|
+
language plpgsql
|
|
84
|
+
stable
|
|
85
|
+
as $$
|
|
86
|
+
declare
|
|
87
|
+
v_code text;
|
|
88
|
+
v_kinds text;
|
|
89
|
+
begin
|
|
90
|
+
if not exists (select 1 from companies c where c.id = p_company_id) then
|
|
91
|
+
raise exception 'unknown_company: %', p_company_id;
|
|
92
|
+
end if;
|
|
93
|
+
|
|
94
|
+
v_code := default_statement_code(p_company_id, p_kind, p_to);
|
|
95
|
+
if v_code is null then
|
|
96
|
+
select string_agg(distinct s.kind, ', ' order by s.kind) into v_kinds
|
|
97
|
+
from available_statements(p_company_id, p_to) s;
|
|
98
|
+
raise exception 'unknown_statement: this company reports no % — it reports %. available_statements() names each one by code.',
|
|
99
|
+
p_kind, coalesce(v_kinds, 'nothing');
|
|
100
|
+
end if;
|
|
101
|
+
|
|
102
|
+
return query
|
|
103
|
+
select v_code, f.line_code, f.parent_code, f.name, f.sequence,
|
|
104
|
+
f.is_total, f.amount, f.xbrl_element
|
|
105
|
+
from financial_statement(p_company_id, v_code, p_from, p_to) f;
|
|
106
|
+
end;
|
|
107
|
+
$$;
|
|
108
|
+
|
|
109
|
+
comment on function financial_statement_of_kind(uuid, text, date, date) is
|
|
110
|
+
'One financial statement of a company by kind — balance_sheet, income_statement, allocation, cash_flow — for a caller that does not know which scheme its country pack carries. Resolves through default_statement_code() at the end date of the period, then answers as financial_statement() does, with the code it chose in the first column.';
|
|
111
|
+
|
|
112
|
+
revoke execute on all functions in schema public from public;
|
|
113
|
+
|
|
114
|
+
revoke execute on function default_statement_code(uuid, text, date) from public, anon;
|
|
115
|
+
grant execute on function default_statement_code(uuid, text, date) to authenticated, service_role;
|
|
116
|
+
revoke execute on function financial_statement_of_kind(uuid, text, date, date) from public, anon;
|
|
117
|
+
grant execute on function financial_statement_of_kind(uuid, text, date, date) to authenticated, service_role;
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
-- Ekwo OS — a machine key that reaches the API, and not only a connection.
|
|
2
|
+
--
|
|
3
|
+
-- Decision 0006 wrote the limit down rather than hiding it: "because PostgREST
|
|
4
|
+
-- runs each request in its own transaction, a key is for a client holding a
|
|
5
|
+
-- connection". `use_api_key()` puts the key's fingerprint in `ekwo.api_key`
|
|
6
|
+
-- transaction-locally, and two REST calls are two transactions, so the key was
|
|
7
|
+
-- never presented when the work ran. Anything operated for somebody else — a
|
|
8
|
+
-- backup, a scheduled report, a script on a host with no psql — had to hold a
|
|
9
|
+
-- password of theirs or their `service_role` key. Both are worse than the key
|
|
10
|
+
-- the schema already mints.
|
|
11
|
+
--
|
|
12
|
+
-- The same decision left one question open, in as many words: "Deciding what
|
|
13
|
+
-- of `companies` a key may read is an open question, recorded rather than
|
|
14
|
+
-- patched per function." This answers it.
|
|
15
|
+
--
|
|
16
|
+
-- ---------------------------------------------------------------------------
|
|
17
|
+
-- 1. The key travels in a header, and the transaction reads it
|
|
18
|
+
-- ---------------------------------------------------------------------------
|
|
19
|
+
--
|
|
20
|
+
-- PostgREST calls one function of our choosing at the start of every request's
|
|
21
|
+
-- transaction — `pgrst.db_pre_request` — which is exactly the place
|
|
22
|
+
-- `use_api_key()` was missing. `ekwo_pre_request()` reads
|
|
23
|
+
-- `X-Ekwo-Api-Key` off `request.headers` and presents the key. No header, no
|
|
24
|
+
-- effect: a request that carries none is the request it was before this
|
|
25
|
+
-- migration, down to the role it runs as.
|
|
26
|
+
--
|
|
27
|
+
-- The name of the header is ours and not `Authorization`: PostgREST reads the
|
|
28
|
+
-- role out of that one, and a value it cannot parse as a JWT fails the request
|
|
29
|
+
-- before any function of ours runs. Two doors, two names.
|
|
30
|
+
--
|
|
31
|
+
-- ---------------------------------------------------------------------------
|
|
32
|
+
-- 2. The role, which is the part that is not obvious
|
|
33
|
+
-- ---------------------------------------------------------------------------
|
|
34
|
+
--
|
|
35
|
+
-- A request carrying only the publishable key runs as `anon`, and `anon` holds
|
|
36
|
+
-- no privilege on any table of this schema — decision 0003, and
|
|
37
|
+
-- `tests/grants.test.ts` asserts it. Row level security never gets a chance to
|
|
38
|
+
-- decide: the grant refuses first. So presenting a key has to move the request
|
|
39
|
+
-- off `anon`, and `ekwo_pre_request()` does that, *after* the key has been
|
|
40
|
+
-- checked and never before:
|
|
41
|
+
--
|
|
42
|
+
-- set_config('role', 'authenticated', true)
|
|
43
|
+
--
|
|
44
|
+
-- Three things make that sound rather than clever.
|
|
45
|
+
--
|
|
46
|
+
-- **It is not a definer function.** PostgreSQL refuses `set role` inside
|
|
47
|
+
-- SECURITY DEFINER — "cannot set parameter role within security-definer
|
|
48
|
+
-- function" — so `ekwo_pre_request()` runs as its caller, and the privilege
|
|
49
|
+
-- check is the ordinary one: the session user is `authenticator`, which is a
|
|
50
|
+
-- member of `authenticated`, and that is what makes the switch legal. A role
|
|
51
|
+
-- that is a member of nothing is refused by the server, not by us.
|
|
52
|
+
--
|
|
53
|
+
-- **Nothing is reached before the key is proven.** `present_api_key()` raises
|
|
54
|
+
-- on a key that is unknown, withdrawn or expired, and a raise inside the
|
|
55
|
+
-- pre-request fails the whole request. The switch is on the line after it.
|
|
56
|
+
--
|
|
57
|
+
-- **`authenticated` is not a person.** `auth.uid()` stays null — a key is not
|
|
58
|
+
-- a session, which is the sentence decision 0006 opens with — so every policy
|
|
59
|
+
-- that asks for a signed-in user still answers no, and what the caller may do
|
|
60
|
+
-- is decided by `has_capability()`, which has answered for a key since the
|
|
61
|
+
-- keys landed. The role is the door; the capabilities are the rooms.
|
|
62
|
+
--
|
|
63
|
+
-- ---------------------------------------------------------------------------
|
|
64
|
+
-- 3. What a key is on: its own company
|
|
65
|
+
-- ---------------------------------------------------------------------------
|
|
66
|
+
--
|
|
67
|
+
-- Past the grants, five policies still refused, and they are the ones that ask
|
|
68
|
+
-- `is_company_member()` rather than a capability: the company row itself, its
|
|
69
|
+
-- members, which modules it has on, how often it files, its matching settings,
|
|
70
|
+
-- its audit trail. They are structural — a caller that cannot read
|
|
71
|
+
-- `companies` cannot export the company, cannot round at its currency and
|
|
72
|
+
-- cannot find its financial year — and none of them has a capability of its
|
|
73
|
+
-- own, by decision 0004: "no capability without something that can refuse on
|
|
74
|
+
-- it".
|
|
75
|
+
--
|
|
76
|
+
-- So the answer is written once, where the question is asked:
|
|
77
|
+
--
|
|
78
|
+
-- a key of a company is on that company.
|
|
79
|
+
--
|
|
80
|
+
-- `is_company_member()` says true for the company the presented key belongs
|
|
81
|
+
-- to, and every policy that asks it follows without being rewritten —
|
|
82
|
+
-- including `module_enabled()`, which is the same question for a module's
|
|
83
|
+
-- tables. A key is still narrower than the member who issued it: every
|
|
84
|
+
-- capability on it was one the issuer held, and every table that has a
|
|
85
|
+
-- capability keeps asking for it. What it gains is the handful of rows that
|
|
86
|
+
-- describe the company it was minted for, which is the company it can already
|
|
87
|
+
-- read the ledger of.
|
|
88
|
+
--
|
|
89
|
+
-- Widened deliberately and stated so a reviewer can object: whatever its
|
|
90
|
+
-- capabilities, a key reads its company's row, its members, its modules, its
|
|
91
|
+
-- filing periods, its matching settings and its audit trail — exactly what the
|
|
92
|
+
-- narrowest member of that company reads. It reads nothing of any other
|
|
93
|
+
-- company, because `api_keys.company_id` is one company and there is no second
|
|
94
|
+
-- one to name.
|
|
95
|
+
--
|
|
96
|
+
-- The reference tables of the installation — currencies, charts, statement
|
|
97
|
+
-- schemes, the capability list — ask a different question again,
|
|
98
|
+
-- `auth.uid() is not null`, and they are the subject of the migration that
|
|
99
|
+
-- follows this one: they are not a company's rows, and what they were reaching
|
|
100
|
+
-- for was never a session but a caller this installation knows.
|
|
101
|
+
|
|
102
|
+
-- ---------------------------------------------------------------------------
|
|
103
|
+
-- The company of the key presented in this transaction
|
|
104
|
+
-- ---------------------------------------------------------------------------
|
|
105
|
+
|
|
106
|
+
create or replace function api_key_company()
|
|
107
|
+
returns uuid
|
|
108
|
+
language sql
|
|
109
|
+
stable
|
|
110
|
+
security definer
|
|
111
|
+
set search_path = public, pg_temp
|
|
112
|
+
as $$
|
|
113
|
+
select k.company_id
|
|
114
|
+
from api_keys k
|
|
115
|
+
where k.key_hash = nullif(current_setting('ekwo.api_key', true), '')
|
|
116
|
+
and k.revoked_at is null
|
|
117
|
+
and (k.expires_at is null or k.expires_at > now());
|
|
118
|
+
$$;
|
|
119
|
+
|
|
120
|
+
comment on function api_key_company() is
|
|
121
|
+
'The company of the machine key presented in this transaction, or nothing. What `is_company_member()` asks so that a key is on the company it was minted for, and the only thing of a key the policy helpers read.';
|
|
122
|
+
|
|
123
|
+
-- ---------------------------------------------------------------------------
|
|
124
|
+
-- A member, or a key of this company
|
|
125
|
+
--
|
|
126
|
+
-- The body is the only place the rule lives. `company_role()` still answers
|
|
127
|
+
-- about `auth.uid()` alone, and stays the answer to "which preset is this
|
|
128
|
+
-- person on" — a key is on no preset, holds a list, and must not be made to
|
|
129
|
+
-- look like a role.
|
|
130
|
+
-- ---------------------------------------------------------------------------
|
|
131
|
+
|
|
132
|
+
create or replace function is_company_member(p_company_id uuid)
|
|
133
|
+
returns boolean
|
|
134
|
+
language sql
|
|
135
|
+
stable
|
|
136
|
+
as $$
|
|
137
|
+
-- `coalesce`, and decision 0005 is why: `p_company_id = api_key_company()`
|
|
138
|
+
-- is NULL when no key is presented, `false or NULL` is NULL, and a guard
|
|
139
|
+
-- written as `if not is_company_member(...)` would not fire for a stranger.
|
|
140
|
+
-- A helper a guard is written on answers true or false and never NULL.
|
|
141
|
+
select company_role(p_company_id) is not null
|
|
142
|
+
or coalesce(p_company_id = api_key_company(), false);
|
|
143
|
+
$$;
|
|
144
|
+
|
|
145
|
+
comment on function is_company_member(uuid) is
|
|
146
|
+
'Whether the caller is on a company: a member of it, or the holder of a machine key minted on it. False, never NULL, for a stranger.';
|
|
147
|
+
|
|
148
|
+
create or replace function is_any_company_member()
|
|
149
|
+
returns boolean
|
|
150
|
+
language sql
|
|
151
|
+
stable
|
|
152
|
+
security definer
|
|
153
|
+
set search_path = public, pg_temp
|
|
154
|
+
as $$
|
|
155
|
+
select exists (select 1 from company_members m where m.user_id = auth.uid())
|
|
156
|
+
or api_key_company() is not null;
|
|
157
|
+
$$;
|
|
158
|
+
|
|
159
|
+
comment on function is_any_company_member() is
|
|
160
|
+
'Whether the caller belongs to at least one company of this installation, as a member or as the holder of a machine key.';
|
|
161
|
+
|
|
162
|
+
-- ---------------------------------------------------------------------------
|
|
163
|
+
-- Presenting a key without reading one
|
|
164
|
+
--
|
|
165
|
+
-- `use_api_key()` returns the row, which is what a client holding a connection
|
|
166
|
+
-- wants and what a pre-request must not hand back: the pre-request is called
|
|
167
|
+
-- by `anon`, so whatever it can call, an anonymous caller can call. This
|
|
168
|
+
-- returns nothing at all, and the row — `key_hash` included — stays behind the
|
|
169
|
+
-- grant it has always been behind.
|
|
170
|
+
-- ---------------------------------------------------------------------------
|
|
171
|
+
|
|
172
|
+
create or replace function present_api_key(p_secret text)
|
|
173
|
+
returns void
|
|
174
|
+
language plpgsql
|
|
175
|
+
security definer
|
|
176
|
+
set search_path = public, pg_temp
|
|
177
|
+
as $$
|
|
178
|
+
begin
|
|
179
|
+
perform use_api_key(p_secret);
|
|
180
|
+
end;
|
|
181
|
+
$$;
|
|
182
|
+
|
|
183
|
+
comment on function present_api_key(text) is
|
|
184
|
+
'Presents a machine key for the current transaction and answers nothing. What `ekwo_pre_request()` calls, and the only form of the question an anonymous caller may ask: the refusals of use_api_key() word for word, and no row.';
|
|
185
|
+
|
|
186
|
+
-- ---------------------------------------------------------------------------
|
|
187
|
+
-- The pre-request
|
|
188
|
+
--
|
|
189
|
+
-- Invoker, deliberately: PostgreSQL refuses `set role` inside a definer
|
|
190
|
+
-- function, and the privilege that makes the switch legal is the session's —
|
|
191
|
+
-- `authenticator` is a member of `authenticated` — not ours to lend.
|
|
192
|
+
--
|
|
193
|
+
-- `request.headers` is set by PostgREST and absent everywhere else, so the
|
|
194
|
+
-- function is a no-op on a direct connection, which is what the command line
|
|
195
|
+
-- and the MCP server use.
|
|
196
|
+
-- ---------------------------------------------------------------------------
|
|
197
|
+
|
|
198
|
+
create or replace function ekwo_pre_request()
|
|
199
|
+
returns void
|
|
200
|
+
language plpgsql
|
|
201
|
+
set search_path = public, pg_temp
|
|
202
|
+
as $$
|
|
203
|
+
declare
|
|
204
|
+
v_headers json := nullif(current_setting('request.headers', true), '')::json;
|
|
205
|
+
v_secret text := nullif(v_headers ->> 'x-ekwo-api-key', '');
|
|
206
|
+
begin
|
|
207
|
+
if v_secret is null then
|
|
208
|
+
return;
|
|
209
|
+
end if;
|
|
210
|
+
|
|
211
|
+
-- Raises on a key that is unknown, withdrawn or expired, and the raise fails
|
|
212
|
+
-- the request. Nothing below this line runs for a key that is not one.
|
|
213
|
+
perform present_api_key(v_secret);
|
|
214
|
+
|
|
215
|
+
-- Off `anon`, which holds no privilege on any table, and onto the role whose
|
|
216
|
+
-- grants row level security is written against. `auth.uid()` stays null.
|
|
217
|
+
perform set_config('role', 'authenticated', true);
|
|
218
|
+
end;
|
|
219
|
+
$$;
|
|
220
|
+
|
|
221
|
+
comment on function ekwo_pre_request() is
|
|
222
|
+
'Called by PostgREST at the start of every request (pgrst.db_pre_request). Presents the key in X-Ekwo-Api-Key when there is one, then moves the request off `anon` so that row level security decides instead of the grants. No header, no effect.';
|
|
223
|
+
|
|
224
|
+
-- ---------------------------------------------------------------------------
|
|
225
|
+
-- Telling PostgREST to call it
|
|
226
|
+
--
|
|
227
|
+
-- The setting lives on the `authenticator` role, which is the login PostgREST
|
|
228
|
+
-- connects with. It is configuration of the API and not of the schema, so a
|
|
229
|
+
-- database that has no such role — PGlite under the tests, a plain Postgres
|
|
230
|
+
-- behind the command line — skips it and loses nothing.
|
|
231
|
+
--
|
|
232
|
+
-- Where the role exists and the migration is not allowed to write its
|
|
233
|
+
-- settings, the schema is still correct and the header is simply not read yet.
|
|
234
|
+
-- That is a state somebody has to be told about rather than left to discover,
|
|
235
|
+
-- so it is a notice here and a check in `ekwo doctor`, which names the exact
|
|
236
|
+
-- statement to run.
|
|
237
|
+
-- ---------------------------------------------------------------------------
|
|
238
|
+
|
|
239
|
+
do $$
|
|
240
|
+
begin
|
|
241
|
+
if not exists (select 1 from pg_roles where rolname = 'authenticator') then
|
|
242
|
+
return;
|
|
243
|
+
end if;
|
|
244
|
+
begin
|
|
245
|
+
execute 'alter role authenticator set pgrst.db_pre_request = ''public.ekwo_pre_request''';
|
|
246
|
+
notify pgrst, 'reload config';
|
|
247
|
+
exception when insufficient_privilege then
|
|
248
|
+
raise notice 'ekwo: could not set pgrst.db_pre_request on the authenticator role. Machine keys will not be read from X-Ekwo-Api-Key until somebody with the privilege runs: alter role authenticator set pgrst.db_pre_request = ''public.ekwo_pre_request''; notify pgrst, ''reload config''; — `ekwo doctor` reports this.';
|
|
249
|
+
end;
|
|
250
|
+
end
|
|
251
|
+
$$;
|
|
252
|
+
|
|
253
|
+
revoke execute on all functions in schema public from public;
|
|
254
|
+
|
|
255
|
+
-- `anon` gains two functions, and the decision record says why. `api_key_company()`
|
|
256
|
+
-- is read by `is_company_member()`, which `anon` already executes on behalf of
|
|
257
|
+
-- a policy; `present_api_key()` and `ekwo_pre_request()` are the door itself,
|
|
258
|
+
-- and both answer `void`.
|
|
259
|
+
revoke execute on function api_key_company() from public;
|
|
260
|
+
revoke execute on function present_api_key(text) from public;
|
|
261
|
+
revoke execute on function ekwo_pre_request() from public;
|
|
262
|
+
|
|
263
|
+
grant execute on function api_key_company() to anon, authenticated, service_role;
|
|
264
|
+
grant execute on function present_api_key(text) to anon, authenticated, service_role;
|
|
265
|
+
grant execute on function ekwo_pre_request() to anon, authenticated, service_role;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
-- Ekwo OS — the version answers a key too, and a stranger not at all.
|
|
2
|
+
--
|
|
3
|
+
-- `installed_schema_version()` was granted to `authenticated` alone, because
|
|
4
|
+
-- the client that asks it asks after signing in. A machine key now reaches the
|
|
5
|
+
-- API (`20260922160000`), and it asks the same question first and for the same
|
|
6
|
+
-- reason: a backup that does not know whether the instance is ahead of the
|
|
7
|
+
-- code reading it writes an archive nobody can check.
|
|
8
|
+
--
|
|
9
|
+
-- Two ways to give it that answer. Granting `anon` the function as it stands
|
|
10
|
+
-- would hand an unauthenticated scanner the exact release an installation
|
|
11
|
+
-- runs, which is what the first migration declined to do. Granting it and
|
|
12
|
+
-- letting the *body* decide gives nothing away: the function returns a row to
|
|
13
|
+
-- a caller this installation knows — a signed-in user, or the holder of a live
|
|
14
|
+
-- key — and no rows at all to anybody else. `anon` may call it; calling it
|
|
15
|
+
-- anonymously is a way of learning nothing.
|
|
16
|
+
--
|
|
17
|
+
-- The grant is the one exception worth the sentence: a key presented through
|
|
18
|
+
-- the pre-request arrives as `authenticated` and does not need it. It is the
|
|
19
|
+
-- call made *before* the key is presented — the screen that checks a pasted
|
|
20
|
+
-- key against an instance — that arrives as `anon`, and the shape of the
|
|
21
|
+
-- answer is the same for both: zero rows unless somebody is there.
|
|
22
|
+
|
|
23
|
+
create or replace function installed_schema_version()
|
|
24
|
+
returns table (schema_version text, edition text)
|
|
25
|
+
language sql
|
|
26
|
+
stable
|
|
27
|
+
security definer
|
|
28
|
+
set search_path = public, pg_temp
|
|
29
|
+
as $$
|
|
30
|
+
select i.schema_version, i.edition::text
|
|
31
|
+
from instance i
|
|
32
|
+
where i.id = 1
|
|
33
|
+
and (auth.uid() is not null or api_key_company() is not null);
|
|
34
|
+
$$;
|
|
35
|
+
|
|
36
|
+
comment on function installed_schema_version() is
|
|
37
|
+
'The schema version this installation runs, and its edition, for a caller it knows: a signed-in account that is on no company yet, or the holder of a machine key. No rows for anybody else, so an anonymous call learns nothing. Nothing else of the instance row comes with it.';
|
|
38
|
+
|
|
39
|
+
revoke execute on all functions in schema public from public;
|
|
40
|
+
|
|
41
|
+
revoke execute on function installed_schema_version() from public;
|
|
42
|
+
grant execute on function installed_schema_version() to anon, authenticated, service_role;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
-- Ekwo OS — reference data is for a caller this installation knows.
|
|
2
|
+
--
|
|
3
|
+
-- Eighteen tables of the socle carry the reference data every reading depends
|
|
4
|
+
-- on: the currencies and their rates, the charts of accounts and their
|
|
5
|
+
-- templates, the taxes and where they post, the boxes of the declaration
|
|
6
|
+
-- forms, the financial statement schemes, the legal mentions, the territories,
|
|
7
|
+
-- the modules, and the list of capabilities itself. None of them belongs to a
|
|
8
|
+
-- company. Their policy has always been the same sentence — `auth.uid() is not
|
|
9
|
+
-- null` — which reads "somebody signed in", and was the right sentence while
|
|
10
|
+
-- the only caller this installation had was a person.
|
|
11
|
+
--
|
|
12
|
+
-- `20260922160000` gave it a second kind of caller. A machine key now reaches
|
|
13
|
+
-- the API, arrives as `authenticated` and is on its own company, and every
|
|
14
|
+
-- policy that asks a capability follows. These eighteen ask none: they ask for
|
|
15
|
+
-- a session, and a key is not a session, so they answered no — and a caller
|
|
16
|
+
-- that cannot read `modules` cannot even be told which tables an archive
|
|
17
|
+
-- carries, which is how `export_company()` was still refusing a key that held
|
|
18
|
+
-- `company.export`. The refusal was not about the company's data at all. It
|
|
19
|
+
-- was about a list of module codes.
|
|
20
|
+
--
|
|
21
|
+
-- So the sentence is replaced by what it was always reaching for, in one
|
|
22
|
+
-- helper that every one of them now calls:
|
|
23
|
+
--
|
|
24
|
+
-- is_known_caller() — a signed-in user, or the holder of a live key.
|
|
25
|
+
--
|
|
26
|
+
-- Nothing else changes. These tables hold no customer data: a chart of
|
|
27
|
+
-- accounts and a currency are the same rows on every installation, which is
|
|
28
|
+
-- why the seed writes them and nobody may. What widens is who may read what
|
|
29
|
+
-- the installation already publishes to every person signed into it, and the
|
|
30
|
+
-- set of callers grows by exactly one: somebody holding a key this
|
|
31
|
+
-- installation minted, which is a stronger claim than having signed up.
|
|
32
|
+
--
|
|
33
|
+
-- `anon` is untouched and still reads none of them: `is_known_caller()`
|
|
34
|
+
-- answers false without a session and without a key, which is the same word
|
|
35
|
+
-- `auth.uid() is not null` gave it.
|
|
36
|
+
--
|
|
37
|
+
-- The two reference tables of the assets module are the same question in a
|
|
38
|
+
-- module's schema, and are moved in the module's own migration, where they
|
|
39
|
+
-- belong.
|
|
40
|
+
|
|
41
|
+
create or replace function is_known_caller()
|
|
42
|
+
returns boolean
|
|
43
|
+
language sql
|
|
44
|
+
stable
|
|
45
|
+
as $$
|
|
46
|
+
select auth.uid() is not null or api_key_company() is not null;
|
|
47
|
+
$$;
|
|
48
|
+
|
|
49
|
+
comment on function is_known_caller() is
|
|
50
|
+
'Whether this installation knows who is asking: a signed-in user, or the holder of a live machine key. What the policies of the reference tables ask, in place of the `auth.uid() is not null` they asked while a person was the only caller.';
|
|
51
|
+
|
|
52
|
+
drop policy account_templates_select on account_templates;
|
|
53
|
+
create policy account_templates_select on account_templates
|
|
54
|
+
for select using (is_known_caller());
|
|
55
|
+
|
|
56
|
+
drop policy capabilities_select on capabilities;
|
|
57
|
+
create policy capabilities_select on capabilities
|
|
58
|
+
for select using (is_known_caller());
|
|
59
|
+
|
|
60
|
+
drop policy chart_templates_select on chart_templates;
|
|
61
|
+
create policy chart_templates_select on chart_templates
|
|
62
|
+
for select using (is_known_caller());
|
|
63
|
+
|
|
64
|
+
drop policy country_defaults_select on country_defaults;
|
|
65
|
+
create policy country_defaults_select on country_defaults
|
|
66
|
+
for select using (is_known_caller());
|
|
67
|
+
|
|
68
|
+
drop policy currencies_select on currencies;
|
|
69
|
+
create policy currencies_select on currencies
|
|
70
|
+
for select using (is_known_caller());
|
|
71
|
+
|
|
72
|
+
drop policy currency_rates_select on currency_rates;
|
|
73
|
+
create policy currency_rates_select on currency_rates
|
|
74
|
+
for select using (is_known_caller());
|
|
75
|
+
|
|
76
|
+
drop policy journal_templates_select on journal_templates;
|
|
77
|
+
create policy journal_templates_select on journal_templates
|
|
78
|
+
for select using (is_known_caller());
|
|
79
|
+
|
|
80
|
+
drop policy legal_mention_templates_select on legal_mention_templates;
|
|
81
|
+
create policy legal_mention_templates_select on legal_mention_templates
|
|
82
|
+
for select using (is_known_caller());
|
|
83
|
+
|
|
84
|
+
drop policy modules_select on modules;
|
|
85
|
+
create policy modules_select on modules
|
|
86
|
+
for select using (is_known_caller());
|
|
87
|
+
|
|
88
|
+
drop policy role_capabilities_select on role_capabilities;
|
|
89
|
+
create policy role_capabilities_select on role_capabilities
|
|
90
|
+
for select using (is_known_caller());
|
|
91
|
+
|
|
92
|
+
drop policy statement_line_rules_select on statement_line_rules;
|
|
93
|
+
create policy statement_line_rules_select on statement_line_rules
|
|
94
|
+
for select using (is_known_caller());
|
|
95
|
+
|
|
96
|
+
drop policy statement_line_templates_select on statement_line_templates;
|
|
97
|
+
create policy statement_line_templates_select on statement_line_templates
|
|
98
|
+
for select using (is_known_caller());
|
|
99
|
+
|
|
100
|
+
drop policy statement_templates_select on statement_templates;
|
|
101
|
+
create policy statement_templates_select on statement_templates
|
|
102
|
+
for select using (is_known_caller());
|
|
103
|
+
|
|
104
|
+
drop policy tax_posting_templates_select on tax_posting_templates;
|
|
105
|
+
create policy tax_posting_templates_select on tax_posting_templates
|
|
106
|
+
for select using (is_known_caller());
|
|
107
|
+
|
|
108
|
+
drop policy tax_report_box_templates_select on tax_report_box_templates;
|
|
109
|
+
create policy tax_report_box_templates_select on tax_report_box_templates
|
|
110
|
+
for select using (is_known_caller());
|
|
111
|
+
|
|
112
|
+
drop policy tax_report_templates_select on tax_report_templates;
|
|
113
|
+
create policy tax_report_templates_select on tax_report_templates
|
|
114
|
+
for select using (is_known_caller());
|
|
115
|
+
|
|
116
|
+
drop policy tax_templates_select on tax_templates;
|
|
117
|
+
create policy tax_templates_select on tax_templates
|
|
118
|
+
for select using (is_known_caller());
|
|
119
|
+
|
|
120
|
+
drop policy territories_select on territories;
|
|
121
|
+
create policy territories_select on territories
|
|
122
|
+
for select using (is_known_caller());
|
|
123
|
+
|
|
124
|
+
revoke execute on all functions in schema public from public;
|
|
125
|
+
|
|
126
|
+
revoke execute on function is_known_caller() from public;
|
|
127
|
+
grant execute on function is_known_caller() to anon, authenticated, service_role;
|
package/dist/assets/migrations/20260922171000_a_key_is_presented_in_a_read_only_transaction.sql
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
-- Ekwo OS — presenting a key must not need a transaction that can write.
|
|
2
|
+
--
|
|
3
|
+
-- Found against a real project, which is the only place it could be found:
|
|
4
|
+
-- PostgREST runs a GET, and an RPC whose function is not volatile, inside a
|
|
5
|
+
-- **read-only transaction**. `use_api_key()` ends by stamping
|
|
6
|
+
-- `api_keys.last_used_at` through `touch_api_key()`, and an UPDATE there is
|
|
7
|
+
-- refused:
|
|
8
|
+
--
|
|
9
|
+
-- cannot execute UPDATE in a read-only transaction (SQLSTATE 25006)
|
|
10
|
+
--
|
|
11
|
+
-- The refusal happens inside `ekwo_pre_request()`, so it fails the whole
|
|
12
|
+
-- request — with a 405 and a message about an UPDATE nobody asked for, on a
|
|
13
|
+
-- plain `GET /rest/v1/companies`. Every read a machine key makes is that
|
|
14
|
+
-- request, which is most of what a machine key is for: a backup, a report, a
|
|
15
|
+
-- dashboard. PGlite never said so, because a test opens the transaction it
|
|
16
|
+
-- wants and none of ours asked for a read-only one.
|
|
17
|
+
--
|
|
18
|
+
-- **The stamp is worth less than the request.** `last_used_at` answers "has
|
|
19
|
+
-- this key been used lately", which is what an operator withdraws keys on. It
|
|
20
|
+
-- is a convenience, and the work the key was presented for is not. So the use
|
|
21
|
+
-- is recorded when the transaction can record it, and skipped when it cannot,
|
|
22
|
+
-- rather than the other way round.
|
|
23
|
+
--
|
|
24
|
+
-- This is not an error being swallowed. Nothing is caught here and nothing
|
|
25
|
+
-- raises: the function asks whether the transaction it is in may write, and
|
|
26
|
+
-- the answer is a fact about the transaction, known before anything is
|
|
27
|
+
-- attempted. A key presented on a connection — the command line, the MCP
|
|
28
|
+
-- server, `ekwo` itself — opens a read-write transaction and is stamped
|
|
29
|
+
-- exactly as before. A key presented on a read request is not, and
|
|
30
|
+
-- `last_used_at` then means "last used in a way that could write it down",
|
|
31
|
+
-- which the column comment now says.
|
|
32
|
+
--
|
|
33
|
+
-- The alternative was an autonomous transaction, which in PostgreSQL means an
|
|
34
|
+
-- extension — dblink or pg_background — and this schema requires none and is
|
|
35
|
+
-- not going to start over a timestamp.
|
|
36
|
+
|
|
37
|
+
create or replace function use_api_key(p_secret text)
|
|
38
|
+
returns api_keys
|
|
39
|
+
language plpgsql
|
|
40
|
+
security definer
|
|
41
|
+
set search_path = public, pg_temp
|
|
42
|
+
as $$
|
|
43
|
+
declare
|
|
44
|
+
v_row api_keys%rowtype;
|
|
45
|
+
begin
|
|
46
|
+
select * into v_row
|
|
47
|
+
from api_keys
|
|
48
|
+
where key_hash = encode(sha256(convert_to(coalesce(p_secret, ''), 'UTF8')), 'hex');
|
|
49
|
+
|
|
50
|
+
if v_row.id is null then
|
|
51
|
+
raise exception 'unknown_api_key: that is not a key of this installation'
|
|
52
|
+
using errcode = '42501';
|
|
53
|
+
end if;
|
|
54
|
+
if v_row.revoked_at is not null then
|
|
55
|
+
raise exception 'api_key_revoked: that key was withdrawn on %', v_row.revoked_at
|
|
56
|
+
using errcode = '42501';
|
|
57
|
+
end if;
|
|
58
|
+
if v_row.expires_at is not null and v_row.expires_at <= now() then
|
|
59
|
+
raise exception 'api_key_expired: that key expired on %', v_row.expires_at
|
|
60
|
+
using errcode = '42501';
|
|
61
|
+
end if;
|
|
62
|
+
|
|
63
|
+
-- Transaction-local: the key is presented for the work at hand and not for
|
|
64
|
+
-- the life of a connection somebody else may inherit from a pool.
|
|
65
|
+
perform set_config('ekwo.api_key', v_row.key_hash, true);
|
|
66
|
+
|
|
67
|
+
-- Recorded where it can be. A read request runs in a read-only transaction
|
|
68
|
+
-- and an UPDATE in one is refused, which would fail the request the key was
|
|
69
|
+
-- presented for.
|
|
70
|
+
if not current_setting('transaction_read_only')::boolean then
|
|
71
|
+
perform touch_api_key(v_row.id);
|
|
72
|
+
end if;
|
|
73
|
+
|
|
74
|
+
return v_row;
|
|
75
|
+
end;
|
|
76
|
+
$$;
|
|
77
|
+
|
|
78
|
+
comment on function use_api_key(text) is
|
|
79
|
+
'Presents a machine key for the current transaction: has_capability() answers for it until the transaction ends. Refuses a key that is unknown, withdrawn or expired. Records the use when the transaction may write — a read request runs in a read-only transaction, where the stamp is worth less than the request.';
|
|
80
|
+
|
|
81
|
+
comment on column api_keys.last_used_at is
|
|
82
|
+
'When this key was last presented in a transaction that could write it down. A read over the API runs read-only and is not stamped, so this is a floor and never a ceiling: a key with an old date may still be in daily use for reading.';
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
-- Ekwo OS — the schema this release defines is 0.8.0.
|
|
2
|
+
--
|
|
3
|
+
-- `ekwo_schema_version()` is the one place the number lives, and a migration
|
|
4
|
+
-- is the only thing that moves it. A database then answers for the files it
|
|
5
|
+
-- has actually run rather than for what somebody believed it had run: the
|
|
6
|
+
-- column default and `init_instance()` both call this function, so a fresh
|
|
7
|
+
-- install records the new number without a second edit, and `ekwo migrate`
|
|
8
|
+
-- reads it back onto `instance.schema_version` for a database that was
|
|
9
|
+
-- installed at an older one.
|
|
10
|
+
--
|
|
11
|
+
-- Between 0.7.0 and here the schema gained the way a key reaches the API.
|
|
12
|
+
-- `ekwo_pre_request()` is called by PostgREST at the start of every request,
|
|
13
|
+
-- named in `pgrst.db_pre_request`, and presents the secret sent in
|
|
14
|
+
-- `X-Ekwo-Api-Key` before the request leaves `anon`; `present_api_key()` does
|
|
15
|
+
-- the presenting, `is_known_caller()` answers for a signed-in user or the
|
|
16
|
+
-- holder of a live key, and `is_company_member()` says true for the company a
|
|
17
|
+
-- key was minted on. It also gained `installed_schema_version()`, which
|
|
18
|
+
-- answers a caller this installation knows and nobody else, and
|
|
19
|
+
-- `default_statement_code()` with `financial_statement_of_kind()`, which give
|
|
20
|
+
-- a balance sheet to a client that does not know the country pack. A 0.7.0
|
|
21
|
+
-- database has none of them, and the packages of this release call them: the
|
|
22
|
+
-- floor of `ekwo-os`, `@ekwo-ai/core` and `@ekwo-ai/mcp` rises to 0.8.0 and
|
|
23
|
+
-- refuses an older database by name, as every release has, rather than
|
|
24
|
+
-- answering for one they were never run against.
|
|
25
|
+
|
|
26
|
+
create or replace function ekwo_schema_version()
|
|
27
|
+
returns text
|
|
28
|
+
language sql
|
|
29
|
+
immutable
|
|
30
|
+
as $$
|
|
31
|
+
select '0.8.0'::text;
|
|
32
|
+
$$;
|
|
33
|
+
|
|
34
|
+
comment on function ekwo_schema_version() is
|
|
35
|
+
'Schema version of the installed release. Bumped by a migration, never by hand.';
|
|
36
|
+
|
|
37
|
+
-- `create or replace` keeps the privileges the function already had, and the
|
|
38
|
+
-- revoke is what every migration of this directory ends with: a function that
|
|
39
|
+
-- comes out with the built-in default is published by Supabase as an
|
|
40
|
+
-- anonymous RPC endpoint.
|
|
41
|
+
revoke execute on all functions in schema public from public;
|
|
42
|
+
grant execute on function ekwo_schema_version() to authenticated, service_role;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
-- Ekwo module `assets` — its reference tables answer the same caller the
|
|
2
|
+
-- socle's do.
|
|
3
|
+
--
|
|
4
|
+
-- `assets.country_rules` and `assets.category_templates` are reference data of
|
|
5
|
+
-- the module: the depreciation rules a country allows, and the categories a
|
|
6
|
+
-- register starts from. Their policy is the sentence the socle used everywhere
|
|
7
|
+
-- before `20260922162500` — `auth.uid() is not null`, which reads "somebody
|
|
8
|
+
-- signed in" — and the socle has since replaced it with what it was reaching
|
|
9
|
+
-- for: `is_known_caller()`, a signed-in user or the holder of a live machine
|
|
10
|
+
-- key.
|
|
11
|
+
--
|
|
12
|
+
-- A module does not get to answer that question differently. A key that may
|
|
13
|
+
-- read the register and cannot read the rules the register is built on reads
|
|
14
|
+
-- half a module, and the half it is missing is the half that explains the
|
|
15
|
+
-- other. The company's own rows are untouched: they keep asking
|
|
16
|
+
-- `has_capability()` and `module_enabled()`, as they did.
|
|
17
|
+
|
|
18
|
+
drop policy assets_country_rules_select on assets.country_rules;
|
|
19
|
+
create policy assets_country_rules_select on assets.country_rules
|
|
20
|
+
for select using (public.is_known_caller());
|
|
21
|
+
|
|
22
|
+
drop policy assets_category_templates_select on assets.category_templates;
|
|
23
|
+
create policy assets_category_templates_select on assets.category_templates
|
|
24
|
+
for select using (public.is_known_caller());
|
package/dist/doctor.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAOL,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAG1C,MAAM,MAAM,QAAQ,GAAG,IAAI,GAAG,SAAS,GAAG,SAAS,CAAC;AAEpD,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC5B;AAED,wBAAsB,MAAM,CAC1B,EAAE,EAAE,SAAS,EACb,UAAU,EAAE,SAAS,EAAE,EACvB,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,YAAY,CAAC,
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAOL,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAG1C,MAAM,MAAM,QAAQ,GAAG,IAAI,GAAG,SAAS,GAAG,SAAS,CAAC;AAEpD,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC5B;AAED,wBAAsB,MAAM,CAC1B,EAAE,EAAE,SAAS,EACb,UAAU,EAAE,SAAS,EAAE,EACvB,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,YAAY,CAAC,CA2BvB"}
|
package/dist/doctor.js
CHANGED
|
@@ -26,6 +26,7 @@ export async function doctor(db, migrations, options = {}) {
|
|
|
26
26
|
checks.push(await checkRowLevelSecurity(db));
|
|
27
27
|
checks.push(await checkPolicies(db));
|
|
28
28
|
checks.push(await checkGrants(db, expected));
|
|
29
|
+
checks.push(await checkPreRequest(db));
|
|
29
30
|
checks.push(await checkOrphanMembers(db));
|
|
30
31
|
checks.push(await checkOrphanAdmins(db));
|
|
31
32
|
checks.push(await checkBankAccounts(db));
|
|
@@ -342,6 +343,45 @@ async function checkBankAccounts(db) {
|
|
|
342
343
|
],
|
|
343
344
|
};
|
|
344
345
|
}
|
|
346
|
+
/**
|
|
347
|
+
* Whether PostgREST has been told to call `ekwo_pre_request()`.
|
|
348
|
+
*
|
|
349
|
+
* A machine key travels in `X-Ekwo-Api-Key` and is read by that function at
|
|
350
|
+
* the start of a request's transaction — which only happens if
|
|
351
|
+
* `pgrst.db_pre_request` names it on the `authenticator` role. The migration
|
|
352
|
+
* sets it where it is allowed to, and a managed project may not allow it, so
|
|
353
|
+
* this is the check that says so out loud instead of leaving somebody to
|
|
354
|
+
* discover that their key does nothing.
|
|
355
|
+
*
|
|
356
|
+
* A database with no `authenticator` role has no PostgREST in front of it —
|
|
357
|
+
* the command line's own connection, a plain Postgres — and there is nothing
|
|
358
|
+
* to report.
|
|
359
|
+
*/
|
|
360
|
+
async function checkPreRequest(db) {
|
|
361
|
+
const name = 'api keys over the API';
|
|
362
|
+
const found = await db.query(`select (select s from unnest(coalesce(r.rolconfig, '{}')) as s
|
|
363
|
+
where s like 'pgrst.db_pre_request=%') as setting
|
|
364
|
+
from pg_roles r where r.rolname = 'authenticator'`);
|
|
365
|
+
if (found.length === 0) {
|
|
366
|
+
return { name, severity: 'ok', summary: 'no PostgREST in front of this database' };
|
|
367
|
+
}
|
|
368
|
+
const setting = found[0]?.setting ?? null;
|
|
369
|
+
if (setting !== null && setting.endsWith('ekwo_pre_request')) {
|
|
370
|
+
return { name, severity: 'ok', summary: 'PostgREST calls ekwo_pre_request()' };
|
|
371
|
+
}
|
|
372
|
+
return {
|
|
373
|
+
name,
|
|
374
|
+
severity: 'warning',
|
|
375
|
+
summary: setting === null
|
|
376
|
+
? 'PostgREST calls no pre-request, so a machine key in X-Ekwo-Api-Key is ignored'
|
|
377
|
+
: `PostgREST calls another pre-request (${setting}), so a machine key in X-Ekwo-Api-Key is ignored`,
|
|
378
|
+
details: [
|
|
379
|
+
"alter role authenticator set pgrst.db_pre_request = 'public.ekwo_pre_request';",
|
|
380
|
+
"notify pgrst, 'reload config';",
|
|
381
|
+
'Run both as a role that may write the settings of `authenticator`. Nothing else is affected: keys presented on a direct connection with use_api_key() work either way.',
|
|
382
|
+
],
|
|
383
|
+
};
|
|
384
|
+
}
|
|
345
385
|
async function checkStatements(db) {
|
|
346
386
|
const rows = await db.query(`select c.name as company, s.statement_date::text,
|
|
347
387
|
s.balance_end_declared::text as declared,
|
package/dist/doctor.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"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"}
|
package/dist/schema.d.ts
CHANGED
package/dist/schema.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ekwo-os",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Install and operate Ekwo OS on your own Supabase project: npx ekwo-os init.",
|
|
5
5
|
"keywords": ["accounting", "supabase", "postgres", "migrations", "cli", "bookkeeping", "ekwo"],
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"bugs": { "url": "https://github.com/Ekwo-ai/ekwo-os/issues" },
|
|
11
11
|
"type": "module",
|
|
12
12
|
"engines": { "node": ">=20" },
|
|
13
|
-
"ekwo": { "schemaMin": "0.
|
|
13
|
+
"ekwo": { "schemaMin": "0.8.0" },
|
|
14
14
|
"files": ["dist", "schema", "README.md"],
|
|
15
15
|
"bin": { "ekwo": "./dist/bin.js" },
|
|
16
16
|
"main": "./dist/index.js",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@ekwo-ai/core": "^0.
|
|
26
|
+
"@ekwo-ai/core": "^0.8.0",
|
|
27
27
|
"postgres": "^3.4.5"
|
|
28
28
|
}
|
|
29
29
|
}
|