rlz-engine 1.0.53 → 1.0.55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/README.md +225 -0
  2. package/dist/back/auth/admin-secret.d.ts +4 -0
  3. package/dist/back/auth/admin-secret.js +86 -0
  4. package/dist/back/auth/admin-secret.js.map +1 -0
  5. package/dist/back/auth/cookies.d.ts +12 -0
  6. package/dist/back/auth/cookies.js +20 -0
  7. package/dist/back/auth/cookies.js.map +1 -0
  8. package/dist/back/auth/csrf.d.ts +8 -0
  9. package/dist/back/auth/csrf.js +47 -0
  10. package/dist/back/auth/csrf.js.map +1 -0
  11. package/dist/back/auth/model.d.ts +7 -3
  12. package/dist/back/auth/module.d.ts +14 -0
  13. package/dist/back/auth/module.js +121 -0
  14. package/dist/back/auth/module.js.map +1 -0
  15. package/dist/back/auth/rate-limit.d.ts +11 -0
  16. package/dist/back/auth/rate-limit.js +59 -0
  17. package/dist/back/auth/rate-limit.js.map +1 -0
  18. package/dist/back/auth/session.d.ts +22 -0
  19. package/dist/back/auth/session.js +55 -0
  20. package/dist/back/auth/session.js.map +1 -0
  21. package/dist/back/auth/storage.d.ts +9 -9
  22. package/dist/back/auth/storage.js +39 -36
  23. package/dist/back/auth/storage.js.map +1 -1
  24. package/dist/back/auth/utils.d.ts +10 -8
  25. package/dist/back/auth/utils.js +43 -56
  26. package/dist/back/auth/utils.js.map +1 -1
  27. package/dist/back/certificate/adm-rpc.d.ts +5 -0
  28. package/dist/back/certificate/adm-rpc.js +52 -0
  29. package/dist/back/certificate/adm-rpc.js.map +1 -0
  30. package/dist/back/certificate/module.d.ts +13 -0
  31. package/dist/back/certificate/module.js +19 -0
  32. package/dist/back/certificate/module.js.map +1 -0
  33. package/dist/back/cli/cli-engine.d.ts +25 -0
  34. package/dist/back/cli/cli-engine.js +68 -0
  35. package/dist/back/cli/cli-engine.js.map +1 -0
  36. package/dist/back/http/module.d.ts +7 -0
  37. package/dist/back/http/module.js +34 -0
  38. package/dist/back/http/module.js.map +1 -0
  39. package/dist/back/http/server.d.ts +22 -0
  40. package/dist/back/http/server.js +126 -0
  41. package/dist/back/http/server.js.map +1 -0
  42. package/dist/back/logger/adm-rpc.d.ts +2 -0
  43. package/dist/back/logger/adm-rpc.js +50 -0
  44. package/dist/back/logger/adm-rpc.js.map +1 -0
  45. package/dist/back/logger/audit-logger.d.ts +97 -0
  46. package/dist/back/logger/audit-logger.js +155 -0
  47. package/dist/back/logger/audit-logger.js.map +1 -0
  48. package/dist/back/logger/cli.d.ts +2 -0
  49. package/dist/back/logger/cli.js +43 -0
  50. package/dist/back/logger/cli.js.map +1 -0
  51. package/dist/back/logger/format.d.ts +3 -0
  52. package/dist/back/logger/format.js +27 -0
  53. package/dist/back/logger/format.js.map +1 -0
  54. package/dist/back/logger/module.d.ts +14 -0
  55. package/dist/back/logger/module.js +24 -0
  56. package/dist/back/logger/module.js.map +1 -0
  57. package/dist/back/logger/sqlite-storage.d.ts +27 -0
  58. package/dist/back/logger/sqlite-storage.js +169 -0
  59. package/dist/back/logger/sqlite-storage.js.map +1 -0
  60. package/dist/back/logger/system-logger.d.ts +27 -0
  61. package/dist/back/logger/system-logger.js +82 -0
  62. package/dist/back/logger/system-logger.js.map +1 -0
  63. package/dist/back/module/composer.d.ts +34 -0
  64. package/dist/back/module/composer.js +57 -0
  65. package/dist/back/module/composer.js.map +1 -0
  66. package/dist/back/rpc/gen.d.ts +2 -1
  67. package/dist/back/rpc/gen.js +38 -17
  68. package/dist/back/rpc/gen.js.map +1 -1
  69. package/dist/back/rpc/module.d.ts +14 -0
  70. package/dist/back/rpc/module.js +43 -0
  71. package/dist/back/rpc/module.js.map +1 -0
  72. package/dist/back/rpc/rpc.d.ts +53 -6
  73. package/dist/back/rpc/rpc.js +72 -29
  74. package/dist/back/rpc/rpc.js.map +1 -1
  75. package/dist/back/storage/db.js +5 -3
  76. package/dist/back/storage/db.js.map +1 -1
  77. package/dist/back/storage/model.d.ts +2 -2
  78. package/dist/back/storage/model.js +2 -2
  79. package/dist/back/storage/model.js.map +1 -1
  80. package/dist/back/storage/sync.d.ts +5 -2
  81. package/dist/back/storage/sync.js +1 -3
  82. package/dist/back/storage/sync.js.map +1 -1
  83. package/dist/client/adm/admin.d.ts +17 -0
  84. package/dist/client/adm/admin.js +62 -0
  85. package/dist/client/adm/admin.js.map +1 -0
  86. package/dist/client/adm/audit-logs.d.ts +5 -0
  87. package/dist/client/adm/audit-logs.js +68 -0
  88. package/dist/client/adm/audit-logs.js.map +1 -0
  89. package/dist/client/adm/certificate.d.ts +5 -0
  90. package/dist/client/adm/certificate.js +48 -0
  91. package/dist/client/adm/certificate.js.map +1 -0
  92. package/dist/client/config.d.ts +2 -0
  93. package/dist/client/config.js +7 -0
  94. package/dist/client/config.js.map +1 -1
  95. package/dist/client/rpc.d.ts +4 -4
  96. package/dist/client/rpc.js +19 -7
  97. package/dist/client/rpc.js.map +1 -1
  98. package/dist/client/screens/404.js.map +1 -1
  99. package/dist/client/screens/SignupSigninScreen.d.ts +13 -1
  100. package/dist/client/screens/SignupSigninScreen.js +41 -37
  101. package/dist/client/screens/SignupSigninScreen.js.map +1 -1
  102. package/dist/client/state/auth.d.ts +13 -7
  103. package/dist/client/state/auth.js +24 -19
  104. package/dist/client/state/auth.js.map +1 -1
  105. package/dist/client/sync.d.ts +7 -2
  106. package/dist/client/sync.js +5 -3
  107. package/dist/client/sync.js.map +1 -1
  108. package/dist/client/widgets/ItemsSelect.js +15 -8
  109. package/dist/client/widgets/ItemsSelect.js.map +1 -1
  110. package/package.json +87 -77
  111. package/dist/back/auth/controllers.d.ts +0 -7
  112. package/dist/back/auth/controllers.js +0 -39
  113. package/dist/back/auth/controllers.js.map +0 -1
  114. package/dist/back/esbuild-plugin-pino.d.ts +0 -6
  115. package/dist/back/esbuild-plugin-pino.js +0 -87
  116. package/dist/back/esbuild-plugin-pino.js.map +0 -1
  117. package/dist/back/logger.d.ts +0 -7
  118. package/dist/back/logger.js +0 -43
  119. package/dist/back/logger.js.map +0 -1
  120. package/dist/back/server.d.ts +0 -17
  121. package/dist/back/server.js +0 -94
  122. package/dist/back/server.js.map +0 -1
  123. package/dist/client/api/api.d.ts +0 -22
  124. package/dist/client/api/api.js +0 -87
  125. package/dist/client/api/api.js.map +0 -1
  126. package/dist/client/api/auth.d.ts +0 -5
  127. package/dist/client/api/auth.js +0 -22
  128. package/dist/client/api/auth.js.map +0 -1
  129. package/dist/shared/api/auth.d.ts +0 -19
  130. package/dist/shared/api/auth.js +0 -17
  131. package/dist/shared/api/auth.js.map +0 -1
  132. package/dist/shared/api/sync.d.ts +0 -21
  133. package/dist/shared/api/sync.js +0 -22
  134. package/dist/shared/api/sync.js.map +0 -1
