sync: update from private repo (e7c4a56)
CI / build-and-test (push) Has been cancelled

This commit is contained in:
oss-sync
2026-06-09 09:43:05 +00:00
parent 483464597a
commit 2bab882d08
8 changed files with 125 additions and 12 deletions
+7
View File
@@ -246,6 +246,13 @@ export function createCoreServer(opts: CoreServerOptions): {
);
}
const authActive = authUsable;
if (!authActive) {
// No-auth single-user mode: per-user rows are owned by the synthetic
// 'local' id, and several tables FK to users(id) (ssh_user_deks,
// browser_session_profiles, …). Seed the 'local' user row so those inserts
// succeed — without it, creating an SSH connection failed with create_failed.
repo.ensureLocalUser();
}
let authenticateUpgrade: import('./auth.js').UpgradeAuthChecker | undefined;
if (authActive) {
+51
View File
@@ -0,0 +1,51 @@
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { mkdtempSync, rmSync } from 'fs';
import { join } from 'path';
import { tmpdir } from 'os';
import { Repository } from './repository.js';
import { bootstrapSystemDek, getOrCreateUserDek } from '../ssh/crypto.js';
// Regression: SSH connection creation in no-auth mode returned `create_failed`.
// Root cause — `ssh_user_deks.user_id REFERENCES users(id)` with foreign keys
// ON (Repository enables the pragma). No-auth owns rows under the synthetic
// 'local' id, but no `users` row with id='local' exists, so the lazy DEK insert
// hit a FK violation and getOrCreateUserDek threw → create_failed. Seeding the
// 'local' user row satisfies the FK (and the whole class of users(id) FKs).
const VALID_KEY = 'a'.repeat(64);
describe('Repository.ensureLocalUser (no-auth SSH create_failed fix)', () => {
let tmpDir = '';
let repo: Repository;
beforeEach(() => {
process.env.MCP_ENCRYPTION_KEY = VALID_KEY;
tmpDir = mkdtempSync(join(tmpdir(), 'ensure-local-'));
repo = new Repository(join(tmpDir, 'db.sqlite')); // constructor enables foreign_keys=ON
bootstrapSystemDek(repo.getDb());
});
afterEach(() => {
repo.close();
rmSync(tmpDir, { recursive: true, force: true });
delete process.env.MCP_ENCRYPTION_KEY;
});
it('reproduces the bug: creating a DEK for owner "local" throws when the user row is absent', () => {
expect(() => getOrCreateUserDek(repo.getDb(), 'local')).toThrow();
});
it('after ensureLocalUser the per-user DEK insert (and thus SSH create) succeeds', () => {
repo.ensureLocalUser();
const dek = getOrCreateUserDek(repo.getDb(), 'local');
expect(Buffer.isBuffer(dek)).toBe(true);
expect(dek.length).toBe(32);
});
it('is idempotent — repeated calls keep a single "local" user', () => {
repo.ensureLocalUser();
repo.ensureLocalUser();
const u = repo.getUserById('local');
expect(u?.id).toBe('local');
expect(u?.name).toBe('local');
});
});
+20
View File
@@ -2457,6 +2457,26 @@ export class Repository {
return user;
}
/**
* Ensure the synthetic 'local' user row exists. No-auth single-user
* deployments own per-user rows under the id 'local' (tasks, jobs, SSH
* connections, DEKs, …). Many of those tables FK to users(id) with
* foreign_keys ON, so the row must exist or the inserts fail — e.g.
* ssh_user_deks → SSH connection creation returned create_failed.
* Idempotent (INSERT OR IGNORE), so it is safe to call on every startup.
* role='admin' mirrors the synthetic 'local' user the HTTP layer injects
* for task-visibility routes in no-auth mode.
*/
ensureLocalUser(): void {
const now = new Date().toISOString();
this.db
.prepare(
`INSERT OR IGNORE INTO users (id, email, name, avatar_url, role, status, created_at, updated_at)
VALUES ('local', 'local@localhost', 'local', NULL, 'admin', 'active', @now, @now)`
)
.run({ now });
}
getUserById(id: string): User | null {
const row = this.db
.prepare('SELECT * FROM users WHERE id = ?')