diff --git a/.changeset/dev-plugin-protocol-family-removed.md b/.changeset/dev-plugin-protocol-family-removed.md new file mode 100644 index 0000000000..46a431ec27 --- /dev/null +++ b/.changeset/dev-plugin-protocol-family-removed.md @@ -0,0 +1,42 @@ +--- +"@objectstack/spec": major +--- + +refactor(spec)!: remove the Dev Mode Plugin Protocol family — a declared dev protocol nothing implemented, whose stub vocabulary described the design ADR-0115 retired (#4149) + +`DevPluginConfigSchema`, `DevServiceOverrideSchema`, `DevFixtureConfigSchema`, +`DevToolsConfigSchema` and `DevPluginPreset` (`@objectstack/spec/kernel`, +dev-plugin.zod) are removed outright. The family declared a full dev-mode +configuration protocol — presets (minimal/standard/full), fixture loading, a +dev-tools dashboard on port 4400, per-service `mock`/`memory`/`stub`/ +`passthrough` strategies, simulated latency — and none of it ever existed: + +- **Zero consumers.** `@objectstack/plugin-dev` reads its own + `DevPluginOptions` interface and never imported these schemas; no other + package did either. The only references were the generated artifacts and the + family's own shape test. +- **No load path parsed it.** `stack.devPlugins` takes + `ManifestSchema | string` (plugin manifests/names), not this config — so no + authored source can carry these keys, which is why there is deliberately NO + `retiredKey()` tombstone and NO ADR-0087 conversion: a prescription nobody + can receive is noise, and there is no source for `os migrate meta` to + rewrite (the `plugin-runtime.zod.ts` DynamicLoadingConfig precedent, #3950). +- **Its vocabulary contradicted the platform.** `strategy: 'stub'` taught the + fill-the-slot-with-a-fake design that ADR-0115 retired; keeping the schema + meant the spec recommending what the runtime forbids. + +FROM → TO: if you imported any of the five types from +`@objectstack/spec/kernel`, delete the import — there is nothing to migrate to, +because nothing ever consumed the values. To configure local development, use +`DevPluginOptions` from `@objectstack/plugin-dev` (port, seedAdminUser, +authSecret, per-part `services` toggles, extraPlugins, stack). + +The retirement kit: baselines dropped deliberately (`json-schema.manifest.json` +minus the five `kernel/Dev*` entries; `authorable-surface.json` minus the 22 +`kernel/Dev*` lines — nothing can author them, so no `[RETIRED]` markers); +`api-surface.json` regenerated (the five exports leave the public surface); +generated reference doc removed by `gen:docs`; v17 release notes' dead-clusters +table extended. No liveness-ledger entries existed (the ledger tracks metadata +types; this was never one). + +No runtime behaviour changes — that impossibility is the reason for the removal. diff --git a/content/docs/references/kernel/dev-plugin.mdx b/content/docs/references/kernel/dev-plugin.mdx deleted file mode 100644 index f523f7056f..0000000000 --- a/content/docs/references/kernel/dev-plugin.mdx +++ /dev/null @@ -1,130 +0,0 @@ ---- -title: Dev Plugin -description: Dev Plugin protocol schemas ---- - -{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs live in the module folders under content/docs/. */} - -# Dev Mode Plugin Protocol - -Declared configuration vocabulary for a development-mode plugin: per-service - -dev strategies, fixture loading, developer tooling, presets. - -⚠️ **Declared, not implemented — pending enforce-or-remove (#4149).** - -The shipped `@objectstack/plugin-dev` consumes its own `DevPluginOptions` - -interface, NOT this schema, and none of the surfaces below (presets, - -fixtures, dev-tools dashboard, per-service strategies, simulated latency) - -exist in it. Since ADR-0115 it is an **assembly** plugin: it wires the real - -platform plugins for local development and registers no stub or simulated - -services — an unfilled slot answers exactly as it does in production. The - -`strategy: 'stub'` value in particular describes a behaviour the platform - -has retired. Do not build against this file until #4149 resolves it. - -Original design goals, kept for the #4149 evaluation: - -- Zero-config by default: `devPlugins: ['@objectstack/plugin-dev']` - -- Every service can be overridden or disabled individually - -- Preset profiles (minimal / standard / full) for common scenarios - - -**Source:** `packages/spec/src/kernel/dev-plugin.zod.ts` - - -## TypeScript Usage - -```typescript -import { DevFixtureConfig, DevPluginConfig, DevPluginPreset, DevServiceOverride, DevToolsConfig } from '@objectstack/spec/kernel'; -import type { DevFixtureConfig, DevPluginConfig, DevPluginPreset, DevServiceOverride, DevToolsConfig } from '@objectstack/spec/kernel'; - -// Validate data -const result = DevFixtureConfig.parse(data); -``` - ---- - -## DevFixtureConfig - -### Properties - -| Property | Type | Required | Description | -| :--- | :--- | :--- | :--- | -| **enabled** | `boolean` | ✅ | Load fixture data on startup | -| **paths** | `string[]` | optional | Glob patterns for fixture files | -| **resetBeforeLoad** | `boolean` | ✅ | Clear existing data before loading fixtures | -| **envFilter** | `string[]` | optional | Only load fixtures matching these environment tags | - - ---- - -## DevPluginConfig - -### Properties - -| Property | Type | Required | Description | -| :--- | :--- | :--- | :--- | -| **preset** | `Enum<'minimal' \| 'standard' \| 'full'>` | ✅ | Base configuration preset | -| **services** | `Record; config?: Record }>` | optional | Per-service dev overrides keyed by service name | -| **fixtures** | `{ enabled: boolean; paths?: string[]; resetBeforeLoad: boolean; envFilter?: string[] }` | optional | Fixture data loading configuration | -| **tools** | `{ hotReload: boolean; requestInspector: boolean; dbExplorer: boolean; verboseLogging: boolean; … }` | optional | Developer tooling settings | -| **port** | `integer` | ✅ | Port for the dev-tools dashboard | -| **open** | `boolean` | ✅ | Auto-open dev dashboard in browser | -| **seedAdminUser** | `boolean` | ✅ | Create a default admin user for development | -| **simulatedLatency** | `integer` | ✅ | Artificial latency (ms) added to service calls | - - ---- - -## DevPluginPreset - -Predefined dev configuration profile - -### Allowed Values - -* `minimal` -* `standard` -* `full` - - ---- - -## DevServiceOverride - -### Properties - -| Property | Type | Required | Description | -| :--- | :--- | :--- | :--- | -| **service** | `string` | ✅ | Target service identifier | -| **enabled** | `boolean` | ✅ | Enable or disable this service | -| **strategy** | `Enum<'mock' \| 'memory' \| 'stub' \| 'passthrough'>` | ✅ | Implementation strategy for development | -| **config** | `Record` | optional | Strategy-specific configuration for this service override | - - ---- - -## DevToolsConfig - -### Properties - -| Property | Type | Required | Description | -| :--- | :--- | :--- | :--- | -| **hotReload** | `boolean` | ✅ | Enable HMR / live-reload | -| **requestInspector** | `boolean` | ✅ | Enable request inspector | -| **dbExplorer** | `boolean` | ✅ | Enable database explorer UI | -| **verboseLogging** | `boolean` | ✅ | Enable verbose logging | -| **apiDocs** | `boolean` | ✅ | Serve OpenAPI docs at /_dev/docs | -| **mailCatcher** | `boolean` | ✅ | Capture outbound emails in dev | - - ---- - diff --git a/content/docs/references/kernel/index.mdx b/content/docs/references/kernel/index.mdx index d0576bd6d2..a969832035 100644 --- a/content/docs/references/kernel/index.mdx +++ b/content/docs/references/kernel/index.mdx @@ -10,7 +10,6 @@ This section contains all protocol schemas for the kernel layer of ObjectStack. - diff --git a/content/docs/references/kernel/meta.json b/content/docs/references/kernel/meta.json index 89f77f1f99..0fd274d631 100644 --- a/content/docs/references/kernel/meta.json +++ b/content/docs/references/kernel/meta.json @@ -25,7 +25,6 @@ "cli-extension", "cluster", "context", - "dev-plugin", "execution-context", "metadata-customization", "metadata-loader", diff --git a/content/docs/releases/v17.mdx b/content/docs/releases/v17.mdx index e3abaca579..00023347fd 100644 --- a/content/docs/releases/v17.mdx +++ b/content/docs/releases/v17.mdx @@ -806,6 +806,7 @@ import or the authored key. | `AuditConfig` cluster (`@objectstack/spec/system`) | dead since #1878 | | Capabilities-descriptor cluster (`ObjectQL`/`ObjectUI`/`Kernel`/`ObjectStack`/`ObjectOS CapabilitiesSchema`) | static snapshots superseded by runtime discovery | | `FeatureFlagSchema` (`kernel` feature.zod) | orphaned module | +| `DevPluginConfigSchema` cluster (`kernel` dev-plugin.zod — `DevServiceOverride` / `DevFixtureConfig` / `DevToolsConfig` / `DevPluginPreset`) | a declared dev-mode protocol (presets, fixtures, dev-tools dashboard, per-service mock/stub strategies, simulated latency) nothing implemented and no load path parsed — `@objectstack/plugin-dev` reads its own `DevPluginOptions`, and the `strategy: 'stub'` vocabulary described the dev-stub design ADR-0115 retired (#4149) | | `SkillSchema.permissions` | never gated anything (#3686) | | `tool.requiresConfirmation` | a safety flag nothing enforced (#3715) | | `object.enable.trash` / `enable.mru` | ADR-0049 enforce-or-remove close-out (#2377) | diff --git a/packages/spec/api-surface.json b/packages/spec/api-surface.json index 06a14958a8..f97400ee67 100644 --- a/packages/spec/api-surface.json +++ b/packages/spec/api-surface.json @@ -1405,16 +1405,6 @@ "DependencyStatusEnum (const)", "DeprecationNotice (type)", "DeprecationNoticeSchema (const)", - "DevFixtureConfig (type)", - "DevFixtureConfigSchema (const)", - "DevPluginConfig (type)", - "DevPluginConfigInput (type)", - "DevPluginConfigSchema (const)", - "DevPluginPreset (type)", - "DevServiceOverride (type)", - "DevServiceOverrideSchema (const)", - "DevToolsConfig (type)", - "DevToolsConfigSchema (const)", "DisablePackageRequest (type)", "DisablePackageRequestSchema (const)", "DisablePackageResponse (type)", diff --git a/packages/spec/authorable-surface.json b/packages/spec/authorable-surface.json index 0477710954..12dd1b800b 100644 --- a/packages/spec/authorable-surface.json +++ b/packages/spec/authorable-surface.json @@ -1,5 +1,5 @@ { - "description": "Ratchet of every AUTHORABLE key in the spec — what a metadata author may write, which for this platform IS the third-party API. Auto-updated on additions (commit the change). A key that disappears without a tombstone fails gen:schema, because these schemas are not .strict() and Zod would silently strip it. \"[RETIRED]\" marks a tombstoned key that still rejects with an upgrade prescription. See #3855, ADR-0059 §5.", + "description": "Ratchet of every AUTHORABLE key in the spec \u2014 what a metadata author may write, which for this platform IS the third-party API. Auto-updated on additions (commit the change). A key that disappears without a tombstone fails gen:schema, because these schemas are not .strict() and Zod would silently strip it. \"[RETIRED]\" marks a tombstoned key that still rejects with an upgrade prescription. See #3855, ADR-0059 \u00a75.", "keys": [ "ai/AIModelConfig:maxTokens", "ai/AIModelConfig:model", @@ -4598,28 +4598,6 @@ "kernel/DeprecationNotice:migrationPath", "kernel/DeprecationNotice:reason", "kernel/DeprecationNotice:removeIn", - "kernel/DevFixtureConfig:enabled", - "kernel/DevFixtureConfig:envFilter", - "kernel/DevFixtureConfig:paths", - "kernel/DevFixtureConfig:resetBeforeLoad", - "kernel/DevPluginConfig:fixtures", - "kernel/DevPluginConfig:open", - "kernel/DevPluginConfig:port", - "kernel/DevPluginConfig:preset", - "kernel/DevPluginConfig:seedAdminUser", - "kernel/DevPluginConfig:services", - "kernel/DevPluginConfig:simulatedLatency", - "kernel/DevPluginConfig:tools", - "kernel/DevServiceOverride:config", - "kernel/DevServiceOverride:enabled", - "kernel/DevServiceOverride:service", - "kernel/DevServiceOverride:strategy", - "kernel/DevToolsConfig:apiDocs", - "kernel/DevToolsConfig:dbExplorer", - "kernel/DevToolsConfig:hotReload", - "kernel/DevToolsConfig:mailCatcher", - "kernel/DevToolsConfig:requestInspector", - "kernel/DevToolsConfig:verboseLogging", "kernel/DisablePackageRequest:id", "kernel/DisablePackageResponse:message", "kernel/DisablePackageResponse:package", diff --git a/packages/spec/json-schema.manifest.json b/packages/spec/json-schema.manifest.json index 5893376d74..ede9396721 100644 --- a/packages/spec/json-schema.manifest.json +++ b/packages/spec/json-schema.manifest.json @@ -1,5 +1,5 @@ { - "description": "Ratchet manifest of every JSON Schema emitted by scripts/build-schemas.ts. Auto-appended when new schemas are added (commit the change). A listed schema that a build no longer emits fails gen:schema — remove a key ONLY for a deliberate retirement. See #2978.", + "description": "Ratchet manifest of every JSON Schema emitted by scripts/build-schemas.ts. Auto-appended when new schemas are added (commit the change). A listed schema that a build no longer emits fails gen:schema \u2014 remove a key ONLY for a deliberate retirement. See #2978.", "schemas": [ "ai/AIModelConfig", "ai/AIUsageRecord", @@ -957,11 +957,6 @@ "kernel/DependencyResolutionResult", "kernel/DependencyStatusEnum", "kernel/DeprecationNotice", - "kernel/DevFixtureConfig", - "kernel/DevPluginConfig", - "kernel/DevPluginPreset", - "kernel/DevServiceOverride", - "kernel/DevToolsConfig", "kernel/DisablePackageRequest", "kernel/DisablePackageResponse", "kernel/DistributedStateConfig", diff --git a/packages/spec/src/kernel/dev-plugin.test.ts b/packages/spec/src/kernel/dev-plugin.test.ts deleted file mode 100644 index eb861cf4f7..0000000000 --- a/packages/spec/src/kernel/dev-plugin.test.ts +++ /dev/null @@ -1,234 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import { - DevServiceOverrideSchema, - DevFixtureConfigSchema, - DevToolsConfigSchema, - DevPluginPreset, - DevPluginConfigSchema, -} from './dev-plugin.zod'; - -describe('Dev Mode Plugin Protocol', () => { - // ========================================================================== - // DevServiceOverrideSchema - // ========================================================================== - describe('DevServiceOverrideSchema', () => { - it('should validate minimal service override', () => { - const result = DevServiceOverrideSchema.safeParse({ service: 'auth' }); - expect(result.success).toBe(true); - if (result.success) { - expect(result.data.enabled).toBe(true); - expect(result.data.strategy).toBe('memory'); - } - }); - - it('should validate full service override', () => { - const override = { - service: 'eventBus', - enabled: true, - strategy: 'mock' as const, - config: { recordCalls: true }, - }; - - const result = DevServiceOverrideSchema.safeParse(override); - expect(result.success).toBe(true); - if (result.success) { - expect(result.data.strategy).toBe('mock'); - expect(result.data.config?.recordCalls).toBe(true); - } - }); - - it('should accept all strategy values', () => { - const strategies = ['mock', 'memory', 'stub', 'passthrough'] as const; - for (const strategy of strategies) { - const result = DevServiceOverrideSchema.safeParse({ service: 'svc', strategy }); - expect(result.success).toBe(true); - } - }); - - it('should reject empty service name', () => { - const result = DevServiceOverrideSchema.safeParse({ service: '' }); - expect(result.success).toBe(false); - }); - - it('should reject invalid strategy', () => { - const result = DevServiceOverrideSchema.safeParse({ - service: 'auth', - strategy: 'invalid', - }); - expect(result.success).toBe(false); - }); - }); - - // ========================================================================== - // DevFixtureConfigSchema - // ========================================================================== - describe('DevFixtureConfigSchema', () => { - it('should apply default values', () => { - const result = DevFixtureConfigSchema.parse({}); - expect(result.enabled).toBe(true); - expect(result.resetBeforeLoad).toBe(true); - }); - - it('should validate full fixture config', () => { - const config = { - enabled: true, - paths: ['./fixtures/*.json', './test/data/*.yml'], - resetBeforeLoad: false, - envFilter: ['dev', 'demo'], - }; - - const result = DevFixtureConfigSchema.safeParse(config); - expect(result.success).toBe(true); - if (result.success) { - expect(result.data.paths).toHaveLength(2); - expect(result.data.envFilter).toEqual(['dev', 'demo']); - } - }); - - it('should allow disabled fixtures', () => { - const result = DevFixtureConfigSchema.parse({ enabled: false }); - expect(result.enabled).toBe(false); - }); - }); - - // ========================================================================== - // DevToolsConfigSchema - // ========================================================================== - describe('DevToolsConfigSchema', () => { - it('should apply default values', () => { - const result = DevToolsConfigSchema.parse({}); - expect(result.hotReload).toBe(true); - expect(result.requestInspector).toBe(false); - expect(result.dbExplorer).toBe(false); - expect(result.verboseLogging).toBe(true); - expect(result.apiDocs).toBe(true); - expect(result.mailCatcher).toBe(false); - }); - - it('should accept all tools enabled', () => { - const config = { - hotReload: true, - requestInspector: true, - dbExplorer: true, - verboseLogging: true, - apiDocs: true, - mailCatcher: true, - }; - - const result = DevToolsConfigSchema.safeParse(config); - expect(result.success).toBe(true); - if (result.success) { - expect(result.data.mailCatcher).toBe(true); - expect(result.data.dbExplorer).toBe(true); - } - }); - }); - - // ========================================================================== - // DevPluginPreset - // ========================================================================== - describe('DevPluginPreset', () => { - it('should validate preset values', () => { - expect(DevPluginPreset.safeParse('minimal').success).toBe(true); - expect(DevPluginPreset.safeParse('standard').success).toBe(true); - expect(DevPluginPreset.safeParse('full').success).toBe(true); - }); - - it('should reject invalid preset', () => { - expect(DevPluginPreset.safeParse('custom').success).toBe(false); - }); - }); - - // ========================================================================== - // DevPluginConfigSchema - // ========================================================================== - describe('DevPluginConfigSchema', () => { - it('should accept zero-config (empty object)', () => { - const result = DevPluginConfigSchema.parse({}); - expect(result.preset).toBe('standard'); - expect(result.port).toBe(4400); - expect(result.open).toBe(false); - expect(result.seedAdminUser).toBe(true); - expect(result.simulatedLatency).toBe(0); - }); - - it('should accept preset-only config', () => { - const result = DevPluginConfigSchema.parse({ preset: 'full' }); - expect(result.preset).toBe('full'); - }); - - it('should accept config with per-service overrides', () => { - const config = { - preset: 'standard' as const, - services: { - auth: { enabled: true, strategy: 'mock' as const }, - fileStorage: { enabled: false }, - }, - }; - - const result = DevPluginConfigSchema.safeParse(config); - expect(result.success).toBe(true); - if (result.success) { - expect(result.data.services?.auth.enabled).toBe(true); - expect(result.data.services?.auth.strategy).toBe('mock'); - expect(result.data.services?.fileStorage.enabled).toBe(false); - } - }); - - it('should accept full configuration', () => { - const config = { - preset: 'full' as const, - services: { - auth: { enabled: true, strategy: 'mock' as const }, - eventBus: { enabled: true, strategy: 'memory' as const }, - fileStorage: { enabled: false }, - }, - fixtures: { - enabled: true, - paths: ['./fixtures/*.json'], - resetBeforeLoad: true, - }, - tools: { - hotReload: true, - dbExplorer: true, - apiDocs: true, - }, - port: 5500, - open: true, - seedAdminUser: true, - simulatedLatency: 200, - }; - - const result = DevPluginConfigSchema.safeParse(config); - expect(result.success).toBe(true); - if (result.success) { - expect(result.data.port).toBe(5500); - expect(result.data.open).toBe(true); - expect(result.data.simulatedLatency).toBe(200); - expect(result.data.fixtures?.paths).toEqual(['./fixtures/*.json']); - } - }); - - it('should reject invalid port', () => { - expect( - DevPluginConfigSchema.safeParse({ port: 0 }).success, - ).toBe(false); - expect( - DevPluginConfigSchema.safeParse({ port: 99999 }).success, - ).toBe(false); - }); - - it('should reject negative simulated latency', () => { - expect( - DevPluginConfigSchema.safeParse({ simulatedLatency: -10 }).success, - ).toBe(false); - }); - - it('should reject empty string as service key', () => { - const result = DevPluginConfigSchema.safeParse({ - services: { '': { enabled: true } }, - }); - expect(result.success).toBe(false); - }); - }); -}); diff --git a/packages/spec/src/kernel/dev-plugin.zod.ts b/packages/spec/src/kernel/dev-plugin.zod.ts deleted file mode 100644 index 196f99c499..0000000000 --- a/packages/spec/src/kernel/dev-plugin.zod.ts +++ /dev/null @@ -1,250 +0,0 @@ -// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license. - -import { z } from 'zod'; - -/** - * # Dev Mode Plugin Protocol - * - * Declared configuration vocabulary for a development-mode plugin: per-service - * dev strategies, fixture loading, developer tooling, presets. - * - * ⚠️ **Declared, not implemented — pending enforce-or-remove (#4149).** - * The shipped `@objectstack/plugin-dev` consumes its own `DevPluginOptions` - * interface, NOT this schema, and none of the surfaces below (presets, - * fixtures, dev-tools dashboard, per-service strategies, simulated latency) - * exist in it. Since ADR-0115 it is an **assembly** plugin: it wires the real - * platform plugins for local development and registers no stub or simulated - * services — an unfilled slot answers exactly as it does in production. The - * `strategy: 'stub'` value in particular describes a behaviour the platform - * has retired. Do not build against this file until #4149 resolves it. - * - * Original design goals, kept for the #4149 evaluation: - * - Zero-config by default: `devPlugins: ['@objectstack/plugin-dev']` - * - Every service can be overridden or disabled individually - * - Preset profiles (minimal / standard / full) for common scenarios - */ - -// ============================================================================ -// Dev Service Override -// ============================================================================ - -/** - * Dev Service Override Schema - * - * Allows fine-grained control over a single service in development mode. - * Each override targets a service by name and specifies whether it should - * be enabled, which implementation strategy to use, and optional config. - */ -import { lazySchema } from '../shared/lazy-schema'; -export const DevServiceOverrideSchema = lazySchema(() => z.object({ - /** Service identifier (e.g. 'auth', 'eventBus', 'fileStorage') */ - service: z.string().min(1).describe('Target service identifier'), - - /** Whether this service is enabled in dev mode */ - enabled: z.boolean().default(true).describe('Enable or disable this service'), - - /** - * Implementation strategy for the service in dev mode. - * - mock: Use a mock/stub that records calls (for assertions) - * - memory: Use a real but in-memory implementation (e.g. SQLite, Map) - * - stub: Use a static/no-op implementation - * - passthrough: Use the real production implementation (for integration testing) - */ - strategy: z.enum(['mock', 'memory', 'stub', 'passthrough']).default('memory') - .describe('Implementation strategy for development'), - - /** Optional per-service configuration (strategy-specific) */ - config: z.record(z.string(), z.unknown()).optional() - .describe('Strategy-specific configuration for this service override'), -})); - -export type DevServiceOverride = z.infer; - -// ============================================================================ -// Dev Fixture Configuration -// ============================================================================ - -/** - * Dev Fixture Config Schema - * - * Configures automatic seed/fixture data loading in development mode. - * Fixtures provide a reproducible dataset for local development and demos. - */ -export const DevFixtureConfigSchema = lazySchema(() => z.object({ - /** Whether to load fixtures on startup */ - enabled: z.boolean().default(true).describe('Load fixture data on startup'), - - /** - * Glob patterns pointing to fixture files - * (e.g. `["./fixtures/*.json", "./test/data/*.yml"]`) - */ - paths: z.array(z.string()).optional() - .describe('Glob patterns for fixture files'), - - /** Whether to reset data before loading fixtures */ - resetBeforeLoad: z.boolean().default(true) - .describe('Clear existing data before loading fixtures'), - - /** - * Environment tag filter – only load fixtures tagged for these environments. - * When omitted, all fixtures are loaded. - */ - envFilter: z.array(z.string()).optional() - .describe('Only load fixtures matching these environment tags'), -})); - -export type DevFixtureConfig = z.infer; - -// ============================================================================ -// Dev Tools Configuration -// ============================================================================ - -/** - * Dev Tools Config Schema - * - * Optional developer tooling that can be enabled alongside the dev plugin. - */ -export const DevToolsConfigSchema = lazySchema(() => z.object({ - /** Enable hot-module replacement / live reload */ - hotReload: z.boolean().default(true).describe('Enable HMR / live-reload'), - - /** Enable request inspector UI for debugging HTTP traffic */ - requestInspector: z.boolean().default(false).describe('Enable request inspector'), - - /** Enable an in-browser database explorer */ - dbExplorer: z.boolean().default(false).describe('Enable database explorer UI'), - - /** Enable verbose logging across all services */ - verboseLogging: z.boolean().default(true).describe('Enable verbose logging'), - - /** Enable OpenAPI / Swagger documentation endpoint */ - apiDocs: z.boolean().default(true).describe('Serve OpenAPI docs at /_dev/docs'), - - /** Enable a mail catcher for outbound email (like MailHog) */ - mailCatcher: z.boolean().default(false).describe('Capture outbound emails in dev'), -})); - -export type DevToolsConfig = z.infer; - -// ============================================================================ -// Dev Plugin Preset -// ============================================================================ - -/** - * Dev Plugin Preset - * - * Predefined configuration profiles for common development scenarios. - * - minimal: Only core data services (fast startup, low memory) - * - standard: Core + API + auth + events (typical full-stack dev) - * - full: Every service enabled, including background jobs and AI agents - */ -export const DevPluginPreset = z.enum([ - 'minimal', - 'standard', - 'full', -]).describe('Predefined dev configuration profile'); - -export type DevPluginPreset = z.infer; - -// ============================================================================ -// Dev Plugin Configuration -// ============================================================================ - -/** - * Dev Plugin Config Schema - * - * Top-level configuration for the development-mode plugin. - * This is the shape of the configuration payload that - * `@objectstack/plugin-dev` (or equivalent) understands. - * - * The outer wiring (e.g. how a stack declares `devPlugins`) is defined - * by the stack/manifest schemas; this type only describes the plugin's - * own config object. - * - * @example Minimal usage (zero-config) - * ```ts - * const devConfig: DevPluginConfig = {}; - * ``` - * - * @example With preset - * ```ts - * const devConfig: DevPluginConfig = { - * preset: 'full', - * }; - * ``` - * - * @example Fine-grained overrides - * ```ts - * const devConfig: DevPluginConfig = { - * preset: 'standard', - * services: { - * auth: { enabled: true, strategy: 'mock' }, - * fileStorage: { enabled: false }, - * }, - * fixtures: { paths: ['./fixtures/*.json'] }, - * tools: { dbExplorer: true }, - * }; - * ``` - */ -export const DevPluginConfigSchema = lazySchema(() => z.object({ - /** - * Configuration preset. - * When provided, services and tools are pre-configured for the selected - * profile. Individual `services` and `tools` settings override the preset. - * @default 'standard' - */ - preset: DevPluginPreset.default('standard') - .describe('Base configuration preset'), - - /** - * Per-service overrides. - * Keys are service names; values configure the dev strategy. - * Only services explicitly listed here override the preset defaults. - */ - services: z.record( - z.string().min(1), - DevServiceOverrideSchema.omit({ service: true }), - ).optional().describe('Per-service dev overrides keyed by service name'), - - /** Fixture / seed data configuration */ - fixtures: DevFixtureConfigSchema.optional() - .describe('Fixture data loading configuration'), - - /** Developer tooling configuration */ - tools: DevToolsConfigSchema.optional() - .describe('Developer tooling settings'), - - /** - * Port for the dev-tools UI dashboard. - * Serves a lightweight web dashboard for inspecting services, events, - * and request logs during development. - * @default 4400 - */ - port: z.number().int().min(1).max(65535).default(4400) - .describe('Port for the dev-tools dashboard'), - - /** - * Auto-open the dev-tools dashboard in the default browser on startup. - */ - open: z.boolean().default(false) - .describe('Auto-open dev dashboard in browser'), - - /** - * Seed a default admin user for development. - * When enabled, the dev plugin creates a pre-authenticated admin user - * so that developers can bypass login flows. - */ - seedAdminUser: z.boolean().default(true) - .describe('Create a default admin user for development'), - - /** - * Simulated latency (ms) to add to service calls. - * Helps developers build UIs that handle loading states correctly. - * Set to 0 to disable. - */ - simulatedLatency: z.number().int().min(0).default(0) - .describe('Artificial latency (ms) added to service calls'), -})); - -export type DevPluginConfig = z.infer; -export type DevPluginConfigInput = z.input; diff --git a/packages/spec/src/kernel/index.ts b/packages/spec/src/kernel/index.ts index 9eb70a630b..b5bc8eb401 100644 --- a/packages/spec/src/kernel/index.ts +++ b/packages/spec/src/kernel/index.ts @@ -4,7 +4,15 @@ export * from './cli-extension.zod'; export * from './cluster.zod'; export * from './context.zod'; export * from './dependency-resolution.zod'; -export * from './dev-plugin.zod'; +// dev-plugin.zod (DevPluginConfigSchema / DevServiceOverrideSchema / +// DevFixtureConfigSchema / DevToolsConfigSchema / DevPluginPreset) was REMOVED +// per ADR-0049 enforce-or-remove (#4149): the whole family had zero consumers — +// @objectstack/plugin-dev reads its own DevPluginOptions and never imported it, +// no load path parsed it (`stack.devPlugins` takes ManifestSchema | string, not +// this config), and none of the declared surfaces (presets, fixtures, dev-tools +// dashboard, per-service strategies, simulated latency) were ever implemented. +// Its `strategy: 'stub'` vocabulary described the dev-stub design ADR-0115 +// retired. The real dev assembly contract is plugin-dev's DevPluginOptions. export * from './events.zod'; // feature.zod (FeatureFlagSchema / FeatureStrategy / FeatureFlag factory) was // REMOVED per ADR-0056 D8: zero runtime consumers, and its only protocol home —