@@ -0,0 +1,25 @@
1
+ /** One command leaf exposed under a CLI module namespace. */
2
+ export interface CliCommand {
3
+ readonly description: string;
4
+ readonly args?: Readonly<Record<string, any>>;
5
+ readonly handler: (args: Record<string, any>) => void | Promise<void>;
6
+ }
7
+ /** A namespaced group of related commands, such as `http start`. */
8
+ export interface CliModule {
9
+ readonly name: string;
10
+ readonly description: string;
11
+ readonly commands: Readonly<Record<string, CliCommand>>;
12
+ }
13
+ /** Builds and runs an application's operational command tree. */
14
+ export declare class CliEngine {
15
+ private readonly binaryName;
16
+ private readonly modules;
17
+ constructor(binaryName?: string);
18
+ /** Add a module; duplicate names and invalid command metadata are rejected. */
19
+ register(module: CliModule): this;
20
+ /** Parse and execute arguments, defaulting to the current process arguments. */
21
+ run(argv?: readonly string[]): Promise<void>;
22
+ }
23
+ /** Development-only commands belong in a separate entry point from the application's operational CLI. */
24
+ export declare class DevCliEngine extends CliEngine {
25
+ }
@@ -0,0 +1,68 @@
1
+ import { command, run as runCommand, subcommands } from 'cmd-ts';
2
+ /** Builds and runs an application's operational command tree. */
3
+ export class CliEngine {
4
+ binaryName;
5
+ modules = new Map();
6
+ constructor(binaryName = 'app.js') {
7
+ this.binaryName = binaryName;
8
+ }
9
+ /** Add a module; duplicate names and invalid command metadata are rejected. */
10
+ register(module) {
11
+ validateName(module.name, 'module');
12
+ validateDescription(module.description, `module ${module.name}`);
13
+ if (this.modules.has(module.name)) {
14
+ throw new Error(`CLI module already registered: ${module.name}`);
15
+ }
16
+ const commands = Object.keys(module.commands);
17
+ if (commands.length === 0) {
18
+ throw new Error(`CLI module has no commands: ${module.name}`);
19
+ }
20
+ for (const [name, commandDefinition] of Object.entries(module.commands)) {
21
+ validateName(name, 'command');
22
+ if (commandDefinition.description.trim() === '') {
23
+ throw new Error(`CLI command ${module.name} ${name} must have a description.`);
24
+ }
25
+ }
26
+ this.modules.set(module.name, module);
27
+ return this;
28
+ }
29
+ /** Parse and execute arguments, defaulting to the current process arguments. */
30
+ async run(argv = process.argv.slice(2)) {
31
+ const modules = Object.fromEntries([...this.modules].map(([name, module]) => [
32
+ name,
33
+ subcommands({
34
+ name,
35
+ description: module.description,
36
+ cmds: Object.fromEntries(Object.entries(module.commands).map(([commandName, definition]) => [
37
+ commandName,
38
+ command({
39
+ name: commandName,
40
+ description: definition.description,
41
+ args: { ...definition.args },
42
+ handler: definition.handler
43
+ })
44
+ ]))
45
+ })
46
+ ]));
47
+ const app = subcommands({
48
+ name: this.binaryName,
49
+ description: 'Application command line interface.',
50
+ cmds: modules
51
+ });
52
+ await runCommand(app, [...argv]);
53
+ }
54
+ }
55
+ /** Development-only commands belong in a separate entry point from the application's operational CLI. */
56
+ export class DevCliEngine extends CliEngine {
57
+ }
58
+ function validateName(name, kind) {
59
+ if (!/^[a-z][a-z0-9-]*$/.test(name)) {
60
+ throw new Error(`Invalid CLI ${kind} name: ${name}`);
61
+ }
62
+ }
63
+ function validateDescription(description, subject) {
64
+ if (description.trim() === '' || description.includes('\n')) {
65
+ throw new Error(`CLI ${subject} must have a one-line description.`);
66
+ }
67
+ }
68
+ //# sourceMappingURL=cli-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-engine.js","sourceRoot":"","sources":["../../../src/back/cli/cli-engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,GAAG,IAAI,UAAU,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAA;AAgBhE,iEAAiE;AACjE,MAAM,OAAO,SAAS;IAGW,UAAU;IAFtB,OAAO,GAAG,IAAI,GAAG,EAAqB,CAAA;IAEvD,YAA6B,UAAU,GAAG,QAAQ;0BAArB,UAAU;IAAc,CAAC;IAEtD,+EAA+E;IAC/E,QAAQ,CAAC,MAAiB;QACtB,YAAY,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;QACnC,mBAAmB,CAAC,MAAM,CAAC,WAAW,EAAE,UAAU,MAAM,CAAC,IAAI,EAAE,CAAC,CAAA;QAChE,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,kCAAkC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAA;QACpE,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;QAC7C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,+BAA+B,MAAM,CAAC,IAAI,EAAE,CAAC,CAAA;QACjE,CAAC;QACD,KAAK,MAAM,CAAC,IAAI,EAAE,iBAAiB,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;YACtE,YAAY,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;YAC7B,IAAI,iBAAiB,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;gBAC9C,MAAM,IAAI,KAAK,CAAC,eAAe,MAAM,CAAC,IAAI,IAAI,IAAI,2BAA2B,CAAC,CAAA;YAClF,CAAC;QACL,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QACrC,OAAO,IAAI,CAAA;IACf,CAAC;IAED,gFAAgF;IAChF,KAAK,CAAC,GAAG,CAAC,IAAI,GAAsB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QACrD,MAAM,OAAO,GAAG,MAAM,CAAC,WAAW,CAC9B,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;YACtC,IAAI;YACJ,WAAW,CAAC;gBACR,IAAI;gBACJ,WAAW,EAAE,MAAM,CAAC,WAAW;gBAC/B,IAAI,EAAE,MAAM,CAAC,WAAW,CACpB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC;oBAC/D,WAAW;oBACX,OAAO,CAAC;wBACJ,IAAI,EAAE,WAAW;wBACjB,WAAW,EAAE,UAAU,CAAC,WAAW;wBACnC,IAAI,EAAE,EAAE,GAAG,UAAU,CAAC,IAAI,EAAE;wBAC5B,OAAO,EAAE,UAAU,CAAC,OAAO;qBAC9B,CAAC;iBACL,CAAC,CACL;aACJ,CAAC;SACL,CAAC,CACL,CAAA;QACD,MAAM,GAAG,GAAG,WAAW,CAAC;YACpB,IAAI,EAAE,IAAI,CAAC,UAAU;YACrB,WAAW,EAAE,qCAAqC;YAClD,IAAI,EAAE,OAAO;SAChB,CAAC,CAAA;QACF,MAAM,UAAU,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAA;IACpC,CAAC;CACJ;AAED,yGAAyG;AACzG,MAAM,OAAO,YAAa,SAAQ,SAAS;CAAG;AAE9C,SAAS,YAAY,CAAC,IAAY,EAAE,IAAY;IAC5C,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,UAAU,IAAI,EAAE,CAAC,CAAA;IACxD,CAAC;AACL,CAAC;AAED,SAAS,mBAAmB,CAAC,WAAmB,EAAE,OAAe;IAC7D,IAAI,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,OAAO,OAAO,oCAAoC,CAAC,CAAA;IACvE,CAAC;AACL,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { InitServerFuncType, RunServerParams } from './server.js';
2
+ import { CliModule } from '../cli/cli-engine.js';
3
+ /** Fastify lifecycle feature; applications provide deployment settings and route setup. */
4
+ export declare const HTTP_MODULE: {
5
+ /** Create the `http start` command using application-owned server configuration. */
6
+ makeCli(params: Omit<RunServerParams, 'init'> | (() => Omit<RunServerParams, 'init'>), init: InitServerFuncType): CliModule;
7
+ };
@@ -0,0 +1,34 @@
1
+ import { flag } from 'cmd-ts';
2
+ import { runServer } from './server.js';
3
+ /** Fastify lifecycle feature; applications provide deployment settings and route setup. */
4
+ export const HTTP_MODULE = {
5
+ /** Create the `http start` command using application-owned server configuration. */
6
+ makeCli(params, init) {
7
+ return {
8
+ name: 'http',
9
+ description: 'Start the application HTTP server.',
10
+ commands: {
11
+ start: {
12
+ description: 'Start the Fastify server using the deployment settings and route initialization supplied by the application. The process remains active until it receives a termination signal.',
13
+ args: {
14
+ debug: flag({ long: 'debug', description: 'Enable debug logging.' }),
15
+ auditSqlite: flag({
16
+ long: 'audit-sqlite',
17
+ description: 'Also write audit logs to SQLite when console logging is enabled.'
18
+ })
19
+ },
20
+ handler: async ({ debug, auditSqlite }) => {
21
+ const serverParams = typeof params === 'function' ? params() : params;
22
+ await runServer({
23
+ ...serverParams,
24
+ debug: debug || serverParams.debug,
25
+ auditSqlite: auditSqlite || serverParams.auditSqlite,
26
+ init
27
+ });
28
+ }
29
+ }
30
+ }
31
+ };
32
+ }
33
+ };
34
+ //# sourceMappingURL=module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module.js","sourceRoot":"","sources":["../../../src/back/http/module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAE7B,OAAO,EAAuC,SAAS,EAAE,MAAM,aAAa,CAAA;AAG5E,2FAA2F;AAC3F,MAAM,CAAC,MAAM,WAAW,GAAG;IACvB,oFAAoF;IACpF,OAAO,CAAC,MAA6E,EAAE,IAAwB;QAC3G,OAAO;YACH,IAAI,EAAE,MAAM;YACZ,WAAW,EAAE,oCAAoC;YACjD,QAAQ,EAAE;gBACN,KAAK,EAAE;oBACH,WAAW,EACP,iLAAiL;oBACrL,IAAI,EAAE;wBACF,KAAK,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,uBAAuB,EAAE,CAAC;wBACpE,WAAW,EAAE,IAAI,CAAC;4BACd,IAAI,EAAE,cAAc;4BACpB,WAAW,EAAE,kEAAkE;yBAClF,CAAC;qBACL;oBACD,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE;wBACtC,MAAM,YAAY,GAAG,OAAO,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAA;wBACrE,MAAM,SAAS,CAAC;4BACZ,GAAG,YAAY;4BACf,KAAK,EAAE,KAAK,IAAI,YAAY,CAAC,KAAK;4BAClC,WAAW,EAAE,WAAW,IAAI,YAAY,CAAC,WAAW;4BACpD,IAAI;yBACP,CAAC,CAAA;oBACN,CAAC;iBACJ;aACJ;SACJ,CAAA;IACL,CAAC;CACJ,CAAA"}
@@ -0,0 +1,22 @@
1
+ import { FastifyBaseLogger, FastifyInstance, RawReplyDefaultExpression, RawRequestDefaultExpression, RawServerBase } from 'fastify';
2
+ import { type AcmeProvider } from 'fastify-acme';
3
+ export type InitServerFuncType = <S extends RawServerBase>(server: FastifyInstance<S, RawRequestDefaultExpression<S>, RawReplyDefaultExpression<S>, FastifyBaseLogger>) => Promise<void>;
4
+ export interface RunServerParams {
5
+ production: boolean;
6
+ debug?: boolean;
7
+ unsecurePort?: number;
8
+ securePort?: number;
9
+ domain: string;
10
+ certDir: string;
11
+ /** Audit retention age, in milliseconds. Defaults to 30 days. */
12
+ auditRetentionMs?: number;
13
+ /** Global maximum audit record count. Defaults to 100,000. */
14
+ auditMaxRecords?: number;
15
+ /** Also persist audit records in SQLite while using the console sink. */
16
+ auditSqlite?: boolean;
17
+ /** Certificate authority used for ACME issuance and renewal. Defaults to Let's Encrypt. */
18
+ acmeProvider?: AcmeProvider;
19
+ staticDir: string;
20
+ init: InitServerFuncType;
21
+ }
22
+ export declare function runServer({ production, debug, domain, certDir, auditRetentionMs, auditMaxRecords, auditSqlite, acmeProvider, staticDir, securePort, unsecurePort, init }: RunServerParams): Promise<() => Promise<void>>;
@@ -0,0 +1,126 @@
1
+ import fastifyCompress from '@fastify/compress';
2
+ import fastifyCookie from '@fastify/cookie';
3
+ import fastifyCors from '@fastify/cors';
4
+ import { fastifyResponseValidation } from '@fastify/response-validation';
5
+ import fastifySensible, { httpErrors } from '@fastify/sensible';
6
+ import fastifyStatic from '@fastify/static';
7
+ import formatsPlugin from 'ajv-formats';
8
+ import fastify from 'fastify';
9
+ import { fastifyAcmeSecurePlugin, fastifyAcmeUnsecurePlugin, getCertAndKey } from 'fastify-acme';
10
+ import { createReadStream } from 'fs';
11
+ import { installIntoGlobal } from 'iterator-helpers-polyfill';
12
+ import path from 'path';
13
+ import { initAuditLogger } from '../logger/audit-logger.js';
14
+ import { getSystemLogger } from '../logger/system-logger.js';
15
+ const DEFAULT_AUDIT_RETENTION_MS = 30 * 24 * 60 * 60 * 1000;
16
+ const DEFAULT_AUDIT_MAX_RECORDS = 100_000;
17
+ const ajvFormatsPlugin = (ajv) => {
18
+ if (ajv.getKeyword('formatMaximum') === undefined)
19
+ formatsPlugin.default(ajv);
20
+ if (ajv.formats?.uuid === undefined) {
21
+ ajv.addFormat('uuid', /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i);
22
+ }
23
+ return ajv;
24
+ };
25
+ installIntoGlobal();
26
+ export async function runServer({ production, debug = false, domain, certDir, auditRetentionMs = DEFAULT_AUDIT_RETENTION_MS, auditMaxRecords = DEFAULT_AUDIT_MAX_RECORDS, auditSqlite = false, acmeProvider, staticDir, securePort, unsecurePort, init }) {
27
+ const sqliteConfig = { path: path.resolve('logs.sqlite'), retentionMs: auditRetentionMs, maxRecords: auditMaxRecords };
28
+ const auditLoggerConfig = production && !debug
29
+ ? { mode: 'sqlite', ...sqliteConfig }
30
+ : auditSqlite
31
+ ? { mode: 'sqlite+console', ...sqliteConfig }
32
+ : { mode: 'console' };
33
+ const closeAuditLogger = initAuditLogger(auditLoggerConfig);
34
+ try {
35
+ const L = getSystemLogger('init', { debug });
36
+ L.info({ production }, 'runServer');
37
+ const httpServer = fastify({
38
+ loggerInstance: getSystemLogger('http', { debug }),
39
+ ajv: {
40
+ plugins: [ajvFormatsPlugin],
41
+ customOptions: { useDefaults: false, coerceTypes: false, allErrors: true, verbose: true }
42
+ }
43
+ });
44
+ if (!production) {
45
+ await httpServer.register(fastifyCookie);
46
+ await httpServer.register(fastifyCors, {
47
+ methods: ['get', 'post']
48
+ });
49
+ await httpServer.register(fastifyCompress);
50
+ await httpServer.register(fastifySensible);
51
+ await httpServer.register(fastifyResponseValidation, {
52
+ ajv: { plugins: [ajvFormatsPlugin], useDefaults: false, coerceTypes: false, allErrors: true, verbose: true }
53
+ });
54
+ await init(httpServer);
55
+ addStaticEndpoints(httpServer, staticDir);
56
+ await httpServer.listen({ port: unsecurePort ?? 8080 });
57
+ return async () => {
58
+ try {
59
+ await httpServer.close();
60
+ }
61
+ finally {
62
+ closeAuditLogger();
63
+ }
64
+ };
65
+ }
66
+ httpServer.register(fastifyAcmeUnsecurePlugin, { redirectDomain: domain });
67
+ await httpServer.listen({ port: unsecurePort ?? 80, host: '::' });
68
+ L.info('Get certificates');
69
+ const certAndKey = await getCertAndKey(certDir, domain, httpServer.log, acmeProvider);
70
+ L.info('Init secure server');
71
+ const httpsServer = fastify({
72
+ http2: true,
73
+ https: {
74
+ allowHTTP1: true,
75
+ cert: certAndKey.cert,
76
+ key: certAndKey.pkey
77
+ },
78
+ loggerInstance: getSystemLogger('https', { debug }),
79
+ ajv: {
80
+ plugins: [ajvFormatsPlugin],
81
+ customOptions: { useDefaults: false, coerceTypes: false, allErrors: true, verbose: true }
82
+ }
83
+ });
84
+ await httpsServer.register(fastifyCookie);
85
+ await httpsServer.register(fastifyAcmeSecurePlugin, {
86
+ certDir,
87
+ domain,
88
+ provider: acmeProvider
89
+ });
90
+ await httpsServer.register(fastifyCompress);
91
+ await httpsServer.register(fastifySensible);
92
+ await httpsServer.register(fastifyResponseValidation, {
93
+ ajv: { plugins: [ajvFormatsPlugin], useDefaults: false, coerceTypes: false, allErrors: true, verbose: true }
94
+ });
95
+ await init(httpsServer);
96
+ httpsServer.all('/rpc/*', async () => {
97
+ return httpErrors.notFound();
98
+ });
99
+ addStaticEndpoints(httpsServer, staticDir);
100
+ await httpsServer.listen({ port: securePort ?? 443, host: '::' });
101
+ L.info('runServer done');
102
+ return async () => {
103
+ try {
104
+ await Promise.all([httpServer.close(), httpsServer.close()]);
105
+ }
106
+ finally {
107
+ closeAuditLogger();
108
+ }
109
+ };
110
+ }
111
+ catch (error) {
112
+ closeAuditLogger();
113
+ throw error;
114
+ }
115
+ }
116
+ function addStaticEndpoints(server, staticPath) {
117
+ const absStaticPath = path.resolve(staticPath);
118
+ const absIndexPath = path.join(absStaticPath, 'index.html');
119
+ server.register((s) => {
120
+ s.register(fastifyStatic, { root: absStaticPath });
121
+ s.setNotFoundHandler(async (_req, resp) => {
122
+ await resp.type('text/html').send(createReadStream(absIndexPath));
123
+ });
124
+ });
125
+ }
126
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/back/http/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ /** Creates the administrative endpoint for browsing the active SQLite audit log. */
2
+ export declare function makeAuditLogAdmRpc(): import("../rpc/rpc.js").AdmRpcPluginBuilder<import("../rpc/rpc.js").AdmRpcPluginOptions>;
@@ -0,0 +1,50 @@
1
+ import z from 'zod';
2
+ import { admRpc } from '../rpc/rpc.js';
3
+ import { getAuditLogReader } from './audit-logger.js';
4
+ const auditLogQuerySchema = z.object({
5
+ from: z
6
+ .string()
7
+ .regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/)
8
+ .optional(),
9
+ to: z
10
+ .string()
11
+ .regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/)
12
+ .optional(),
13
+ module: z.string().min(1).optional(),
14
+ level: z.enum(['fatal', 'error', 'warn', 'info', 'debug', 'trace']).optional(),
15
+ limit: z.number().int().min(1).max(1000).optional(),
16
+ offset: z.number().int().min(0).optional()
17
+ });
18
+ const auditLogPageSchema = z.object({
19
+ records: z.array(z.object({
20
+ id: z.number().int().nonnegative(),
21
+ time: z.string(),
22
+ level: z.enum(['fatal', 'error', 'warn', 'info', 'debug', 'trace']),
23
+ module: z.string(),
24
+ type: z.string(),
25
+ data: z.record(z.string(), z.unknown()).optional(),
26
+ error: z.object({ name: z.string(), message: z.string(), stack: z.string().optional() }).optional()
27
+ })),
28
+ total: z.number().int().nonnegative()
29
+ });
30
+ /** Creates the administrative endpoint for browsing the active SQLite audit log. */
31
+ export function makeAuditLogAdmRpc() {
32
+ return admRpc('audit').add({
33
+ name: 'logs',
34
+ v: 1,
35
+ bodySchema: auditLogQuerySchema,
36
+ respSchema: auditLogPageSchema,
37
+ action: (body) => {
38
+ const query = {
39
+ ...(body.from === undefined ? {} : { from: body.from }),
40
+ ...(body.to === undefined ? {} : { to: body.to }),
41
+ ...(body.module === undefined ? {} : { module: body.module }),
42
+ ...(body.level === undefined ? {} : { level: body.level }),
43
+ limit: body.limit ?? 100,
44
+ offset: body.offset ?? 0
45
+ };
46
+ return getAuditLogReader().read(query);
47
+ }
48
+ });
49
+ }
50
+ //# sourceMappingURL=adm-rpc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adm-rpc.js","sourceRoot":"","sources":["../../../src/back/logger/adm-rpc.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,97 @@
1
+ export type LogLevel = 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace';
2
+ /** An application event passed to an audit logger. Define an app-specific union for strict typing. */
3
+ export interface AuditEvent {
4
+ type: string;
5
+ [field: string]: unknown;
6
+ }
7
+ export interface AuditErrorRecord {
8
+ name: string;
9
+ message: string;
10
+ stack?: string;
11
+ }
12
+ export interface AuditRecord {
13
+ time: string;
14
+ level: LogLevel;
15
+ module: string;
16
+ type: string;
17
+ data?: Record<string, unknown>;
18
+ error?: AuditErrorRecord;
19
+ }
20
+ export interface AuditLogEntry extends AuditRecord {
21
+ id: number;
22
+ }
23
+ export interface AuditLogQuery {
24
+ from?: string;
25
+ to?: string;
26
+ module?: string;
27
+ level?: LogLevel;
28
+ limit: number;
29
+ offset: number;
30
+ }
31
+ export interface AuditLogPage {
32
+ records: AuditLogEntry[];
33
+ total: number;
34
+ }
35
+ interface ConsoleAuditLoggerConfig {
36
+ mode: 'console';
37
+ color?: boolean;
38
+ }
39
+ interface SqliteAuditLoggerConfig {
40
+ mode: 'sqlite';
41
+ path: string;
42
+ retentionMs: number;
43
+ maxRecords: number;
44
+ cleanupIntervalMs?: number;
45
+ }
46
+ interface SqliteAndConsoleAuditLoggerConfig extends Omit<SqliteAuditLoggerConfig, 'mode'> {
47
+ mode: 'sqlite+console';
48
+ color?: boolean;
49
+ }
50
+ export type AuditLoggerConfig = ConsoleAuditLoggerConfig | SqliteAuditLoggerConfig | SqliteAndConsoleAuditLoggerConfig;
51
+ /** Selects the shared audit output. Audit loggers remain no-op until this is called. */
52
+ export declare function initAuditLogger(config: AuditLoggerConfig): () => void;
53
+ /**
54
+ * Module-scoped structured audit logger. Define a discriminated union of events in the application and
55
+ * specialize this class, then compose one or more domain-focused wrappers around it:
56
+ *
57
+ * ```ts
58
+ * type AppEvent =
59
+ * | { type: 'user.registered'; userId: string }
60
+ * | { type: 'payment.failed'; userId: string; reason: string }
61
+ *
62
+ * const audit = getAuditLogger<AppEvent>('APP')
63
+ *
64
+ * class AppAuditLogger {
65
+ * constructor(private readonly log: AuditLogger<AppEvent> = audit) {}
66
+ * userRegistered(userId: string) {
67
+ * this.log.info({ type: 'user.registered', userId })
68
+ * }
69
+ * paymentFailed(userId: string, reason: string) {
70
+ * this.log.error({ type: 'payment.failed', userId, reason })
71
+ * }
72
+ * }
73
+ * ```
74
+ *
75
+ * Keep these wrappers in application code: they provide convenient domain methods while this logger
76
+ * owns levels, module attribution, timestamps, and output. Multiple wrappers can share the same base
77
+ * logger. Event fields are stored as structured data alongside `type`; do not put secrets in them.
78
+ * Instances obtained before initAuditLogger become active after initialization.
79
+ */
80
+ export declare class AuditLogger<TEvent extends AuditEvent = AuditEvent> {
81
+ private readonly module;
82
+ constructor(module: string);
83
+ fatal(event: TEvent, error?: Error): void;
84
+ error(event: TEvent, error?: Error): void;
85
+ warn(event: TEvent, error?: Error): void;
86
+ info(event: TEvent, error?: Error): void;
87
+ debug(event: TEvent, error?: Error): void;
88
+ trace(event: TEvent, error?: Error): void;
89
+ write(level: LogLevel, event: TEvent, error?: Error): void;
90
+ }
91
+ export declare function getAuditLogger<TEvent extends AuditEvent = AuditEvent>(module: string): AuditLogger<TEvent>;
92
+ /** Reads persisted audit records; console-only or uninitialized loggers return an empty page. */
93
+ export declare class AuditLogReader {
94
+ read(query: AuditLogQuery): AuditLogPage;
95
+ }
96
+ export declare function getAuditLogReader(): AuditLogReader;
97
+ export {};
@@ -0,0 +1,155 @@
1
+ import { formatAuditRecord } from './format.js';
2
+ import { SqliteAuditStorage } from './sqlite-storage.js';
3
+ let activeSink;
4
+ let closeActiveSink;
5
+ let activeReader;
6
+ /** Selects the shared audit output. Audit loggers remain no-op until this is called. */
7
+ export function initAuditLogger(config) {
8
+ const previousClose = closeActiveSink;
9
+ activeSink = undefined;
10
+ closeActiveSink = undefined;
11
+ activeReader = undefined;
12
+ try {
13
+ previousClose?.();
14
+ }
15
+ catch (error) {
16
+ reportAuditError(error, 'shutdown failed');
17
+ }
18
+ try {
19
+ let sink;
20
+ let close = () => undefined;
21
+ if (config.mode === 'console') {
22
+ const color = config.color ?? true;
23
+ sink = (record) => {
24
+ writeConsole(record, color);
25
+ };
26
+ }
27
+ else {
28
+ const storage = new SqliteAuditStorage(config);
29
+ activeReader = (query) => storage.read(query);
30
+ const withConsole = config.mode === 'sqlite+console';
31
+ const color = config.mode === 'sqlite+console' ? (config.color ?? true) : false;
32
+ sink = (record) => {
33
+ try {
34
+ storage.write(record);
35
+ }
36
+ catch (error) {
37
+ reportAuditError(error, 'write failed');
38
+ }
39
+ if (withConsole)
40
+ writeConsole(record, color);
41
+ };
42
+ close = () => storage.close();
43
+ }
44
+ activeSink = sink;
45
+ closeActiveSink = close;
46
+ return () => {
47
+ if (activeSink !== sink)
48
+ return;
49
+ activeSink = undefined;
50
+ closeActiveSink = undefined;
51
+ activeReader = undefined;
52
+ try {
53
+ close();
54
+ }
55
+ catch (error) {
56
+ reportAuditError(error, 'shutdown failed');
57
+ }
58
+ };
59
+ }
60
+ catch (error) {
61
+ reportAuditError(error, 'initialization failed');
62
+ return () => undefined;
63
+ }
64
+ }
65
+ /**
66
+ * Module-scoped structured audit logger. Define a discriminated union of events in the application and
67
+ * specialize this class, then compose one or more domain-focused wrappers around it:
68
+ *
69
+ * ```ts
70
+ * type AppEvent =
71
+ * | { type: 'user.registered'; userId: string }
72
+ * | { type: 'payment.failed'; userId: string; reason: string }
73
+ *
74
+ * const audit = getAuditLogger<AppEvent>('APP')
75
+ *
76
+ * class AppAuditLogger {
77
+ * constructor(private readonly log: AuditLogger<AppEvent> = audit) {}
78
+ * userRegistered(userId: string) {
79
+ * this.log.info({ type: 'user.registered', userId })
80
+ * }
81
+ * paymentFailed(userId: string, reason: string) {
82
+ * this.log.error({ type: 'payment.failed', userId, reason })
83
+ * }
84
+ * }
85
+ * ```
86
+ *
87
+ * Keep these wrappers in application code: they provide convenient domain methods while this logger
88
+ * owns levels, module attribution, timestamps, and output. Multiple wrappers can share the same base
89
+ * logger. Event fields are stored as structured data alongside `type`; do not put secrets in them.
90
+ * Instances obtained before initAuditLogger become active after initialization.
91
+ */
92
+ export class AuditLogger {
93
+ module;
94
+ constructor(module) {
95
+ this.module = module;
96
+ }
97
+ fatal(event, error) {
98
+ this.write('fatal', event, error);
99
+ }
100
+ error(event, error) {
101
+ this.write('error', event, error);
102
+ }
103
+ warn(event, error) {
104
+ this.write('warn', event, error);
105
+ }
106
+ info(event, error) {
107
+ this.write('info', event, error);
108
+ }
109
+ debug(event, error) {
110
+ this.write('debug', event, error);
111
+ }
112
+ trace(event, error) {
113
+ this.write('trace', event, error);
114
+ }
115
+ write(level, event, error) {
116
+ if (activeSink === undefined)
117
+ return;
118
+ const record = {
119
+ time: new Date().toISOString(),
120
+ level,
121
+ module: this.module,
122
+ type: event.type,
123
+ data: Object.fromEntries(Object.entries(event).filter(([key]) => key !== 'type')),
124
+ ...(error === undefined ? {} : { error: { name: error.name, message: error.message, stack: error.stack } })
125
+ };
126
+ try {
127
+ activeSink(record);
128
+ }
129
+ catch (sinkError) {
130
+ reportAuditError(sinkError, 'write failed');
131
+ }
132
+ }
133
+ }
134
+ export function getAuditLogger(module) {
135
+ return new AuditLogger(module);
136
+ }
137
+ /** Reads persisted audit records; console-only or uninitialized loggers return an empty page. */
138
+ export class AuditLogReader {
139
+ read(query) {
140
+ if (activeReader === undefined)
141
+ return { records: [], total: 0 };
142
+ return activeReader(query);
143
+ }
144
+ }
145
+ export function getAuditLogReader() {
146
+ return new AuditLogReader();
147
+ }
148
+ function writeConsole(record, color) {
149
+ process.stderr.write(formatAuditRecord(record, color));
150
+ }
151
+ function reportAuditError(error, context) {
152
+ const message = error instanceof Error ? `${error.name}: ${error.message}` : String(error);
153
+ process.stderr.write(`AuditLogger ${context}: ${message.replaceAll(/[\r\n]+/g, ' | ')}\n`);
154
+ }
155
+ //# sourceMappingURL=audit-logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-logger.js","sourceRoot":"","sources":["../../../src/back/logger/audit-logger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { CliModule } from '../cli/cli-engine.js';
2
+ export declare function makeAuditLogCliModule(workingDirectory?: string | (() => string)): CliModule;