@ekwo-ai/mcp 0.8.0 → 0.9.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/format.js ADDED
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Amounts as decimal strings, everywhere, in both directions.
3
+ *
4
+ * Postgres holds `numeric` exactly and hands it over as text; a table read
5
+ * asks for `amount::text` so that is what arrives. The one place a float can
6
+ * appear is a function result crossing PostgREST as JSON, where `1210.00`
7
+ * becomes a number before any code of ours sees it. `money()` puts it back to
8
+ * two decimals, which is exact for every amount a ledger holds, and a model
9
+ * reading `"1210.00"` never has to wonder whether `1210.0000000001` was the
10
+ * VAT rounding or the transport.
11
+ */
12
+ import { EkwoMcpError } from './backend.js';
13
+ import { roundCurrency } from './rounding.js';
14
+ /** A numeric, as the decimal string the ledger holds. */
15
+ export function money(value) {
16
+ if (value === null || value === undefined)
17
+ return null;
18
+ if (typeof value === 'number')
19
+ return roundCurrency(value, 2).toFixed(2);
20
+ const text = String(value);
21
+ return text.length === 0 ? null : text;
22
+ }
23
+ /** The same, for a quantity or a rate, where two decimals would be a lie. */
24
+ export function decimal(value) {
25
+ if (value === null || value === undefined)
26
+ return null;
27
+ const text = String(value);
28
+ return text.length === 0 ? null : text;
29
+ }
30
+ /** Applies `money()` to the named keys of every row. */
31
+ export function moneyFields(rows, keys) {
32
+ return rows.map((row) => {
33
+ const out = { ...row };
34
+ for (const key of keys) {
35
+ if (key in out)
36
+ out[key] = money(out[key]);
37
+ }
38
+ return out;
39
+ });
40
+ }
41
+ /** An amount on its way into the database: `"1210.00"`, never 1210.0000001. */
42
+ export function amountIn(value) {
43
+ const text = typeof value === 'number' ? roundCurrency(value, 2).toFixed(2) : value.trim();
44
+ if (!/^-?\d+(\.\d+)?$/.test(text)) {
45
+ throw new EkwoMcpError(`bad_amount: ${String(value)} is not a decimal amount`);
46
+ }
47
+ return text;
48
+ }
49
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAI9C,yDAAyD;AACzD,MAAM,UAAU,KAAK,CAAC,KAAc;IAClC,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACvD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,aAAa,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACzE,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC3B,OAAO,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACzC,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,OAAO,CAAC,KAAc;IACpC,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACvD,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC3B,OAAO,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACzC,CAAC;AAED,wDAAwD;AACxD,MAAM,UAAU,WAAW,CAAoC,IAAS,EAAE,IAAc;IACtF,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACtB,MAAM,GAAG,GAA4B,EAAE,GAAG,GAAG,EAAE,CAAC;QAChD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,IAAI,GAAG,IAAI,GAAG;gBAAE,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,GAAQ,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,QAAQ,CAAC,KAAsB;IAC7C,MAAM,IAAI,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IAC3F,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,YAAY,CAAC,eAAe,MAAM,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
package/dist/http.d.ts ADDED
@@ -0,0 +1,92 @@
1
+ /**
2
+ * The same server over HTTP: the Streamable HTTP transport of MCP, stateless.
3
+ *
4
+ * `bin.ts` is a process a client starts on its own machine, and it reads who
5
+ * it acts as from its environment. A server somebody reaches by URL is the
6
+ * other shape: one process answers many people, so **who a request acts as
7
+ * is decided per request**, by whatever put the server on the network — its
8
+ * own sign-in, its own tokens — and handed in here as a connection. This
9
+ * file knows nothing about how that host authenticates anybody. It takes a
10
+ * request and the connection that request is allowed to use, and answers.
11
+ *
12
+ * ## Stateless, in JSON
13
+ *
14
+ * Each request builds a server, answers, and closes it. Nothing is kept
15
+ * between two requests — no session id, no stream, no cache of whose books
16
+ * were open — so a host can run it on a function platform, behind a load
17
+ * balancer, or on one machine, and two people never share a thing. The
18
+ * answers are plain JSON (`enableJsonResponse`): every tool of this server
19
+ * answers once, and an open event stream would hold a connection for nothing.
20
+ * A `GET` — the stream a client may open for messages the server sends on its
21
+ * own — is answered `405`, which the protocol allows and which is the truth:
22
+ * this server never speaks first.
23
+ *
24
+ * ## What a connection may be
25
+ *
26
+ * - **A person's session on the instance**: the project address, its
27
+ * publishable key and an access token. Row level security decides, as it
28
+ * does for that person in a browser.
29
+ * - **A key of Ekwo OS**: the same two, and a key `create_api_key()` issued.
30
+ * It travels in `X-Ekwo-Api-Key`, the core's pre-request hook presents it
31
+ * (decision 0062), and the caller is on the key's one company with the
32
+ * key's capabilities.
33
+ * - **A backend already built**, for a host that reaches the database some
34
+ * other way — and for the tests, which run the real schema in PGlite.
35
+ *
36
+ * A `service_role` key is refused in every slot it could arrive in, as it is
37
+ * on stdio: this server has no privilege of its own, over any transport.
38
+ */
39
+ import type { IncomingMessage, ServerResponse } from 'node:http';
40
+ import { type Backend } from './backend.js';
41
+ /** Who one request acts as, over PostgREST. Exactly one of the two credentials. */
42
+ export interface HttpConnection {
43
+ /** The project, `https://<ref>.supabase.co`. */
44
+ supabaseUrl: string;
45
+ /** Its publishable (anon) key. Never the `service_role` key. */
46
+ anonKey: string;
47
+ /** A person's access token on that project. */
48
+ accessToken?: string | undefined;
49
+ /** A key of Ekwo OS, issued on one company of that project. */
50
+ apiKey?: string | undefined;
51
+ }
52
+ export interface HttpHandlerOptions {
53
+ /**
54
+ * The modules whose tools are offered. Left out, the database is asked on
55
+ * every request that needs to know — a host that knows already, or caches
56
+ * the answer, passes it and saves the round trip.
57
+ */
58
+ modules?: readonly string[] | undefined;
59
+ /** The `fetch` the PostgREST backend uses. A host or a test may hand its own. */
60
+ fetch?: typeof globalThis.fetch | undefined;
61
+ }
62
+ /**
63
+ * Checks a connection and says what is wrong with it, without a network.
64
+ *
65
+ * The three refusals of `readConfig`, for a connection that did not come from
66
+ * an environment: nothing to act as, two things to act as, and a
67
+ * `service_role` key in any of the three slots.
68
+ */
69
+ export declare function checkConnection(connection: HttpConnection): void;
70
+ /** The backend a connection describes. The caller closes it. */
71
+ export declare function openHttpBackend(connection: HttpConnection, options?: {
72
+ fetch?: typeof globalThis.fetch | undefined;
73
+ }): Promise<Backend>;
74
+ /**
75
+ * Answers one HTTP request of the MCP Streamable HTTP transport.
76
+ *
77
+ * `connection` is who this request acts as, decided by the host before it
78
+ * calls this. Nothing about it is remembered once the response is built.
79
+ */
80
+ export declare function handleHttpRequest(request: Request, connection: HttpConnection | Backend, options?: HttpHandlerOptions): Promise<Response>;
81
+ /**
82
+ * The same handler for `node:http` (and anything built on it).
83
+ *
84
+ * The request is read into a web `Request`, answered by `handleHttpRequest`,
85
+ * and the `Response` written back — one path, whichever server a host runs.
86
+ * `origin` is the address this server is reached at, which `node:http` does
87
+ * not know: `https://mcp.example.org`.
88
+ */
89
+ export declare function handleNodeRequest(req: IncomingMessage, res: ServerResponse, connection: HttpConnection | Backend, options: HttpHandlerOptions & {
90
+ origin: string;
91
+ }): Promise<void>;
92
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAGjE,OAAO,EAAgB,KAAK,OAAO,EAAE,MAAM,cAAc,CAAC;AAM1D,mFAAmF;AACnF,MAAM,WAAW,cAAc;IAC7B,gDAAgD;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB,gEAAgE;IAChE,OAAO,EAAE,MAAM,CAAC;IAChB,+CAA+C;IAC/C,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAED,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IACxC,iFAAiF;IACjF,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,GAAG,SAAS,CAAC;CAC7C;AAaD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,cAAc,GAAG,IAAI,CAuBhE;AAED,gEAAgE;AAChE,wBAAsB,eAAe,CACnC,UAAU,EAAE,cAAc,EAC1B,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,GAAG,SAAS,CAAA;CAAO,GAC5D,OAAO,CAAC,OAAO,CAAC,CASlB;AAYD;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,cAAc,GAAG,OAAO,EACpC,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,QAAQ,CAAC,CA4DnB;AAWD;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,UAAU,EAAE,cAAc,GAAG,OAAO,EACpC,OAAO,EAAE,kBAAkB,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAC/C,OAAO,CAAC,IAAI,CAAC,CAkBf"}
package/dist/http.js ADDED
@@ -0,0 +1,208 @@
1
+ /**
2
+ * The same server over HTTP: the Streamable HTTP transport of MCP, stateless.
3
+ *
4
+ * `bin.ts` is a process a client starts on its own machine, and it reads who
5
+ * it acts as from its environment. A server somebody reaches by URL is the
6
+ * other shape: one process answers many people, so **who a request acts as
7
+ * is decided per request**, by whatever put the server on the network — its
8
+ * own sign-in, its own tokens — and handed in here as a connection. This
9
+ * file knows nothing about how that host authenticates anybody. It takes a
10
+ * request and the connection that request is allowed to use, and answers.
11
+ *
12
+ * ## Stateless, in JSON
13
+ *
14
+ * Each request builds a server, answers, and closes it. Nothing is kept
15
+ * between two requests — no session id, no stream, no cache of whose books
16
+ * were open — so a host can run it on a function platform, behind a load
17
+ * balancer, or on one machine, and two people never share a thing. The
18
+ * answers are plain JSON (`enableJsonResponse`): every tool of this server
19
+ * answers once, and an open event stream would hold a connection for nothing.
20
+ * A `GET` — the stream a client may open for messages the server sends on its
21
+ * own — is answered `405`, which the protocol allows and which is the truth:
22
+ * this server never speaks first.
23
+ *
24
+ * ## What a connection may be
25
+ *
26
+ * - **A person's session on the instance**: the project address, its
27
+ * publishable key and an access token. Row level security decides, as it
28
+ * does for that person in a browser.
29
+ * - **A key of Ekwo OS**: the same two, and a key `create_api_key()` issued.
30
+ * It travels in `X-Ekwo-Api-Key`, the core's pre-request hook presents it
31
+ * (decision 0062), and the caller is on the key's one company with the
32
+ * key's capabilities.
33
+ * - **A backend already built**, for a host that reaches the database some
34
+ * other way — and for the tests, which run the real schema in PGlite.
35
+ *
36
+ * A `service_role` key is refused in every slot it could arrive in, as it is
37
+ * on stdio: this server has no privilege of its own, over any transport.
38
+ */
39
+ import { WebStandardStreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js';
40
+ import { isServiceRoleKey, serviceRoleRefusal } from '@ekwo-ai/core';
41
+ import { EkwoMcpError } from './backend.js';
42
+ import { postgrestBackend } from './postgrest.js';
43
+ import { assertSchemaSupported } from './schema.js';
44
+ import { buildServer } from './server.js';
45
+ import { installedModules } from './tools/modules.js';
46
+ const SURFACE = 'this server';
47
+ const SIGN_IN = 'connect it with a person\'s session or with a key of Ekwo OS';
48
+ /** A JSON-RPC error on the wire, for the refusals that come before the protocol. */
49
+ function rpcError(status, code, message, id = null) {
50
+ return new Response(JSON.stringify({ jsonrpc: '2.0', error: { code, message }, id }), {
51
+ status,
52
+ headers: { 'Content-Type': 'application/json' },
53
+ });
54
+ }
55
+ /**
56
+ * Checks a connection and says what is wrong with it, without a network.
57
+ *
58
+ * The three refusals of `readConfig`, for a connection that did not come from
59
+ * an environment: nothing to act as, two things to act as, and a
60
+ * `service_role` key in any of the three slots.
61
+ */
62
+ export function checkConnection(connection) {
63
+ const { supabaseUrl, anonKey, accessToken, apiKey } = connection;
64
+ if (supabaseUrl.trim().length === 0 || anonKey.trim().length === 0) {
65
+ throw new EkwoMcpError('missing_configuration: a connection needs the project address and its publishable key.');
66
+ }
67
+ if (isServiceRoleKey(anonKey)) {
68
+ throw new EkwoMcpError(serviceRoleRefusal('the publishable key of the connection', 'apikey', SURFACE, SIGN_IN));
69
+ }
70
+ const hasToken = accessToken !== undefined && accessToken.length > 0;
71
+ const hasKey = apiKey !== undefined && apiKey.length > 0;
72
+ if (hasToken && isServiceRoleKey(accessToken)) {
73
+ throw new EkwoMcpError(serviceRoleRefusal('the access token of the connection', 'authorization', SURFACE, SIGN_IN));
74
+ }
75
+ if (hasKey && isServiceRoleKey(apiKey)) {
76
+ throw new EkwoMcpError(serviceRoleRefusal('the key of the connection', 'apikey', SURFACE, SIGN_IN));
77
+ }
78
+ if (hasToken === hasKey) {
79
+ throw new EkwoMcpError(hasToken
80
+ ? 'two_credentials: a connection acts as a person or as a key of Ekwo OS, never as both at once.'
81
+ : 'missing_credentials: a connection needs a person\'s access token or a key of Ekwo OS. This server has no identity of its own.');
82
+ }
83
+ }
84
+ /** The backend a connection describes. The caller closes it. */
85
+ export async function openHttpBackend(connection, options = {}) {
86
+ checkConnection(connection);
87
+ return postgrestBackend({
88
+ supabaseUrl: connection.supabaseUrl,
89
+ anonKey: connection.anonKey,
90
+ accessToken: connection.apiKey === undefined ? connection.accessToken : undefined,
91
+ apiKey: connection.apiKey,
92
+ fetch: options.fetch,
93
+ });
94
+ }
95
+ /** The JSON-RPC messages of a body, whether it held one or a batch. */
96
+ function messagesOf(body) {
97
+ if (Array.isArray(body))
98
+ return body;
99
+ if (body !== null && typeof body === 'object')
100
+ return [body];
101
+ return [];
102
+ }
103
+ /** Methods whose answer depends on which tools this installation carries. */
104
+ const NEEDS_MODULES = new Set(['tools/list', 'tools/call']);
105
+ /**
106
+ * Answers one HTTP request of the MCP Streamable HTTP transport.
107
+ *
108
+ * `connection` is who this request acts as, decided by the host before it
109
+ * calls this. Nothing about it is remembered once the response is built.
110
+ */
111
+ export async function handleHttpRequest(request, connection, options = {}) {
112
+ if (request.method === 'GET' || request.method === 'DELETE') {
113
+ // No stream to open and no session to end: every answer is in the
114
+ // response to the request that asked for it.
115
+ return new Response(null, { status: 405, headers: { Allow: 'POST' } });
116
+ }
117
+ if (request.method !== 'POST') {
118
+ return new Response(null, { status: 405, headers: { Allow: 'POST' } });
119
+ }
120
+ let body;
121
+ try {
122
+ body = await request.json();
123
+ }
124
+ catch {
125
+ return rpcError(400, -32700, 'Parse error: the body is not JSON.');
126
+ }
127
+ const messages = messagesOf(body);
128
+ const methods = new Set(messages.map((message) => message.method));
129
+ const firstId = messages.find((message) => message.id !== undefined)?.id ?? null;
130
+ let backend;
131
+ const owned = !isBackend(connection);
132
+ try {
133
+ backend = isBackend(connection) ? connection : await openHttpBackend(connection, { fetch: options.fetch });
134
+ }
135
+ catch (error) {
136
+ // A connection the host built wrong, or a token the instance refused.
137
+ // The host decided this request may act; the database disagreeing is
138
+ // still an answer, and it goes back as one.
139
+ return rpcError(200, -32001, error instanceof Error ? error.message : String(error), firstId);
140
+ }
141
+ try {
142
+ if (methods.has('initialize')) {
143
+ // The one moment a client is told what this server is, so the moment a
144
+ // database older than it is refused by name. On stdio this is the start
145
+ // of the process; here there is no such thing.
146
+ try {
147
+ await assertSchemaSupported(backend);
148
+ }
149
+ catch (error) {
150
+ return rpcError(200, -32002, error instanceof Error ? error.message : String(error), firstId);
151
+ }
152
+ }
153
+ const needsModules = [...methods].some((method) => typeof method === 'string' && NEEDS_MODULES.has(method));
154
+ const modules = options.modules ?? (needsModules ? await installedModules(backend) : []);
155
+ const server = buildServer(backend, { modules });
156
+ const transport = new WebStandardStreamableHTTPServerTransport({
157
+ sessionIdGenerator: undefined,
158
+ enableJsonResponse: true,
159
+ });
160
+ try {
161
+ await server.connect(transport);
162
+ return await transport.handleRequest(request, { parsedBody: body });
163
+ }
164
+ finally {
165
+ await server.close().catch(() => { });
166
+ }
167
+ }
168
+ finally {
169
+ if (owned)
170
+ await backend.close().catch(() => { });
171
+ }
172
+ }
173
+ function isBackend(value) {
174
+ return typeof value.select === 'function';
175
+ }
176
+ // ---------------------------------------------------------------------------
177
+ // node:http, for a host that is not a function platform
178
+ // ---------------------------------------------------------------------------
179
+ /**
180
+ * The same handler for `node:http` (and anything built on it).
181
+ *
182
+ * The request is read into a web `Request`, answered by `handleHttpRequest`,
183
+ * and the `Response` written back — one path, whichever server a host runs.
184
+ * `origin` is the address this server is reached at, which `node:http` does
185
+ * not know: `https://mcp.example.org`.
186
+ */
187
+ export async function handleNodeRequest(req, res, connection, options) {
188
+ const chunks = [];
189
+ for await (const chunk of req)
190
+ chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk);
191
+ const headers = new Headers();
192
+ for (const [name, value] of Object.entries(req.headers)) {
193
+ if (value === undefined)
194
+ continue;
195
+ headers.set(name, Array.isArray(value) ? value.join(', ') : value);
196
+ }
197
+ const method = req.method ?? 'GET';
198
+ const request = new Request(new URL(req.url ?? '/', options.origin), {
199
+ method,
200
+ headers,
201
+ ...(method === 'GET' || method === 'HEAD' ? {} : { body: Buffer.concat(chunks) }),
202
+ });
203
+ const response = await handleHttpRequest(request, connection, options);
204
+ res.statusCode = response.status;
205
+ response.headers.forEach((value, name) => res.setHeader(name, value));
206
+ res.end(Buffer.from(await response.arrayBuffer()));
207
+ }
208
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -10,7 +10,8 @@ export { EkwoMcpError, explain, socleCode, type Backend, type Filter, type Order
10
10
  export { ENV, isServiceRoleKey, openBackend, readConfig, type Config } from './config.js';
11
11
  export { amountIn, decimal, money, moneyFields, type Decimal } from '@ekwo-ai/core';
12
12
  export { connect, sqlBackend, type SqlBackendOptions, type SqlClient } from './sql.js';
13
- export { postgrestBackend, type PostgrestBackendOptions } from './postgrest.js';
13
+ export { API_KEY_HEADER, postgrestBackend, type PostgrestBackendOptions } from './postgrest.js';
14
+ export { checkConnection, handleHttpRequest, handleNodeRequest, openHttpBackend, type HttpConnection, type HttpHandlerOptions, } from './http.js';
14
15
  export { SERVER_NAME, SERVER_VERSION, buildServer, type ServerOptions } from './server.js';
15
16
  export { SCHEMA_MIN, assertSchemaSupported, installedSchemaVersion } from './schema.js';
16
17
  export { serverFromEnvironment, type Started } from './start.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,YAAY,EACZ,OAAO,EACP,SAAS,EACT,KAAK,OAAO,EACZ,KAAK,MAAM,EACX,KAAK,KAAK,EACV,KAAK,GAAG,EACR,KAAK,WAAW,GACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,GAAG,EAAE,gBAAgB,EAAE,WAAW,EAAE,UAAU,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1F,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AACpF,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,KAAK,SAAS,EAAE,MAAM,UAAU,CAAC;AACvF,OAAO,EAAE,gBAAgB,EAAE,KAAK,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,WAAW,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAC3F,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACxF,OAAO,EAAE,qBAAqB,EAAE,KAAK,OAAO,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAChF,OAAO,KAAK,SAAS,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,KAAK,UAAU,EACf,KAAK,aAAa,GACnB,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,YAAY,EACZ,OAAO,EACP,SAAS,EACT,KAAK,OAAO,EACZ,KAAK,MAAM,EACX,KAAK,KAAK,EACV,KAAK,GAAG,EACR,KAAK,WAAW,GACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,GAAG,EAAE,gBAAgB,EAAE,WAAW,EAAE,UAAU,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1F,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AACpF,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,KAAK,SAAS,EAAE,MAAM,UAAU,CAAC;AACvF,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,KAAK,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAChG,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,KAAK,cAAc,EACnB,KAAK,kBAAkB,GACxB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,WAAW,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAC3F,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACxF,OAAO,EAAE,qBAAqB,EAAE,KAAK,OAAO,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAChF,OAAO,KAAK,SAAS,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,KAAK,UAAU,EACf,KAAK,aAAa,GACnB,MAAM,oBAAoB,CAAC"}
package/dist/index.js CHANGED
@@ -10,7 +10,8 @@ export { EkwoMcpError, explain, socleCode, } from './backend.js';
10
10
  export { ENV, isServiceRoleKey, openBackend, readConfig } from './config.js';
11
11
  export { amountIn, decimal, money, moneyFields } from '@ekwo-ai/core';
12
12
  export { connect, sqlBackend } from './sql.js';
13
- export { postgrestBackend } from './postgrest.js';
13
+ export { API_KEY_HEADER, postgrestBackend } from './postgrest.js';
14
+ export { checkConnection, handleHttpRequest, handleNodeRequest, openHttpBackend, } from './http.js';
14
15
  export { SERVER_NAME, SERVER_VERSION, buildServer } from './server.js';
15
16
  export { SCHEMA_MIN, assertSchemaSupported, installedSchemaVersion } from './schema.js';
16
17
  export { serverFromEnvironment } from './start.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,YAAY,EACZ,OAAO,EACP,SAAS,GAMV,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,GAAG,EAAE,gBAAgB,EAAE,WAAW,EAAE,UAAU,EAAe,MAAM,aAAa,CAAC;AAC1F,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAgB,MAAM,eAAe,CAAC;AACpF,OAAO,EAAE,OAAO,EAAE,UAAU,EAA0C,MAAM,UAAU,CAAC;AACvF,OAAO,EAAE,gBAAgB,EAAgC,MAAM,gBAAgB,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,WAAW,EAAsB,MAAM,aAAa,CAAC;AAC3F,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACxF,OAAO,EAAE,qBAAqB,EAAgB,MAAM,YAAY,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAChF,OAAO,KAAK,SAAS,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,WAAW,GAGZ,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,YAAY,EACZ,OAAO,EACP,SAAS,GAMV,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,GAAG,EAAE,gBAAgB,EAAE,WAAW,EAAE,UAAU,EAAe,MAAM,aAAa,CAAC;AAC1F,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAgB,MAAM,eAAe,CAAC;AACpF,OAAO,EAAE,OAAO,EAAE,UAAU,EAA0C,MAAM,UAAU,CAAC;AACvF,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAgC,MAAM,gBAAgB,CAAC;AAChG,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,GAGhB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,WAAW,EAAsB,MAAM,aAAa,CAAC;AAC3F,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACxF,OAAO,EAAE,qBAAqB,EAAgB,MAAM,YAAY,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAChF,OAAO,KAAK,SAAS,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,WAAW,GAGZ,MAAM,oBAAoB,CAAC"}
@@ -23,7 +23,22 @@ export interface PostgrestBackendOptions {
23
23
  accessToken?: string | undefined;
24
24
  email?: string | undefined;
25
25
  password?: string | undefined;
26
+ /**
27
+ * A key of Ekwo OS — what `create_api_key()` issues — instead of a person.
28
+ *
29
+ * It travels in `X-Ekwo-Api-Key` and the core's `db_pre_request` hook
30
+ * presents it at the top of every request's transaction (decision 0062), so
31
+ * the caller is on the key's company with the key's capabilities and
32
+ * nothing else. Such a request carries **no `Authorization`**: PostgREST
33
+ * decides the role from that header before any function of the core runs,
34
+ * and the hook is what moves the request off `anon`.
35
+ */
36
+ apiKey?: string | undefined;
37
+ /** The `fetch` every request goes through. A host or a test may hand its own. */
38
+ fetch?: typeof globalThis.fetch | undefined;
26
39
  }
40
+ /** The header the core's pre-request hook reads a key out of. */
41
+ export declare const API_KEY_HEADER = "X-Ekwo-Api-Key";
27
42
  /**
28
43
  * Signs in, or takes the token it was given, and returns the backend.
29
44
  *
@@ -1 +1 @@
1
- {"version":3,"file":"postgrest.d.ts","sourceRoot":"","sources":["../src/postgrest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,EAIL,KAAK,OAAO,EAIb,MAAM,cAAc,CAAC;AAuDtB,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,OAAO,CAAC,CAkHzF"}
1
+ {"version":3,"file":"postgrest.d.ts","sourceRoot":"","sources":["../src/postgrest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,EAIL,KAAK,OAAO,EAIb,MAAM,cAAc,CAAC;AAuDtB,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B;;;;;;;;;OASG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,iFAAiF;IACjF,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,GAAG,SAAS,CAAC;CAC7C;AAED,iEAAiE;AACjE,eAAO,MAAM,cAAc,mBAAmB,CAAC;AAkB/C;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,OAAO,CAAC,CA2HzF"}
package/dist/postgrest.js CHANGED
@@ -50,6 +50,23 @@ function unwrap(answer, what) {
50
50
  }
51
51
  return answer.data;
52
52
  }
53
+ /** The header the core's pre-request hook reads a key out of. */
54
+ export const API_KEY_HEADER = 'X-Ekwo-Api-Key';
55
+ /**
56
+ * A `fetch` that never sends `Authorization`.
57
+ *
58
+ * `supabase-js` puts the publishable key in `Authorization` when nothing else
59
+ * is there. With a key of Ekwo OS on the request that is the one header that
60
+ * must be absent, so it is taken off on the way out rather than trusted not to
61
+ * be added.
62
+ */
63
+ function withoutAuthorization(inner) {
64
+ return (input, init) => {
65
+ const headers = new Headers(init?.headers ?? (input instanceof Request ? input.headers : undefined));
66
+ headers.delete('authorization');
67
+ return inner(input, { ...init, headers });
68
+ };
69
+ }
53
70
  /**
54
71
  * Signs in, or takes the token it was given, and returns the backend.
55
72
  *
@@ -58,20 +75,31 @@ function unwrap(answer, what) {
58
75
  * server outlives the first hour without a credential cache existing.
59
76
  */
60
77
  export async function postgrestBackend(options) {
78
+ const apiKey = options.apiKey !== undefined && options.apiKey.length > 0 ? options.apiKey : undefined;
61
79
  const headers = {};
62
- if (options.accessToken !== undefined && options.accessToken.length > 0) {
80
+ if (apiKey !== undefined) {
81
+ headers[API_KEY_HEADER] = apiKey;
82
+ }
83
+ else if (options.accessToken !== undefined && options.accessToken.length > 0) {
63
84
  headers['Authorization'] = `Bearer ${options.accessToken}`;
64
85
  }
86
+ const baseFetch = options.fetch ?? globalThis.fetch;
65
87
  const client = createClient(options.supabaseUrl, options.anonKey, {
66
88
  auth: {
67
89
  persistSession: false,
68
- autoRefreshToken: options.accessToken === undefined,
90
+ autoRefreshToken: apiKey === undefined && options.accessToken === undefined,
69
91
  detectSessionInUrl: false,
70
92
  },
71
- global: { headers },
93
+ global: { headers, fetch: apiKey === undefined ? baseFetch : withoutAuthorization(baseFetch) },
72
94
  });
73
95
  let actingAs;
74
- if (options.accessToken === undefined || options.accessToken.length === 0) {
96
+ if (apiKey !== undefined) {
97
+ // A key is not a person: there is nobody to sign in and no user id to
98
+ // report. What it may do is decided by the capabilities it carries, on
99
+ // the one company it was issued for.
100
+ actingAs = undefined;
101
+ }
102
+ else if (options.accessToken === undefined || options.accessToken.length === 0) {
75
103
  if (options.email === undefined || options.password === undefined) {
76
104
  throw new EkwoMcpError('no_credentials: set EKWO_EMAIL and EKWO_PASSWORD, or EKWO_ACCESS_TOKEN');
77
105
  }
@@ -1 +1 @@
1
- {"version":3,"file":"postgrest.js","sourceRoot":"","sources":["../src/postgrest.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"postgrest.js","sourceRoot":"","sources":["../src/postgrest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,YAAY,EAAuB,MAAM,uBAAuB,CAAC;AAC1E,OAAO,EACL,YAAY,EACZ,OAAO,EACP,UAAU,GAKX,MAAM,cAAc,CAAC;AAetB,SAAS,YAAY,CAA0B,OAAU,EAAE,OAA6B;IACtF,IAAI,GAAG,GAAG,OAAO,CAAC;IAClB,KAAK,MAAM,MAAM,IAAI,OAAO,IAAI,EAAE,EAAE,CAAC;QACnC,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACzC,QAAQ,MAAM,CAAC,EAAE,EAAE,CAAC;YAClB,KAAK,IAAI;gBACP,GAAG,GAAG,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;gBAC3B,MAAM;YACR,KAAK,IAAI;gBACP,GAAG,GAAG,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,KAAc,CAAC,CAAC;gBAC5C,MAAM;YACR,KAAK,OAAO;gBACV,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;gBACtC,MAAM;YACR;gBACE,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,KAAc,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAOD,4EAA4E;AAC5E,SAAS,MAAM,CAAI,MAAiB,EAAE,IAAY;IAChD,IAAI,MAAM,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;QAC1B,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC;QAChD,iEAAiE;QACjE,MAAM,IAAI,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAChH,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,SAAS,CAAC,CAAC;IAC3D,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;QACzB,MAAM,IAAI,YAAY,CAAC,GAAG,IAAI,qBAAqB,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC;AAwBD,iEAAiE;AACjE,MAAM,CAAC,MAAM,cAAc,GAAG,gBAAgB,CAAC;AAE/C;;;;;;;GAOG;AACH,SAAS,oBAAoB,CAAC,KAA8B;IAC1D,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACrB,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,IAAI,EAAE,OAAO,IAAI,CAAC,KAAK,YAAY,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;QACrG,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QAChC,OAAO,KAAK,CAAC,KAAK,EAAE,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IAC5C,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAAgC;IACrE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IACtG,MAAM,OAAO,GAA2B,EAAE,CAAC;IAC3C,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,CAAC,cAAc,CAAC,GAAG,MAAM,CAAC;IACnC,CAAC;SAAM,IAAI,OAAO,CAAC,WAAW,KAAK,SAAS,IAAI,OAAO,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/E,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,OAAO,CAAC,WAAW,EAAE,CAAC;IAC7D,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC;IACpD,MAAM,MAAM,GAAmB,YAAY,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,OAAO,EAAE;QAChF,IAAI,EAAE;YACJ,cAAc,EAAE,KAAK;YACrB,gBAAgB,EAAE,MAAM,KAAK,SAAS,IAAI,OAAO,CAAC,WAAW,KAAK,SAAS;YAC3E,kBAAkB,EAAE,KAAK;SAC1B;QACD,MAAM,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,oBAAoB,CAAC,SAAS,CAAC,EAAE;KAC/F,CAAC,CAAC;IAEH,IAAI,QAA4B,CAAC;IAEjC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,sEAAsE;QACtE,uEAAuE;QACvE,qCAAqC;QACrC,QAAQ,GAAG,SAAS,CAAC;IACvB,CAAC;SAAM,IAAI,OAAO,CAAC,WAAW,KAAK,SAAS,IAAI,OAAO,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjF,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YAClE,MAAM,IAAI,YAAY,CACpB,wEAAwE,CACzE,CAAC;QACJ,CAAC;QACD,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC;YAC3D,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,QAAQ,EAAE,OAAO,CAAC,QAAQ;SAC3B,CAAC,CAAC;QACH,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,MAAM,IAAI,YAAY,CAAC,mBAAmB,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAC7D,CAAC;QACD,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;IAC3B,CAAC;SAAM,CAAC;QACN,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAChE,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;IAC3B,CAAC;IAED;;;;;;;OAOG;IACH,MAAM,EAAE,GAAG,CAAC,MAA0B,EAAiB,EAAE,CACvD,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAE,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAA8B,CAAC;IAElG,OAAO;QACL,IAAI,EAAE,WAAW;QACjB,QAAQ;QAER,KAAK,CAAC,GAAG,CAAI,EAAU,EAAE,OAAgC,EAAE,EAAE,MAAe;YAC1E,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAoB,CAAC;YAC/E,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAChC,oEAAoE;YACpE,gEAAgE;YAChE,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAQ,CAAC;QACtD,CAAC;QAED,KAAK,CAAC,OAAO,CAAC,EAAU,EAAE,OAAgC,EAAE,EAAE,MAAe;YAC3E,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAoB,CAAC;YAC/E,IAAI,MAAM,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;gBAC1B,MAAM,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACtC,CAAC;QACH,CAAC;QAED,KAAK,CAAC,MAAM,CAAI,KAAkB;YAChC,IAAI,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YAC7F,OAAO,GAAG,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;YAC7C,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;gBACtC,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,KAAK,KAAK,EAAE,CAAC,CAAC;YAC9F,CAAC;YACD,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;gBAAE,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACpE,OAAO,MAAM,CAAC,CAAC,MAAM,OAAO,CAAgB,EAAE,eAAe,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;QAC9E,CAAC;QAED,KAAK,CAAC,MAAM,CACV,KAAa,EACb,IAAW,EACX,YAAsB,CAAC,GAAG,CAAC,EAC3B,MAAe;YAEf,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC;iBAC7B,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;iBACvB,MAAM,CAAC,IAAI,CAAC;iBACZ,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAgB,CAAC;YAC/C,OAAO,MAAM,CAAC,MAAM,EAAE,eAAe,KAAK,EAAE,CAAC,CAAC;QAChD,CAAC;QAED,KAAK,CAAC,MAAM,CACV,KAAa,EACb,KAAU,EACV,KAAe,EACf,YAAsB,CAAC,GAAG,CAAC,EAC3B,MAAe;YAEf,IAAI,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC/D,OAAO,GAAG,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YACvC,MAAM,MAAM,GAAG,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAgB,CAAC;YAC1E,OAAO,MAAM,CAAC,MAAM,EAAE,UAAU,KAAK,EAAE,CAAC,CAAC;QAC3C,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,KAAe,EAAE,MAAe;YAC1D,IAAI,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;YAC1D,OAAO,GAAG,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YACvC,MAAM,MAAM,GAAG,CAAC,MAAM,OAAO,CAAoB,CAAC;YAClD,IAAI,MAAM,CAAC,KAAK,KAAK,IAAI;gBAAE,MAAM,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACjE,CAAC;QAED,KAAK,CAAC,KAAK;YACT,4DAA4D;YAC5D,MAAM,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC;QACtC,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * The one rounding rule of Ekwo: **half up, on the absolute value, at the
3
+ * currency's decimals**.
4
+ *
5
+ * Three packages used to answer this differently — `Math.round((v + EPSILON) *
6
+ * 100) / 100`, `Math.round(v * 100) / 100` and `Number.prototype.toFixed(2)` —
7
+ * and the three disagreed on the two cases that matter: a negative half, where
8
+ * `Math.round` goes towards positive infinity and turns -0.005 into -0.00, and
9
+ * a value a binary float cannot hold, where 2.675 becomes 2.67 because
10
+ * `2.675 * 100` is really 267.49999999999994. A credit note is a sale with the
11
+ * sign flipped; a rule that treats the two differently puts a cent between an
12
+ * invoice and its credit note, and the cent is found by the person filing the
13
+ * return.
14
+ *
15
+ * Half up on the absolute value is what an invoice, a VAT return and a set of
16
+ * annual accounts are written with, and it is symmetric by construction: the
17
+ * rounding of -x is the rounding of x with the sign put back.
18
+ *
19
+ * The file is deliberately identical in every package that holds a copy. A
20
+ * format brick may not import the core or another brick, so the rule is
21
+ * duplicated rather than shared — and `tests/rounding.test.ts` reads the
22
+ * copies and refuses one that has drifted. See `docs/decisions.md`.
23
+ */
24
+ export declare function roundCurrency(value: number, decimals?: number): number;
25
+ //# sourceMappingURL=rounding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rounding.d.ts","sourceRoot":"","sources":["../src/rounding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,SAAI,GAAG,MAAM,CAUjE"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * The one rounding rule of Ekwo: **half up, on the absolute value, at the
3
+ * currency's decimals**.
4
+ *
5
+ * Three packages used to answer this differently — `Math.round((v + EPSILON) *
6
+ * 100) / 100`, `Math.round(v * 100) / 100` and `Number.prototype.toFixed(2)` —
7
+ * and the three disagreed on the two cases that matter: a negative half, where
8
+ * `Math.round` goes towards positive infinity and turns -0.005 into -0.00, and
9
+ * a value a binary float cannot hold, where 2.675 becomes 2.67 because
10
+ * `2.675 * 100` is really 267.49999999999994. A credit note is a sale with the
11
+ * sign flipped; a rule that treats the two differently puts a cent between an
12
+ * invoice and its credit note, and the cent is found by the person filing the
13
+ * return.
14
+ *
15
+ * Half up on the absolute value is what an invoice, a VAT return and a set of
16
+ * annual accounts are written with, and it is symmetric by construction: the
17
+ * rounding of -x is the rounding of x with the sign put back.
18
+ *
19
+ * The file is deliberately identical in every package that holds a copy. A
20
+ * format brick may not import the core or another brick, so the rule is
21
+ * duplicated rather than shared — and `tests/rounding.test.ts` reads the
22
+ * copies and refuses one that has drifted. See `docs/decisions.md`.
23
+ */
24
+ export function roundCurrency(value, decimals = 2) {
25
+ const factor = 10 ** decimals;
26
+ const scaled = Math.abs(value) * factor;
27
+ // The nudge is proportional to the number, which is what makes it work at
28
+ // 1.005 and at 1000000.005 alike, and far too small to move a value that is
29
+ // not already within a bit of the halfway point.
30
+ const rounded = Math.round(scaled + Number.EPSILON * scaled);
31
+ // `-0` is a value of its own in JavaScript and it prints as "-0.00".
32
+ // Adding zero turns it back into `0`.
33
+ return (value < 0 ? -rounded : rounded) / factor + 0;
34
+ }
35
+ //# sourceMappingURL=rounding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rounding.js","sourceRoot":"","sources":["../src/rounding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa,EAAE,QAAQ,GAAG,CAAC;IACvD,MAAM,MAAM,GAAG,EAAE,IAAI,QAAQ,CAAC;IAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC;IACxC,0EAA0E;IAC1E,4EAA4E;IAC5E,iDAAiD;IACjD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,CAAC;IAC7D,qEAAqE;IACrE,sCAAsC;IACtC,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC;AACvD,CAAC"}
package/dist/schema.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * What this server needs of the database it is pointed at.
3
3
  *
4
- * An MCP client is installed by whoever wants an assistant, and the database
4
+ * An MCP client is installed by whoever wants an agent, and the database
5
5
  * it reaches was installed by whoever runs the books — two decisions, two
6
6
  * dates. So the server asks the schema its version before it answers anything,
7
7
  * and refuses one it is too new for, by name. The alternative is what an
8
- * assistant does with a missing column: it improvises, and the improvisation
8
+ * agent does with a missing column: it improvises, and the improvisation
9
9
  * is an accounting entry.
10
10
  *
11
11
  * Declared in `package.json` under `ekwo.schemaMin`, as a country pack
@@ -14,7 +14,7 @@
14
14
  */
15
15
  import { type Backend } from './backend.js';
16
16
  /** The oldest schema this server speaks to. */
17
- export declare const SCHEMA_MIN = "0.8.0";
17
+ export declare const SCHEMA_MIN = "0.9.0";
18
18
  /** The version the migrations of that database define. */
19
19
  export declare function installedSchemaVersion(backend: Backend): Promise<string | undefined>;
20
20
  /**