Some checks failed
ci/woodpecker/pr/ci Pipeline failed
Independent review of PR #870 found defaultCapabilityProbe() resolved the installed CLI via req.resolve('@mosaicstack/mosaic/package.json') — a subpath NOT present in package.json's `exports` map. Node throws ERR_PACKAGE_PATH_NOT_EXPORTED for that on every real install, which the catch-all silently turned into an always-null probe: leaseEnforcementActivatable() could never return true anywhere, defeating the card's purpose. Fix: resolve via the already-exported "." entry instead (require.resolve('@mosaicstack/mosaic') -> dist/index.js), then take cli.js as its sibling in the same built dist/ directory — matching package.json's bin.mosaic mapping. No change to the exports map itself (that would mask a separate, out-of-scope pre-existing issue in resolveTool()/launch.ts per review guidance). Adds a positive-path test that stages a realistic fake dist/index.js + dist/cli.js at the package's real resolved location and asserts defaultCapabilityProbe() returns the actual {name, version} capability object with zero mocking of the resolver. Verified red against the prior (reverted-and-restored) buggy resolution before landing the fix, and green after — the previous only-unmocked test asserted null for the wrong reason (masking this bug) and is left in place alongside the new one. Re-verified: launch.spec.ts (30), fail-closed-regression.spec.ts (2), and runtime_tools_unittest.py (25, including both C-REGRESS-locked fail-closed cases) all still green. typecheck/lint/format:check pass via `turbo run ... --filter=@mosaicstack/mosaic`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
218 lines
8.8 KiB
TypeScript
218 lines
8.8 KiB
TypeScript
import { describe, it, expect, afterEach } from 'vitest';
|
|
import { Command } from 'commander';
|
|
import { existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
import { dirname, join } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
import {
|
|
LEASE_ACTIVATION_CAPABILITY,
|
|
LEASE_CAPABILITY_PROBE_COMMAND,
|
|
defaultCapabilityProbe,
|
|
defaultSupervisorProbe,
|
|
leaseEnforcementActivatable,
|
|
registerLeaseCapabilityProbe,
|
|
type LeaseActivationCapability,
|
|
type SupervisorProbeResult,
|
|
} from './lease-activation-probe.js';
|
|
|
|
/**
|
|
* Red-first tests for issue #869 Point-1 C1 — leaseEnforcementActivatable().
|
|
*
|
|
* Root cause under test: #828 shipped the lease broker's ENFORCEMENT half
|
|
* (hooks) and ACTIVATION half (execLeaseGatedRuntime + a running daemon.py
|
|
* broker) on different channels, and they drifted — the published CLI
|
|
* tarball lacked the activation half even though it existed in source. The
|
|
* predicate here must say NO when either half of activation is unavailable,
|
|
* and only YES when both are genuinely present — never based on "does the
|
|
* source file exist", but on a real capability signal + real supervisor
|
|
* detection.
|
|
*/
|
|
|
|
const compatibleCapability: LeaseActivationCapability = { ...LEASE_ACTIVATION_CAPABILITY };
|
|
const presentSupervisor: SupervisorProbeResult = {
|
|
supervisorPresent: true,
|
|
socketPath: '/run/user/1000/mosaic-lease/broker.sock',
|
|
};
|
|
|
|
describe('leaseEnforcementActivatable', () => {
|
|
it('is false when the activation capability is absent (null)', () => {
|
|
const result = leaseEnforcementActivatable({
|
|
getCapability: () => null,
|
|
probeSupervisor: () => presentSupervisor,
|
|
});
|
|
expect(result).toBe(false);
|
|
});
|
|
|
|
it('is false when the activation capability name does not match', () => {
|
|
const result = leaseEnforcementActivatable({
|
|
getCapability: () => ({
|
|
name: 'some-other-capability',
|
|
version: LEASE_ACTIVATION_CAPABILITY.version,
|
|
}),
|
|
probeSupervisor: () => presentSupervisor,
|
|
});
|
|
expect(result).toBe(false);
|
|
});
|
|
|
|
it('is false when the activation capability version is incompatible (stale/newer build)', () => {
|
|
const result = leaseEnforcementActivatable({
|
|
getCapability: () => ({
|
|
name: LEASE_ACTIVATION_CAPABILITY.name,
|
|
version: LEASE_ACTIVATION_CAPABILITY.version + 1,
|
|
}),
|
|
probeSupervisor: () => presentSupervisor,
|
|
});
|
|
expect(result).toBe(false);
|
|
});
|
|
|
|
it('is false when the supervisor artifacts (launcher/daemon) are not present', () => {
|
|
const result = leaseEnforcementActivatable({
|
|
getCapability: () => compatibleCapability,
|
|
probeSupervisor: () => ({
|
|
supervisorPresent: false,
|
|
socketPath: presentSupervisor.socketPath,
|
|
}),
|
|
});
|
|
expect(result).toBe(false);
|
|
});
|
|
|
|
it('is false when the supervisor socket path is not resolvable', () => {
|
|
const result = leaseEnforcementActivatable({
|
|
getCapability: () => compatibleCapability,
|
|
probeSupervisor: () => ({ supervisorPresent: true, socketPath: null }),
|
|
});
|
|
expect(result).toBe(false);
|
|
});
|
|
|
|
it('is false when BOTH capability and supervisor are absent', () => {
|
|
const result = leaseEnforcementActivatable({
|
|
getCapability: () => null,
|
|
probeSupervisor: () => ({ supervisorPresent: false, socketPath: null }),
|
|
});
|
|
expect(result).toBe(false);
|
|
});
|
|
|
|
it('is true when a compatible capability AND a resolvable supervisor are both present', () => {
|
|
const result = leaseEnforcementActivatable({
|
|
getCapability: () => compatibleCapability,
|
|
probeSupervisor: () => presentSupervisor,
|
|
});
|
|
expect(result).toBe(true);
|
|
});
|
|
|
|
it('uses the real default probes when no deps are injected (does not throw)', () => {
|
|
// No live broker / built CLI is guaranteed in a test environment, so this
|
|
// only asserts the predicate degrades to a safe boolean rather than
|
|
// throwing — the fail-closed behavior itself is covered by the injected
|
|
// cases above.
|
|
expect(() => leaseEnforcementActivatable()).not.toThrow();
|
|
expect(typeof leaseEnforcementActivatable()).toBe('boolean');
|
|
});
|
|
});
|
|
|
|
describe('defaultCapabilityProbe', () => {
|
|
it('returns null (fail-closed) when no built CLI artifact is resolvable', () => {
|
|
// This source checkout has no dist/cli.js built for @mosaicstack/mosaic,
|
|
// so the probe must report "no capability" rather than fabricate one
|
|
// from source-tree presence — this is the exact distinction #828's
|
|
// version skew needed: source existing is not the same as the published
|
|
// artifact advertising the capability.
|
|
expect(defaultCapabilityProbe()).toBeNull();
|
|
});
|
|
|
|
describe('positive path — a real built dist/cli.js advertises the capability', () => {
|
|
// Resolve the ACTUAL @mosaicstack/mosaic package root on disk (two levels
|
|
// up from src/commands/), so this test exercises the exact same
|
|
// require.resolve('@mosaicstack/mosaic') self-reference codepath
|
|
// defaultCapabilityProbe() itself uses — no mocking of the resolver.
|
|
// This is the regression proof for the reviewer-found bug: the previous
|
|
// implementation resolved via the NOT-exported './package.json' subpath
|
|
// (ERR_PACKAGE_PATH_NOT_EXPORTED on every real install), which the
|
|
// catch-all silently turned into an always-null probe. That bug returns
|
|
// null here regardless of a built dist/cli.js being present — so this
|
|
// test fails red against it and only passes once resolution goes through
|
|
// the package's already-exported "." entry.
|
|
const mosaicRoot = join(dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
const distDir = join(mosaicRoot, 'dist');
|
|
const distIndexPath = join(distDir, 'index.js');
|
|
const distCliPath = join(distDir, 'cli.js');
|
|
|
|
// dist/ is gitignored and unbuilt in a fresh checkout; only remove what
|
|
// THIS test created, never a real build that predates it.
|
|
const distDirPreexisted = existsSync(distDir);
|
|
const indexPreexisted = existsSync(distIndexPath);
|
|
const cliPreexisted = existsSync(distCliPath);
|
|
|
|
afterEach(() => {
|
|
if (!cliPreexisted) rmSync(distCliPath, { force: true });
|
|
if (!indexPreexisted) rmSync(distIndexPath, { force: true });
|
|
if (!distDirPreexisted) rmSync(distDir, { recursive: true, force: true });
|
|
});
|
|
|
|
it('returns the real {name, version} capability object', () => {
|
|
mkdirSync(distDir, { recursive: true });
|
|
// Minimal stand-in for the built "." export target — only needs to
|
|
// exist for require.resolve('@mosaicstack/mosaic') to succeed; its
|
|
// content is never loaded by defaultCapabilityProbe().
|
|
writeFileSync(distIndexPath, 'export {};\n');
|
|
// Minimal stand-in for the built CLI's hidden __lease-capability
|
|
// subcommand — prints exactly what registerLeaseCapabilityProbe()
|
|
// wires the real `mosaic __lease-capability` command to print.
|
|
writeFileSync(
|
|
distCliPath,
|
|
`process.stdout.write(JSON.stringify(${JSON.stringify(LEASE_ACTIVATION_CAPABILITY)}));\n`,
|
|
);
|
|
|
|
const result = defaultCapabilityProbe();
|
|
expect(result).toEqual(LEASE_ACTIVATION_CAPABILITY);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('defaultSupervisorProbe', () => {
|
|
it('returns a well-shaped result without starting or connecting to anything', () => {
|
|
const result = defaultSupervisorProbe({});
|
|
expect(typeof result.supervisorPresent).toBe('boolean');
|
|
expect(result.socketPath === null || typeof result.socketPath === 'string').toBe(true);
|
|
});
|
|
|
|
it('resolves a socket path from an explicit MOSAIC_LEASE_BROKER_SOCKET override', () => {
|
|
const result = defaultSupervisorProbe({ MOSAIC_LEASE_BROKER_SOCKET: '/tmp/explicit.sock' });
|
|
expect(result.socketPath).toBe('/tmp/explicit.sock');
|
|
});
|
|
});
|
|
|
|
describe('registerLeaseCapabilityProbe', () => {
|
|
it('registers a hidden subcommand named __lease-capability', () => {
|
|
const program = new Command();
|
|
program.exitOverride();
|
|
registerLeaseCapabilityProbe(program);
|
|
|
|
const registered = program.commands.find((c) => c.name() === LEASE_CAPABILITY_PROBE_COMMAND);
|
|
expect(registered).toBeDefined();
|
|
// Commander exposes "hidden" only as help-output suppression (no public
|
|
// getter) — assert the observable behavior instead of a private field.
|
|
expect(program.helpInformation()).not.toContain(LEASE_CAPABILITY_PROBE_COMMAND);
|
|
});
|
|
|
|
it('prints the capability constant as JSON when invoked', () => {
|
|
const program = new Command();
|
|
program.exitOverride();
|
|
registerLeaseCapabilityProbe(program);
|
|
|
|
let written = '';
|
|
const originalWrite = process.stdout.write.bind(process.stdout);
|
|
process.stdout.write = ((chunk: string) => {
|
|
written += chunk;
|
|
return true;
|
|
}) as typeof process.stdout.write;
|
|
|
|
try {
|
|
program.parse(['node', 'mosaic', LEASE_CAPABILITY_PROBE_COMMAND]);
|
|
} finally {
|
|
process.stdout.write = originalWrite;
|
|
}
|
|
|
|
expect(JSON.parse(written)).toEqual(LEASE_ACTIVATION_CAPABILITY);
|
|
});
|
|
});
|