Skip to content

Commit 5924876

Browse files
Merge pull request #1230 from objectstack-ai/claude/add-auth-security-audit-ai-plugins
[WIP] Add Auth, Security, Audit, and AI plugins for Setup App menu
2 parents c7ca885 + 3b84755 commit 5924876

File tree

6 files changed

+38
-15
lines changed

6 files changed

+38
-15
lines changed

apps/console/objectstack.config.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const require = createRequire(import.meta.url);
44
// @ts-ignore
55
globalThis.require = require;
66

7-
import { sharedConfig, appConfigs, setupAppConfig } from './objectstack.shared';
7+
import { sharedConfig, appConfigs } from './objectstack.shared';
88

99
// @ts-ignore
1010
import * as MSWPluginPkg from '@objectstack/plugin-msw';
@@ -13,6 +13,10 @@ import * as ObjectQLPluginPkg from '@objectstack/objectql';
1313
// @ts-ignore
1414
import * as HonoServerPluginPkg from '@objectstack/plugin-hono-server';
1515
// @ts-ignore
16+
import * as AuthPluginPkg from '@objectstack/plugin-auth';
17+
// @ts-ignore
18+
import * as SetupPluginPkg from '@objectstack/plugin-setup';
19+
// @ts-ignore
1620
import * as DriverMemoryPkg from '@objectstack/driver-memory';
1721
// @ts-ignore
1822
import * as RuntimePkg from '@objectstack/runtime';
@@ -25,6 +29,8 @@ const InMemoryDriver = DriverMemoryPkg.InMemoryDriver || (DriverMemoryPkg as any
2529
const DriverPlugin = RuntimePkg.DriverPlugin || (RuntimePkg as any).default?.DriverPlugin || (RuntimePkg as any).default;
2630
const AppPlugin = RuntimePkg.AppPlugin || (RuntimePkg as any).default?.AppPlugin || (RuntimePkg as any).default;
2731
const HonoServerPlugin = HonoServerPluginPkg.HonoServerPlugin || (HonoServerPluginPkg as any).default?.HonoServerPlugin || (HonoServerPluginPkg as any).default;
32+
const AuthPlugin = AuthPluginPkg.AuthPlugin || (AuthPluginPkg as any).default?.AuthPlugin || (AuthPluginPkg as any).default;
33+
const SetupPlugin = SetupPluginPkg.SetupPlugin || (SetupPluginPkg as any).default?.SetupPlugin || (SetupPluginPkg as any).default;
2834
const createMemoryI18n = CorePkg.createMemoryI18n || (CorePkg as any).default?.createMemoryI18n;
2935

3036
import { ConsolePlugin } from './plugin';
@@ -70,15 +76,23 @@ class MemoryI18nPlugin {
7076
*
7177
* MemoryI18nPlugin MUST come before AppPlugin so that the i18n service
7278
* exists when AppPlugin.start() → loadTranslations() runs.
79+
*
80+
* SetupPlugin MUST load before AuthPlugin so that the setupNav service
81+
* is registered and available when AuthPlugin.init() tries to contribute menu items.
7382
*/
7483
const plugins: any[] = [
7584
new MemoryI18nPlugin(),
7685
new ObjectQLPlugin(),
7786
new DriverPlugin(new InMemoryDriver(), 'memory'),
7887
// Each example stack loaded as an independent AppPlugin
7988
...appConfigs.map((config: any) => new AppPlugin(config)),
80-
// Setup App registered via AppPlugin so ObjectQLPlugin discovers it
81-
new AppPlugin(setupAppConfig),
89+
// SetupPlugin must come before AuthPlugin (setupNav service dependency)
90+
new SetupPlugin(),
91+
// AuthPlugin contributes to setupNav during init, so it must come AFTER SetupPlugin
92+
new AuthPlugin({
93+
secret: process.env.AUTH_SECRET || 'objectui-server-secret',
94+
baseUrl: process.env.BASE_URL || 'http://localhost:3000',
95+
}),
8296
new HonoServerPlugin({ port: 3000 }),
8397
new ConsolePlugin(),
8498
];

apps/console/src/__tests__/i18n-translations.test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { describe, it, expect, beforeAll, afterAll } from 'vitest';
1313
import { setupServer } from 'msw/node';
1414
import { createKernel, type KernelResult } from '../mocks/createKernel';
1515
import { createAuthHandlers } from '../mocks/authHandlers';
16-
import { appConfigs, setupAppConfig } from '../../objectstack.shared';
16+
import { appConfigs } from '../../objectstack.shared';
1717
import { crmLocales } from '@object-ui/example-crm';
1818

1919
// Expected values from the CRM i18n bundles — avoid hard-coding in assertions
@@ -26,7 +26,8 @@ describe('i18n translations pipeline', () => {
2626

2727
beforeAll(async () => {
2828
result = await createKernel({
29-
appConfigs: [...appConfigs, setupAppConfig],
29+
// SetupPlugin is registered in createKernel, so no need for setupAppConfig here
30+
appConfigs: [...appConfigs],
3031
persistence: false,
3132
mswOptions: {
3233
enableBrowser: false,

apps/console/src/mocks/browser.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { setupWorker } from 'msw/browser';
1616
import { ObjectKernel } from '@objectstack/runtime';
1717
import { InMemoryDriver } from '@objectstack/driver-memory';
1818
import type { MSWPlugin } from '@objectstack/plugin-msw';
19-
import { appConfigs, setupAppConfig, customReportsConfig } from '../../objectstack.shared';
19+
import { appConfigs, customReportsConfig } from '../../objectstack.shared';
2020
import { createKernel } from './createKernel';
2121
import { createAuthHandlers } from './authHandlers';
2222

@@ -43,7 +43,8 @@ export async function startMockServer() {
4343
if (import.meta.env.DEV) console.log('[MSW] Starting ObjectStack Runtime (Browser Mode)...');
4444

4545
const result = await createKernel({
46-
appConfigs: [...appConfigs, setupAppConfig, customReportsConfig],
46+
// SetupPlugin is registered in createKernel, so no need for setupAppConfig here
47+
appConfigs: [...appConfigs, customReportsConfig],
4748
mswOptions: {
4849
enableBrowser: false,
4950
baseUrl: '/api/v1',

apps/console/src/mocks/createKernel.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { ObjectQLPlugin } from '@objectstack/objectql';
1717
import { InMemoryDriver, MemoryAnalyticsService } from '@objectstack/driver-memory';
1818
import { MSWPlugin } from '@objectstack/plugin-msw';
1919
import type { MSWPluginOptions } from '@objectstack/plugin-msw';
20+
import { AuthPlugin } from '@objectstack/plugin-auth';
2021
import { SetupPlugin } from '@objectstack/plugin-setup';
2122
import type { Cube } from '@objectstack/spec/data';
2223
import { http, HttpResponse } from 'msw';
@@ -317,7 +318,14 @@ export async function createKernel(options: KernelOptions): Promise<KernelResult
317318
for (const config of configs) {
318319
await kernel.use(new AppPlugin(config));
319320
}
321+
// SetupPlugin MUST load before AuthPlugin so that the setupNav service
322+
// is registered and available when AuthPlugin.init() tries to contribute menu items.
320323
await kernel.use(new SetupPlugin() as unknown as Plugin);
324+
// AuthPlugin contributes to setupNav during init, so it must come AFTER SetupPlugin.
325+
await kernel.use(new AuthPlugin({
326+
secret: 'objectui-demo-secret',
327+
baseUrl: 'http://localhost:5173', // Vite dev server default
328+
}) as unknown as Plugin);
321329

322330
// Register MemoryAnalyticsService so that HttpDispatcher can serve
323331
// /api/v1/analytics/* endpoints in demo/MSW/dev environments.

apps/console/src/mocks/server.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { ObjectKernel } from '@objectstack/runtime';
1616
import { InMemoryDriver } from '@objectstack/driver-memory';
1717
import { setupServer } from 'msw/node';
1818
import type { MSWPlugin } from '@objectstack/plugin-msw';
19-
import { appConfigs, setupAppConfig, customReportsConfig } from '../../objectstack.shared';
19+
import { appConfigs, customReportsConfig } from '../../objectstack.shared';
2020
import { createKernel } from './createKernel';
2121
import { createAuthHandlers } from './authHandlers';
2222

@@ -34,7 +34,8 @@ export async function startMockServer() {
3434
console.log('[MSW] Starting ObjectStack Runtime (Test Mode)...');
3535

3636
const result = await createKernel({
37-
appConfigs: [...appConfigs, setupAppConfig, customReportsConfig],
37+
// SetupPlugin is registered in createKernel, so no need for setupAppConfig here
38+
appConfigs: [...appConfigs, customReportsConfig],
3839
persistence: false,
3940
mswOptions: {
4041
enableBrowser: false,

objectstack.config.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,16 +64,14 @@ export default {
6464
new AppPlugin(prepareConfig(crmConfig)),
6565
new AppPlugin(prepareConfig(todoConfig)),
6666
new AppPlugin(prepareConfig(kitchenSinkConfig)),
67-
// AuthPlugin before SetupPlugin: both use namespace 'sys', and the
68-
// ObjectQL registry requires the package that owns objects (AuthPlugin →
69-
// com.objectstack.system) to register first.
67+
// SetupPlugin MUST load before AuthPlugin so that the setupNav service
68+
// is registered and available when AuthPlugin.init() tries to contribute menu items.
69+
new SetupPlugin(),
70+
// AuthPlugin contributes to setupNav during init, so it must come AFTER SetupPlugin.
7071
new AuthPlugin({
7172
secret: process.env.AUTH_SECRET || 'objectui-dev-secret',
7273
baseUrl: 'http://localhost:3000',
7374
}),
74-
// SetupPlugin registers setupNav during init and the merged Setup app
75-
// during start. Must come after AuthPlugin to avoid sys namespace collision.
76-
new SetupPlugin(),
7775
new HonoServerPlugin({ port: 3000 }),
7876
new ConsolePlugin(),
7977
],

0 commit comments

Comments
 (0)