Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Preserved skill independence — Each skill remains independently installable/referenceable (no global routing required)

### Fixed
- **MetadataPlugin driver bridging fallback** — Fixed `MetadataPlugin.start()` so the driver service scan fallback (`driver.*`) is reached when ObjectQL returns `null` (not just when it throws). Previously, `setDatabaseDriver` was never called in environments where ObjectQL was not loaded.
- **Auth trustedOrigins test alignment** — Updated `plugin-auth` tests to match the auto-default `http://localhost:*` behavior added in PR #1152 for better-auth CORS support. When no `trustedOrigins` are configured, the implementation correctly defaults to trusting all localhost ports for development convenience.
- **Docs build: lucide-react module resolution** — Added Turbopack `resolveAlias` in `apps/docs/next.config.mjs` so MDX content files in `content/docs/` (outside the app directory) can resolve `lucide-react`. Turbopack starts module resolution from the file's directory, which doesn't have access to the app's `node_modules/`.
- **Client Hono integration test timeout** — Fixed `afterAll` hook timeout in `client.hono.test.ts` by racing `kernel.shutdown()` against a 10s deadline. The shutdown can hang when pino's worker-thread flush callback never fires in CI, so the race ensures the hook completes within the 30s vitest limit.
- **CI: Replace `pnpm/action-setup@v6` with corepack** — Switched all GitHub Actions workflows (`ci.yml`, `lint.yml`, `release.yml`, `validate-deps.yml`, `pr-automation.yml`) from `pnpm/action-setup@v6` to `corepack enable` to fix persistent `ERR_PNPM_BROKEN_LOCKFILE` errors. Corepack reads the exact `packageManager` field from `package.json` (including SHA verification), ensuring the correct pnpm version is used in CI. Also bumped pnpm store cache keys to v3 and added a pnpm version verification step.
- **Broken pnpm lockfile** — Regenerated `pnpm-lock.yaml` from scratch to fix `ERR_PNPM_BROKEN_LOCKFILE` ("expected a single document in the stream, but found more") that was causing all CI jobs to fail. The previous merge of PR #1117 only included workflow cache key changes but did not carry over the regenerated lockfile.
- **service-ai: Fix navigation item labels using deprecated i18n object format** — Replaced `{ key, defaultValue }` i18n objects with plain string labels in `AIServicePlugin`'s Setup App navigation contributions, completing the `I18nLabelSchema` migration from [#1054](https://github.com/objectstack-ai/framework/issues/1054).
Expand Down
9 changes: 9 additions & 0 deletions apps/docs/next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ const config = {
typescript: {
ignoreBuildErrors: false,
},
turbopack: {
resolveAlias: {
// MDX content lives in ../../content/docs/ (outside the app directory).
// Turbopack resolves modules starting from the file's directory, so it
// can't find packages installed under this app's node_modules/.
// Alias lucide-react so external MDX files can import it.
'lucide-react': './node_modules/lucide-react',
},
},
images: {
remotePatterns: [
{
Expand Down
14 changes: 11 additions & 3 deletions packages/client/src/client.hono.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,19 @@ describe('ObjectStackClient (with Hono Server)', () => {
baseUrl = `http://localhost:${port}`;

console.log(`Test server running at ${baseUrl}`);
});
}, 30_000);

afterAll(async () => {
if (kernel) await kernel.shutdown();
});
if (kernel) {
// Race shutdown against a hard deadline.
// kernel.shutdown() can hang when pino's flush callback never fires
// in CI (worker-thread transport timing issues), so cap the wait.
await Promise.race([
kernel.shutdown(),
new Promise<void>((resolve) => setTimeout(resolve, 10_000)),
]);
}
}, 30_000);

it('should connect to hono server and discover endpoints', async () => {
const client = new ObjectStackClient({ baseUrl });
Expand Down
9 changes: 8 additions & 1 deletion packages/metadata/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ export class MetadataPlugin implements Plugin {
// Bridge database driver from kernel service registry to MetadataManager.
// Uses ObjectQL engine's datasource mapping to resolve the correct driver
// for sys_metadata (respects namespace → datasource routing).
// Falls back to the first available driver.* service when ObjectQL is unavailable.
let driverBridged = false;
try {
const ql = ctx.getService<any>('objectql');
if (ql) {
Expand All @@ -118,12 +120,17 @@ export class MetadataPlugin implements Plugin {
driver: driver.name,
});
this.manager.setDatabaseDriver(driver);
driverBridged = true;
} else {
ctx.logger.debug('[MetadataPlugin] ObjectQL could not resolve driver for metadata table', { tableName });
}
}
} catch {
// ObjectQL not available — fall back to first available driver service
// ObjectQL not available — will fall through to driver service fallback below
}

// Fallback: scan for driver.* services when ObjectQL didn't provide a driver
if (!driverBridged) {
try {
const services = ctx.getServices();
for (const [serviceName, service] of services) {
Expand Down
8 changes: 4 additions & 4 deletions packages/plugins/plugin-auth/src/auth-manager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ describe('AuthManager', () => {
]);
});

it('should NOT include trustedOrigins key when not provided', () => {
it('should default to localhost wildcard when trustedOrigins not provided', () => {
let capturedConfig: any;
(betterAuth as any).mockImplementation((config: any) => {
capturedConfig = config;
Expand All @@ -449,10 +449,10 @@ describe('AuthManager', () => {
manager.getAuthInstance();
warnSpy.mockRestore();

expect(capturedConfig).not.toHaveProperty('trustedOrigins');
expect(capturedConfig.trustedOrigins).toEqual(['http://localhost:*']);
});

it('should NOT include trustedOrigins key when array is empty', () => {
it('should default to localhost wildcard when trustedOrigins array is empty', () => {
let capturedConfig: any;
(betterAuth as any).mockImplementation((config: any) => {
capturedConfig = config;
Expand All @@ -468,7 +468,7 @@ describe('AuthManager', () => {
manager.getAuthInstance();
warnSpy.mockRestore();

expect(capturedConfig).not.toHaveProperty('trustedOrigins');
expect(capturedConfig.trustedOrigins).toEqual(['http://localhost:*']);
});
});

Expand Down
Loading