@cyberismo/backend 0.0.20 → 0.0.22

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 (131) hide show
  1. package/dist/app.d.ts +5 -2
  2. package/dist/app.js +22 -9
  3. package/dist/app.js.map +1 -1
  4. package/dist/auth/index.d.ts +16 -0
  5. package/dist/auth/index.js +15 -0
  6. package/dist/auth/index.js.map +1 -0
  7. package/dist/auth/keycloak.d.ts +27 -0
  8. package/dist/auth/keycloak.js +81 -0
  9. package/dist/auth/keycloak.js.map +1 -0
  10. package/dist/auth/mock.d.ts +23 -0
  11. package/dist/auth/mock.js +28 -0
  12. package/dist/auth/mock.js.map +1 -0
  13. package/dist/auth/types.d.ts +16 -0
  14. package/dist/auth/types.js +14 -0
  15. package/dist/auth/types.js.map +1 -0
  16. package/dist/domain/auth/index.d.ts +14 -0
  17. package/dist/domain/auth/index.js +30 -0
  18. package/dist/domain/auth/index.js.map +1 -0
  19. package/dist/domain/calculations/index.js +3 -1
  20. package/dist/domain/calculations/index.js.map +1 -1
  21. package/dist/domain/calculations/service.js +13 -11
  22. package/dist/domain/calculations/service.js.map +1 -1
  23. package/dist/domain/cardTypes/index.js +5 -3
  24. package/dist/domain/cardTypes/index.js.map +1 -1
  25. package/dist/domain/cardTypes/service.js +24 -72
  26. package/dist/domain/cardTypes/service.js.map +1 -1
  27. package/dist/domain/cards/index.js +19 -15
  28. package/dist/domain/cards/index.js.map +1 -1
  29. package/dist/domain/cards/lib.js +95 -93
  30. package/dist/domain/cards/lib.js.map +1 -1
  31. package/dist/domain/cards/service.d.ts +2 -1
  32. package/dist/domain/cards/service.js +60 -87
  33. package/dist/domain/cards/service.js.map +1 -1
  34. package/dist/domain/fieldTypes/index.js +4 -2
  35. package/dist/domain/fieldTypes/index.js.map +1 -1
  36. package/dist/domain/graphModels/index.js +3 -1
  37. package/dist/domain/graphModels/index.js.map +1 -1
  38. package/dist/domain/graphViews/index.js +3 -1
  39. package/dist/domain/graphViews/index.js.map +1 -1
  40. package/dist/domain/labels/index.js +4 -2
  41. package/dist/domain/labels/index.js.map +1 -1
  42. package/dist/domain/labels/service.d.ts +1 -1
  43. package/dist/domain/labels/service.js +2 -2
  44. package/dist/domain/labels/service.js.map +1 -1
  45. package/dist/domain/linkTypes/index.js +4 -2
  46. package/dist/domain/linkTypes/index.js.map +1 -1
  47. package/dist/domain/logicPrograms/index.js +3 -1
  48. package/dist/domain/logicPrograms/index.js.map +1 -1
  49. package/dist/domain/mcp/index.d.ts +15 -0
  50. package/dist/domain/mcp/index.js +127 -0
  51. package/dist/domain/mcp/index.js.map +1 -0
  52. package/dist/domain/project/index.js +7 -5
  53. package/dist/domain/project/index.js.map +1 -1
  54. package/dist/domain/project/service.js +18 -14
  55. package/dist/domain/project/service.js.map +1 -1
  56. package/dist/domain/reports/index.js +3 -1
  57. package/dist/domain/reports/index.js.map +1 -1
  58. package/dist/domain/resources/index.js +6 -4
  59. package/dist/domain/resources/index.js.map +1 -1
  60. package/dist/domain/resources/schema.d.ts +1 -0
  61. package/dist/domain/resources/schema.js +1 -0
  62. package/dist/domain/resources/schema.js.map +1 -1
  63. package/dist/domain/resources/service.js +66 -64
  64. package/dist/domain/resources/service.js.map +1 -1
  65. package/dist/domain/templates/index.js +5 -3
  66. package/dist/domain/templates/index.js.map +1 -1
  67. package/dist/domain/tree/index.js +3 -1
  68. package/dist/domain/tree/index.js.map +1 -1
  69. package/dist/domain/workflows/index.js +3 -1
  70. package/dist/domain/workflows/index.js.map +1 -1
  71. package/dist/export.d.ts +6 -5
  72. package/dist/export.js +15 -11
  73. package/dist/export.js.map +1 -1
  74. package/dist/index.d.ts +8 -2
  75. package/dist/index.js +5 -3
  76. package/dist/index.js.map +1 -1
  77. package/dist/main.js +29 -2
  78. package/dist/main.js.map +1 -1
  79. package/dist/middleware/auth.d.ts +40 -0
  80. package/dist/middleware/auth.js +68 -0
  81. package/dist/middleware/auth.js.map +1 -0
  82. package/dist/middleware/commandManager.d.ts +2 -2
  83. package/dist/middleware/commandManager.js +9 -11
  84. package/dist/middleware/commandManager.js.map +1 -1
  85. package/dist/middleware/zvalidator.d.ts +1 -1
  86. package/dist/public/THIRD-PARTY.txt +147 -51
  87. package/dist/public/assets/index-B_lh6qtv.css +1 -0
  88. package/dist/public/assets/{index-DP0xZy_p.js → index-CEol8Bfi.js} +54255 -49274
  89. package/dist/public/config.json +1 -0
  90. package/dist/public/index.html +2 -2
  91. package/dist/types.d.ts +25 -0
  92. package/dist/types.js +13 -1
  93. package/dist/types.js.map +1 -1
  94. package/package.json +10 -7
  95. package/src/app.ts +34 -14
  96. package/src/auth/index.ts +17 -0
  97. package/src/auth/keycloak.ts +109 -0
  98. package/src/auth/mock.ts +38 -0
  99. package/src/auth/types.ts +18 -0
  100. package/src/domain/auth/index.ts +35 -0
  101. package/src/domain/calculations/index.ts +13 -6
  102. package/src/domain/calculations/service.ts +16 -14
  103. package/src/domain/cardTypes/index.ts +24 -16
  104. package/src/domain/cardTypes/service.ts +41 -95
  105. package/src/domain/cards/index.ts +62 -44
  106. package/src/domain/cards/lib.ts +105 -100
  107. package/src/domain/cards/service.ts +73 -89
  108. package/src/domain/fieldTypes/index.ts +23 -16
  109. package/src/domain/graphModels/index.ts +13 -6
  110. package/src/domain/graphViews/index.ts +13 -6
  111. package/src/domain/labels/index.ts +5 -2
  112. package/src/domain/labels/service.ts +2 -2
  113. package/src/domain/linkTypes/index.ts +14 -7
  114. package/src/domain/logicPrograms/index.ts +3 -0
  115. package/src/domain/mcp/index.ts +159 -0
  116. package/src/domain/project/index.ts +17 -8
  117. package/src/domain/project/service.ts +20 -16
  118. package/src/domain/reports/index.ts +13 -6
  119. package/src/domain/resources/index.ts +6 -1
  120. package/src/domain/resources/schema.ts +1 -0
  121. package/src/domain/resources/service.ts +102 -97
  122. package/src/domain/templates/index.ts +31 -19
  123. package/src/domain/tree/index.ts +3 -1
  124. package/src/domain/workflows/index.ts +13 -6
  125. package/src/export.ts +16 -13
  126. package/src/index.ts +10 -3
  127. package/src/main.ts +44 -2
  128. package/src/middleware/auth.ts +90 -0
  129. package/src/middleware/commandManager.ts +11 -14
  130. package/src/types.ts +27 -0
  131. package/dist/public/assets/index-CRSBseQM.css +0 -1
package/dist/app.d.ts CHANGED
@@ -11,11 +11,14 @@
11
11
  License along with this program. If not, see <https://www.gnu.org/licenses/>.
12
12
  */
13
13
  import { Hono } from 'hono';
14
+ import type { CommandManager } from '@cyberismo/data-handler';
14
15
  import type { AppVars, TreeOptions } from './types.js';
16
+ import type { AuthProvider } from './auth/types.js';
15
17
  /**
16
18
  * Create the Hono app for the backend
17
- * @param projectPath - Path to the project
19
+ * @param authProvider - Authentication provider
20
+ * @param commands - CommandManager instance for the project
18
21
  */
19
- export declare function createApp(projectPath?: string, opts?: TreeOptions): Hono<{
22
+ export declare function createApp(authProvider: AuthProvider, commands: CommandManager, opts?: TreeOptions): Hono<{
20
23
  Variables: AppVars;
21
24
  }, import("hono/types").BlankSchema, "/">;
package/dist/app.js CHANGED
@@ -12,7 +12,6 @@
12
12
  */
13
13
  import { Hono } from 'hono';
14
14
  import { staticFrontendDirRelative } from './utils.js';
15
- import { cors } from 'hono/cors';
16
15
  import { serveStatic } from '@hono/node-server/serve-static';
17
16
  import { attachCommandManager } from './middleware/commandManager.js';
18
17
  import calculationsRouter from './domain/calculations/index.js';
@@ -34,20 +33,29 @@ import logicProgramsRouter from './domain/logicPrograms/index.js';
34
33
  import { isSSGContext } from 'hono/ssg';
35
34
  import treeMiddleware from './middleware/tree.js';
36
35
  import projectRouter from './domain/project/index.js';
36
+ import mcpRouter from './domain/mcp/index.js';
37
+ import { createAuthRouter } from './domain/auth/index.js';
38
+ import { createAuthMiddleware } from './middleware/auth.js';
37
39
  /**
38
40
  * Create the Hono app for the backend
39
- * @param projectPath - Path to the project
41
+ * @param authProvider - Authentication provider
42
+ * @param commands - CommandManager instance for the project
40
43
  */
41
- export function createApp(projectPath, opts) {
44
+ export function createApp(authProvider, commands, opts) {
42
45
  const app = new Hono();
43
- app.use('/api', cors());
44
- app.use('*', serveStatic({
45
- root: staticFrontendDirRelative,
46
- }));
47
46
  app.use(treeMiddleware(opts));
48
- // Attach CommandManager to all requests
49
- app.use(attachCommandManager(projectPath));
47
+ // Apply authentication middleware to all API and MCP routes
48
+ app.use('/api/*', createAuthMiddleware(authProvider));
49
+ app.use('/mcp', createAuthMiddleware(authProvider));
50
+ app.use('/mcp/*', createAuthMiddleware(authProvider));
51
+ // Attach CommandManager to API and MCP routes
52
+ const commandManagerMiddleware = attachCommandManager(commands);
53
+ app.use('/api/*', commandManagerMiddleware);
54
+ app.use('/mcp', commandManagerMiddleware);
55
+ app.use('/mcp/*', commandManagerMiddleware);
50
56
  // Wire up routes
57
+ app.route('/api/auth', createAuthRouter());
58
+ // Mount routers
51
59
  app.route('/api/calculations', calculationsRouter);
52
60
  app.route('/api/cards', cardsRouter);
53
61
  app.route('/api/cardTypes', cardTypesRouter);
@@ -63,6 +71,11 @@ export function createApp(projectPath, opts) {
63
71
  app.route('/api/logicPrograms', logicProgramsRouter);
64
72
  app.route('/api/labels', labelsRouter);
65
73
  app.route('/api/project', projectRouter);
74
+ // MCP endpoint for AI assistant integration
75
+ app.route('/mcp', mcpRouter);
76
+ app.use('*', serveStatic({
77
+ root: staticFrontendDirRelative,
78
+ }));
66
79
  // serve index.html for all other routes
67
80
  app.notFound(async (c) => {
68
81
  if (c.req.path.startsWith('/api')) {
package/dist/app.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ Cyberismo
3
+ Copyright © Cyberismo Ltd and contributors 2026
4
+ This program is free software: you can redistribute it and/or modify it under
5
+ the terms of the GNU Affero General Public License version 3 as published by
6
+ the Free Software Foundation. This program is distributed in the hope that it
7
+ will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
8
+ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9
+ See the GNU Affero General Public License for more details.
10
+ You should have received a copy of the GNU Affero General Public
11
+ License along with this program. If not, see <https://www.gnu.org/licenses/>.
12
+ */
13
+ export type { AuthProvider } from './types.js';
14
+ export { MockAuthProvider } from './mock.js';
15
+ export { KeycloakAuthProvider } from './keycloak.js';
16
+ export type { KeycloakConfig } from './keycloak.js';
@@ -0,0 +1,15 @@
1
+ /**
2
+ Cyberismo
3
+ Copyright © Cyberismo Ltd and contributors 2026
4
+ This program is free software: you can redistribute it and/or modify it under
5
+ the terms of the GNU Affero General Public License version 3 as published by
6
+ the Free Software Foundation. This program is distributed in the hope that it
7
+ will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
8
+ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9
+ See the GNU Affero General Public License for more details.
10
+ You should have received a copy of the GNU Affero General Public
11
+ License along with this program. If not, see <https://www.gnu.org/licenses/>.
12
+ */
13
+ export { MockAuthProvider } from './mock.js';
14
+ export { KeycloakAuthProvider } from './keycloak.js';
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;EAWE;AAGF,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ Cyberismo
3
+ Copyright © Cyberismo Ltd and contributors 2026
4
+ This program is free software: you can redistribute it and/or modify it under
5
+ the terms of the GNU Affero General Public License version 3 as published by
6
+ the Free Software Foundation. This program is distributed in the hope that it
7
+ will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
8
+ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9
+ See the GNU Affero General Public License for more details.
10
+ You should have received a copy of the GNU Affero General Public
11
+ License along with this program. If not, see <https://www.gnu.org/licenses/>.
12
+ */
13
+ import type { UserInfo } from '../types.js';
14
+ import type { AuthProvider } from './types.js';
15
+ export interface KeycloakConfig {
16
+ issuer: string;
17
+ audience: string;
18
+ }
19
+ export declare class KeycloakAuthProvider implements AuthProvider {
20
+ private readonly issuer;
21
+ private readonly audience;
22
+ private jwks;
23
+ constructor(config: KeycloakConfig);
24
+ private getJWKS;
25
+ authenticate(req: Request): Promise<UserInfo | null>;
26
+ private mapRole;
27
+ }
@@ -0,0 +1,81 @@
1
+ /**
2
+ Cyberismo
3
+ Copyright © Cyberismo Ltd and contributors 2026
4
+ This program is free software: you can redistribute it and/or modify it under
5
+ the terms of the GNU Affero General Public License version 3 as published by
6
+ the Free Software Foundation. This program is distributed in the hope that it
7
+ will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
8
+ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9
+ See the GNU Affero General Public License for more details.
10
+ You should have received a copy of the GNU Affero General Public
11
+ License along with this program. If not, see <https://www.gnu.org/licenses/>.
12
+ */
13
+ import { createRemoteJWKSet, jwtVerify } from 'jose';
14
+ import { UserRole } from '../types.js';
15
+ export class KeycloakAuthProvider {
16
+ issuer;
17
+ audience;
18
+ jwks = null;
19
+ constructor(config) {
20
+ this.issuer = config.issuer;
21
+ this.audience = config.audience;
22
+ }
23
+ getJWKS() {
24
+ if (!this.jwks) {
25
+ const jwksUrl = new URL(`${this.issuer.replace(/\/$/, '')}/protocol/openid-connect/certs`);
26
+ this.jwks = createRemoteJWKSet(jwksUrl);
27
+ }
28
+ return this.jwks;
29
+ }
30
+ async authenticate(req) {
31
+ const authHeader = req.headers.get('authorization');
32
+ if (!authHeader) {
33
+ return null;
34
+ }
35
+ const token = authHeader.replace(/^Bearer\s+/i, '');
36
+ if (!token) {
37
+ return null;
38
+ }
39
+ try {
40
+ const jwks = this.getJWKS();
41
+ const { payload } = await jwtVerify(token, jwks, {
42
+ issuer: this.issuer,
43
+ audience: this.audience,
44
+ });
45
+ const claims = payload;
46
+ const role = this.mapRole(claims.realm_access?.roles);
47
+ if (!claims.sub) {
48
+ throw new Error('Missing sub');
49
+ }
50
+ if (!claims.email) {
51
+ throw new Error('Missing email');
52
+ }
53
+ return {
54
+ id: claims.sub,
55
+ email: claims.email,
56
+ name: claims.name ?? claims.preferred_username ?? 'Unknown',
57
+ role,
58
+ };
59
+ }
60
+ catch {
61
+ // TODO: add proper logging
62
+ return null;
63
+ }
64
+ }
65
+ mapRole(roles) {
66
+ if (!roles) {
67
+ throw new Error('Token missing realm_access roles');
68
+ }
69
+ if (roles.includes('admin')) {
70
+ return UserRole.Admin;
71
+ }
72
+ if (roles.includes('editor')) {
73
+ return UserRole.Editor;
74
+ }
75
+ if (roles.includes('reader')) {
76
+ return UserRole.Reader;
77
+ }
78
+ throw new Error('No recognized role found in token');
79
+ }
80
+ }
81
+ //# sourceMappingURL=keycloak.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keycloak.js","sourceRoot":"","sources":["../../src/auth/keycloak.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ Cyberismo
3
+ Copyright © Cyberismo Ltd and contributors 2026
4
+ This program is free software: you can redistribute it and/or modify it under
5
+ the terms of the GNU Affero General Public License version 3 as published by
6
+ the Free Software Foundation. This program is distributed in the hope that it
7
+ will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
8
+ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9
+ See the GNU Affero General Public License for more details.
10
+ You should have received a copy of the GNU Affero General Public
11
+ License along with this program. If not, see <https://www.gnu.org/licenses/>.
12
+ */
13
+ import type { UserInfo } from '../types.js';
14
+ import type { AuthProvider } from './types.js';
15
+ export interface MockUserConfig {
16
+ name?: string;
17
+ email?: string;
18
+ }
19
+ export declare class MockAuthProvider implements AuthProvider {
20
+ private readonly userConfig;
21
+ constructor(config?: MockUserConfig);
22
+ authenticate(): Promise<UserInfo>;
23
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ Cyberismo
3
+ Copyright © Cyberismo Ltd and contributors 2026
4
+ This program is free software: you can redistribute it and/or modify it under
5
+ the terms of the GNU Affero General Public License version 3 as published by
6
+ the Free Software Foundation. This program is distributed in the hope that it
7
+ will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
8
+ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9
+ See the GNU Affero General Public License for more details.
10
+ You should have received a copy of the GNU Affero General Public
11
+ License along with this program. If not, see <https://www.gnu.org/licenses/>.
12
+ */
13
+ import { UserRole } from '../types.js';
14
+ export class MockAuthProvider {
15
+ userConfig;
16
+ constructor(config) {
17
+ this.userConfig = config ?? {};
18
+ }
19
+ async authenticate() {
20
+ return {
21
+ id: 'mock-user',
22
+ email: this.userConfig.email ?? 'admin@cyberismo.local',
23
+ name: this.userConfig.name ?? 'Local Admin',
24
+ role: UserRole.Admin,
25
+ };
26
+ }
27
+ }
28
+ //# sourceMappingURL=mock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock.js","sourceRoot":"","sources":["../../src/auth/mock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;EAWE;AAEF,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AASvC,MAAM,OAAO,gBAAgB;IACV,UAAU,CAAiB;IAE5C,YAAY,MAAuB;QACjC,IAAI,CAAC,UAAU,GAAG,MAAM,IAAI,EAAE,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,OAAO;YACL,EAAE,EAAE,WAAW;YACf,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK,IAAI,uBAAuB;YACvD,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,IAAI,aAAa;YAC3C,IAAI,EAAE,QAAQ,CAAC,KAAK;SACrB,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ Cyberismo
3
+ Copyright © Cyberismo Ltd and contributors 2026
4
+ This program is free software: you can redistribute it and/or modify it under
5
+ the terms of the GNU Affero General Public License version 3 as published by
6
+ the Free Software Foundation. This program is distributed in the hope that it
7
+ will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
8
+ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9
+ See the GNU Affero General Public License for more details.
10
+ You should have received a copy of the GNU Affero General Public
11
+ License along with this program. If not, see <https://www.gnu.org/licenses/>.
12
+ */
13
+ import type { UserInfo } from '../types.js';
14
+ export interface AuthProvider {
15
+ authenticate(req: Request): Promise<UserInfo | null>;
16
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ Cyberismo
3
+ Copyright © Cyberismo Ltd and contributors 2026
4
+ This program is free software: you can redistribute it and/or modify it under
5
+ the terms of the GNU Affero General Public License version 3 as published by
6
+ the Free Software Foundation. This program is distributed in the hope that it
7
+ will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
8
+ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9
+ See the GNU Affero General Public License for more details.
10
+ You should have received a copy of the GNU Affero General Public
11
+ License along with this program. If not, see <https://www.gnu.org/licenses/>.
12
+ */
13
+ export {};
14
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;EAWE"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ Cyberismo
3
+ Copyright © Cyberismo Ltd and contributors 2026
4
+ This program is free software: you can redistribute it and/or modify it under
5
+ the terms of the GNU Affero General Public License version 3 as published by
6
+ the Free Software Foundation. This program is distributed in the hope that it
7
+ will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
8
+ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9
+ See the GNU Affero General Public License for more details.
10
+ You should have received a copy of the GNU Affero General Public
11
+ License along with this program. If not, see <https://www.gnu.org/licenses/>.
12
+ */
13
+ import { Hono } from 'hono';
14
+ export declare function createAuthRouter(): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
@@ -0,0 +1,30 @@
1
+ /**
2
+ Cyberismo
3
+ Copyright © Cyberismo Ltd and contributors 2026
4
+ This program is free software: you can redistribute it and/or modify it under
5
+ the terms of the GNU Affero General Public License version 3 as published by
6
+ the Free Software Foundation. This program is distributed in the hope that it
7
+ will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
8
+ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9
+ See the GNU Affero General Public License for more details.
10
+ You should have received a copy of the GNU Affero General Public
11
+ License along with this program. If not, see <https://www.gnu.org/licenses/>.
12
+ */
13
+ import { Hono } from 'hono';
14
+ import { getCurrentUser } from '../../middleware/auth.js';
15
+ export function createAuthRouter() {
16
+ const router = new Hono();
17
+ /**
18
+ * GET /api/auth/me
19
+ * Returns the current user's information (id, email, name, role)
20
+ */
21
+ router.get('/me', async (c) => {
22
+ const user = getCurrentUser(c);
23
+ if (!user) {
24
+ return c.json({ error: 'Unauthorized' }, 401);
25
+ }
26
+ return c.json(user);
27
+ });
28
+ return router;
29
+ }
30
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/domain/auth/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;EAWE;AAEF,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,MAAM,UAAU,gBAAgB;IAC9B,MAAM,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;IAE1B;;;OAGG;IACH,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAC5B,MAAM,IAAI,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;QAE/B,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE,GAAG,CAAC,CAAC;QAChD,CAAC;QAED,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -14,6 +14,8 @@ import { Hono } from 'hono';
14
14
  import * as calculationService from './service.js';
15
15
  import { createCalculationSchema } from './schema.js';
16
16
  import { zValidator } from '../../middleware/zvalidator.js';
17
+ import { UserRole } from '../../types.js';
18
+ import { requireRole } from '../../middleware/auth.js';
17
19
  const router = new Hono();
18
20
  /**
19
21
  * @swagger
@@ -40,7 +42,7 @@ const router = new Hono();
40
42
  * 500:
41
43
  * description: Server error
42
44
  */
43
- router.post('/', zValidator('json', createCalculationSchema), async (c) => {
45
+ router.post('/', requireRole(UserRole.Admin), zValidator('json', createCalculationSchema), async (c) => {
44
46
  const commands = c.get('commands');
45
47
  const { identifier } = c.req.valid('json');
46
48
  await calculationService.createCalculation(commands, identifier);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/domain/calculations/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;EAWE;AAEF,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,kBAAkB,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAE5D,MAAM,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;AAE1B;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,MAAM,EAAE,uBAAuB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IACxE,MAAM,QAAQ,GAAG,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACnC,MAAM,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAE3C,MAAM,kBAAkB,CAAC,iBAAiB,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IACjE,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,kCAAkC,EAAE,CAAC,CAAC;AACjE,CAAC,CAAC,CAAC;AAEH,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/domain/calculations/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;EAWE;AAEF,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,kBAAkB,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD,MAAM,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;AAE1B;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,CAAC,IAAI,CACT,GAAG,EACH,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,EAC3B,UAAU,CAAC,MAAM,EAAE,uBAAuB,CAAC,EAC3C,KAAK,EAAE,CAAC,EAAE,EAAE;IACV,MAAM,QAAQ,GAAG,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACnC,MAAM,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAE3C,MAAM,kBAAkB,CAAC,iBAAiB,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IACjE,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,kCAAkC,EAAE,CAAC,CAAC;AACjE,CAAC,CACF,CAAC;AAEF,eAAe,MAAM,CAAC"}
@@ -20,16 +20,18 @@ function capitalize(str) {
20
20
  return str.charAt(0).toUpperCase() + str.slice(1);
21
21
  }
22
22
  export async function createCalculation(commands, identifier) {
23
- await commands.createCmd.createCalculation(identifier);
24
- // Set displayName to capitalized version of identifier
25
- const project = await commands.showCmd.showProject();
26
- await updateResourceWithOperation(commands, { prefix: project.prefix, type: 'calculations', identifier }, {
27
- updateKey: { key: 'displayName' },
28
- operation: {
29
- name: 'change',
30
- target: '',
31
- to: capitalize(identifier),
32
- },
33
- });
23
+ await commands.atomic(async () => {
24
+ await commands.createCmd.createCalculation(identifier);
25
+ // Set displayName to capitalized version of identifier
26
+ const project = await commands.showCmd.showProject();
27
+ await updateResourceWithOperation(commands, { prefix: project.prefix, type: 'calculations', identifier }, {
28
+ updateKey: { key: 'displayName' },
29
+ operation: {
30
+ name: 'change',
31
+ target: '',
32
+ to: capitalize(identifier),
33
+ },
34
+ });
35
+ }, `Create calculation ${identifier}`);
34
36
  }
35
37
  //# sourceMappingURL=service.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"service.js","sourceRoot":"","sources":["../../../src/domain/calculations/service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;EAWE;AAGF,OAAO,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AAEtE;;GAEG;AACH,SAAS,UAAU,CAAC,GAAW;IAC7B,IAAI,CAAC,GAAG;QAAE,OAAO,GAAG,CAAC;IACrB,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,QAAwB,EACxB,UAAkB;IAElB,MAAM,QAAQ,CAAC,SAAS,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;IAEvD,uDAAuD;IACvD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;IACrD,MAAM,2BAA2B,CAC/B,QAAQ,EACR,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,UAAU,EAAE,EAC5D;QACE,SAAS,EAAE,EAAE,GAAG,EAAE,aAAa,EAAE;QACjC,SAAS,EAAE;YACT,IAAI,EAAE,QAAQ;YACd,MAAM,EAAE,EAAE;YACV,EAAE,EAAE,UAAU,CAAC,UAAU,CAAC;SAC3B;KACF,CACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../../src/domain/calculations/service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;EAWE;AAGF,OAAO,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AAEtE;;GAEG;AACH,SAAS,UAAU,CAAC,GAAW;IAC7B,IAAI,CAAC,GAAG;QAAE,OAAO,GAAG,CAAC;IACrB,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,QAAwB,EACxB,UAAkB;IAElB,MAAM,QAAQ,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE;QAC/B,MAAM,QAAQ,CAAC,SAAS,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;QAEvD,uDAAuD;QACvD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;QACrD,MAAM,2BAA2B,CAC/B,QAAQ,EACR,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,UAAU,EAAE,EAC5D;YACE,SAAS,EAAE,EAAE,GAAG,EAAE,aAAa,EAAE;YACjC,SAAS,EAAE;gBACT,IAAI,EAAE,QAAQ;gBACd,MAAM,EAAE,EAAE;gBACV,EAAE,EAAE,UAAU,CAAC,UAAU,CAAC;aAC3B;SACF,CACF,CAAC;IACJ,CAAC,EAAE,sBAAsB,UAAU,EAAE,CAAC,CAAC;AACzC,CAAC"}
@@ -14,6 +14,8 @@ import { Hono } from 'hono';
14
14
  import * as cardTypeService from './service.js';
15
15
  import { createCardTypeSchema, cardTypeNameParamSchema, fieldVisibilityBodySchema, } from './schema.js';
16
16
  import { zValidator } from '../../middleware/zvalidator.js';
17
+ import { UserRole } from '../../types.js';
18
+ import { requireRole } from '../../middleware/auth.js';
17
19
  const router = new Hono();
18
20
  /**
19
21
  * @swagger
@@ -29,7 +31,7 @@ const router = new Hono();
29
31
  * 500:
30
32
  * description: project_path not set or other internal error
31
33
  */
32
- router.get('/', async (c) => {
34
+ router.get('/', requireRole(UserRole.Reader), async (c) => {
33
35
  const commands = c.get('commands');
34
36
  try {
35
37
  const cardTypes = await cardTypeService.getCardTypes(commands);
@@ -69,7 +71,7 @@ router.get('/', async (c) => {
69
71
  * 500:
70
72
  * description: Server error
71
73
  */
72
- router.post('/', zValidator('json', createCardTypeSchema), async (c) => {
74
+ router.post('/', requireRole(UserRole.Admin), zValidator('json', createCardTypeSchema), async (c) => {
73
75
  const commands = c.get('commands');
74
76
  const { identifier, workflowName } = c.req.valid('json');
75
77
  try {
@@ -125,7 +127,7 @@ router.post('/', zValidator('json', createCardTypeSchema), async (c) => {
125
127
  * 500:
126
128
  * description: Server error
127
129
  */
128
- router.patch('/:cardTypeName/field-visibility', zValidator('param', cardTypeNameParamSchema), zValidator('json', fieldVisibilityBodySchema), async (c) => {
130
+ router.patch('/:cardTypeName/field-visibility', requireRole(UserRole.Admin), zValidator('param', cardTypeNameParamSchema), zValidator('json', fieldVisibilityBodySchema), async (c) => {
129
131
  const commands = c.get('commands');
130
132
  const { cardTypeName } = c.req.valid('param');
131
133
  const body = c.req.valid('json');
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/domain/cardTypes/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/domain/cardTypes/index.ts"],"names":[],"mappings":"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"}
@@ -34,87 +34,39 @@ function getCurrentGroup(alwaysVisibleFields, optionallyVisibleFields, fieldName
34
34
  */
35
35
  export async function updateFieldVisibility(commands, cardTypeName, body) {
36
36
  const { fieldName, group: targetGroup, index: targetIndex } = body;
37
- // Get current card type data
38
- const cardType = await commands.showCmd.showResource(cardTypeName, 'cardTypes');
39
- if (!cardType) {
40
- throw new Error(`Card type '${cardTypeName}' not found`);
41
- }
42
- const customFields = cardType.customFields || [];
43
- const alwaysVisibleFields = cardType.alwaysVisibleFields || [];
44
- const optionallyVisibleFields = cardType.optionallyVisibleFields || [];
45
- // Validate that the field exists in customFields
46
- const fieldExists = customFields.some((f) => f.name === fieldName);
47
- if (!fieldExists) {
48
- throw new Error(`Field '${fieldName}' does not exist in card type '${cardTypeName}'. `);
49
- }
50
- const currentGroup = getCurrentGroup(alwaysVisibleFields, optionallyVisibleFields, fieldName);
51
- // If same group, just handle reordering
52
- if (currentGroup === targetGroup) {
53
- if (targetGroup === 'hidden') {
54
- // Nothing to reorder in hidden group
55
- return;
37
+ await commands.atomic(async () => {
38
+ // Read is now inside the write lock
39
+ const cardType = await commands.showCmd.showResource(cardTypeName, 'cardTypes');
40
+ if (!cardType) {
41
+ throw new Error(`Card type '${cardTypeName}' not found`);
42
+ }
43
+ const customFields = cardType.customFields || [];
44
+ const alwaysVisibleFields = cardType.alwaysVisibleFields || [];
45
+ const optionallyVisibleFields = cardType.optionallyVisibleFields || [];
46
+ // Validate that the field exists in customFields
47
+ const fieldExists = customFields.some((f) => f.name === fieldName);
48
+ if (!fieldExists) {
49
+ throw new Error(`Field '${fieldName}' does not exist in card type '${cardTypeName}'. `);
56
50
  }
57
- if (targetIndex !== undefined) {
58
- await commands.updateCmd.applyResourceOperation(cardTypeName, {
59
- key: groupToKey[targetGroup],
60
- }, {
61
- name: 'rank',
62
- target: fieldName,
63
- newIndex: targetIndex,
64
- });
51
+ const currentGroup = getCurrentGroup(alwaysVisibleFields, optionallyVisibleFields, fieldName);
52
+ // If same group, just handle reordering
53
+ if (currentGroup === targetGroup) {
54
+ if (targetGroup !== 'hidden' && targetIndex !== undefined) {
55
+ await commands.updateCmd.applyResourceOperation(cardTypeName, { key: groupToKey[targetGroup] }, { name: 'rank', target: fieldName, newIndex: targetIndex });
56
+ }
57
+ return;
65
58
  }
66
- return;
67
- }
68
- // Different group - need to remove from old and add to new
69
- let removedFromOld = false;
70
- try {
71
59
  // Remove from current group (if not hidden)
72
60
  if (currentGroup !== 'hidden') {
73
- await commands.updateCmd.applyResourceOperation(cardTypeName, {
74
- key: groupToKey[currentGroup],
75
- }, {
76
- name: 'remove',
77
- target: fieldName,
78
- });
79
- removedFromOld = true;
61
+ await commands.updateCmd.applyResourceOperation(cardTypeName, { key: groupToKey[currentGroup] }, { name: 'remove', target: fieldName });
80
62
  }
81
63
  // Add to new group (if not hidden)
82
64
  if (targetGroup !== 'hidden') {
83
- await commands.updateCmd.applyResourceOperation(cardTypeName, {
84
- key: groupToKey[targetGroup],
85
- }, {
86
- name: 'add',
87
- target: fieldName,
88
- });
89
- // Reorder if index specified
65
+ await commands.updateCmd.applyResourceOperation(cardTypeName, { key: groupToKey[targetGroup] }, { name: 'add', target: fieldName });
90
66
  if (targetIndex !== undefined) {
91
- await commands.updateCmd.applyResourceOperation(cardTypeName, {
92
- key: groupToKey[targetGroup],
93
- }, {
94
- name: 'rank',
95
- target: fieldName,
96
- newIndex: targetIndex,
97
- });
98
- }
99
- }
100
- }
101
- catch (error) {
102
- // Attempt rollback if we removed from old group but failed to add to new
103
- if (removedFromOld && currentGroup !== 'hidden') {
104
- try {
105
- await commands.updateCmd.applyResourceOperation(cardTypeName, {
106
- key: groupToKey[currentGroup],
107
- }, {
108
- name: 'add',
109
- target: fieldName,
110
- });
111
- }
112
- catch {
113
- // Rollback failed - log but throw original error
114
- console.error(`Rollback failed for field '${fieldName}' in card type '${cardTypeName}'`);
67
+ await commands.updateCmd.applyResourceOperation(cardTypeName, { key: groupToKey[targetGroup] }, { name: 'rank', target: fieldName, newIndex: targetIndex });
115
68
  }
116
69
  }
117
- throw error;
118
- }
70
+ }, `Update field visibility for ${cardTypeName}`);
119
71
  }
120
72
  //# sourceMappingURL=service.js.map