@sonicjs-cms/core 3.0.0-beta.7 → 3.0.0-beta.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{filter-bar.template-DlVYMk-T.d.cts → admin-layout-catalyst.template-DrwDUfsE.d.cts} +25 -1
- package/dist/{filter-bar.template-DlVYMk-T.d.ts → admin-layout-catalyst.template-DrwDUfsE.d.ts} +25 -1
- package/dist/{chunk-GO2NICMM.cjs → chunk-2FONGKMG.cjs} +237 -237
- package/dist/{chunk-GO2NICMM.cjs.map → chunk-2FONGKMG.cjs.map} +1 -1
- package/dist/{chunk-GVHST4D7.js → chunk-3WSZNGIK.js} +50 -4
- package/dist/chunk-3WSZNGIK.js.map +1 -0
- package/dist/{chunk-BDDABDAB.cjs → chunk-4BTBSXMR.cjs} +2 -239
- package/dist/chunk-4BTBSXMR.cjs.map +1 -0
- package/dist/{chunk-7RY3YKI7.cjs → chunk-7AMFLNK6.cjs} +3 -3
- package/dist/{chunk-7RY3YKI7.cjs.map → chunk-7AMFLNK6.cjs.map} +1 -1
- package/dist/{chunk-WACUJVXY.cjs → chunk-C5RJWUZX.cjs} +57 -11
- package/dist/chunk-C5RJWUZX.cjs.map +1 -0
- package/dist/{chunk-2JOMHEKO.js → chunk-E2LLKPFQ.js} +3 -3
- package/dist/{chunk-2JOMHEKO.js.map → chunk-E2LLKPFQ.js.map} +1 -1
- package/dist/{chunk-5QVYEAVV.cjs → chunk-ITXAUOBC.cjs} +10 -10
- package/dist/{chunk-5QVYEAVV.cjs.map → chunk-ITXAUOBC.cjs.map} +1 -1
- package/dist/{chunk-2RJDEVB3.cjs → chunk-J46JBAZX.cjs} +2 -2
- package/dist/{chunk-2RJDEVB3.cjs.map → chunk-J46JBAZX.cjs.map} +1 -1
- package/dist/{chunk-XCPIXYOP.js → chunk-NSE36XKR.js} +4 -4
- package/dist/{chunk-XCPIXYOP.js.map → chunk-NSE36XKR.js.map} +1 -1
- package/dist/{chunk-WJTMTIYR.js → chunk-PYVFXCSD.js} +255 -3
- package/dist/chunk-PYVFXCSD.js.map +1 -0
- package/dist/{chunk-OECDF2RF.cjs → chunk-R4ILO3W6.cjs} +258 -2
- package/dist/chunk-R4ILO3W6.cjs.map +1 -0
- package/dist/{chunk-ZEZ245PW.js → chunk-RQ6N3FTV.js} +3 -236
- package/dist/chunk-RQ6N3FTV.js.map +1 -0
- package/dist/{chunk-ISIRU7AK.cjs → chunk-RU5TA4J7.cjs} +4 -4
- package/dist/{chunk-ISIRU7AK.cjs.map → chunk-RU5TA4J7.cjs.map} +1 -1
- package/dist/{chunk-BYCBFBUG.js → chunk-SBVOWPJ5.js} +2 -2
- package/dist/{chunk-BYCBFBUG.js.map → chunk-SBVOWPJ5.js.map} +1 -1
- package/dist/{chunk-LH7RKNUW.js → chunk-VHYQ67LW.js} +10 -10
- package/dist/{chunk-LH7RKNUW.js.map → chunk-VHYQ67LW.js.map} +1 -1
- package/dist/{chunk-POGSN5WI.js → chunk-ZHPOJZRR.js} +3 -3
- package/dist/{chunk-POGSN5WI.js.map → chunk-ZHPOJZRR.js.map} +1 -1
- package/dist/index.cjs +264 -260
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +17 -16
- package/dist/index.js.map +1 -1
- package/dist/middleware.cjs +33 -32
- package/dist/middleware.js +4 -3
- package/dist/migrations-6MRNHE2W.cjs +13 -0
- package/dist/{migrations-TBEFSZIV.cjs.map → migrations-6MRNHE2W.cjs.map} +1 -1
- package/dist/migrations-SBX554MG.js +4 -0
- package/dist/{migrations-IEWABLIP.js.map → migrations-SBX554MG.js.map} +1 -1
- package/dist/plugins.cjs +40 -40
- package/dist/plugins.js +3 -3
- package/dist/routes.cjs +28 -28
- package/dist/routes.js +8 -8
- package/dist/services.cjs +42 -42
- package/dist/services.d.cts +14 -1
- package/dist/services.d.ts +14 -1
- package/dist/services.js +3 -3
- package/dist/{telemetry-B9vIV4wh.d.cts → telemetry-Cku1ax74.d.cts} +1 -1
- package/dist/{telemetry-B9vIV4wh.d.ts → telemetry-Cku1ax74.d.ts} +1 -1
- package/dist/templates.d.cts +2 -24
- package/dist/templates.d.ts +2 -24
- package/dist/types.d.cts +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/utils.cjs +8 -8
- package/dist/utils.d.cts +1 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-BDDABDAB.cjs.map +0 -1
- package/dist/chunk-GVHST4D7.js.map +0 -1
- package/dist/chunk-OECDF2RF.cjs.map +0 -1
- package/dist/chunk-WACUJVXY.cjs.map +0 -1
- package/dist/chunk-WJTMTIYR.js.map +0 -1
- package/dist/chunk-ZEZ245PW.js.map +0 -1
- package/dist/migrations-IEWABLIP.js +0 -4
- package/dist/migrations-TBEFSZIV.cjs +0 -13
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/services/document-type-registry.ts","../src/services/document-types-seed.ts","../src/middleware/bootstrap.ts","../src/middleware/auth.ts","../src/middleware/metrics.ts","../src/middleware/csrf.ts","../src/middleware/rate-limit.ts","../src/middleware/security-headers.ts","../src/middleware/plugin-middleware.ts","../src/middleware/index.ts"],"names":["ensureScalarSchema","z","getCollectionRegistry","hasHookSystem","getHookSystem","MigrationService","loadCollectionConfigs","RbacService","PluginBootstrapService","getTelemetryService","c","sign","verify","getCookie","result","setCookie","metricsTracker","JWT_SECRET_FALLBACK"],"mappings":"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","file":"chunk-C5RJWUZX.cjs","sourcesContent":["import { D1Database } from '@cloudflare/workers-types'\nimport { nanoid } from 'nanoid'\nimport type {\n PluginDocumentType,\n DocumentType,\n DocumentTypeRow,\n} from '../schemas/document'\nimport { ensureScalarSchema } from './document-scalar-schema'\n\nfunction rowToDocumentType(row: DocumentTypeRow): DocumentType {\n return {\n id: row.id,\n name: row.name,\n displayName: row.display_name,\n description: row.description,\n schema: JSON.parse(row.schema),\n queryableFields: JSON.parse(row.queryable_fields),\n settings: JSON.parse(row.settings),\n pluginId: row.plugin_id,\n source: row.source,\n schemaVersion: row.schema_version,\n isSystem: row.is_system === 1,\n isActive: row.is_active === 1,\n isAuth: row.is_auth === 1,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n }\n}\n\nexport class DocumentTypeRegistry {\n private cache = new Map<string, DocumentType>()\n\n constructor(private db: D1Database) {}\n\n // Register or update a document type. Idempotent: bumps schema_version only when schema changes.\n async register(def: PluginDocumentType & { pluginId?: string; source?: 'code' | 'plugin' | 'system' }): Promise<DocumentType> {\n const now = Math.floor(Date.now() / 1000)\n const existing = await this.findById(def.id)\n\n // A z.ZodSchema is not JSON-serializable, so persist a stable serializable shape derived from\n // the type's queryable fields + settings. This is what schemaChanged compares, so schema_version\n // bumps whenever a type's filterable shape changes (and is stamped onto documents.type_version).\n const schemaJson = JSON.stringify({ queryableFields: def.queryableFields ?? [], settings: def.settings ?? {} })\n const queryableJson = JSON.stringify(def.queryableFields ?? [])\n const settingsJson = JSON.stringify(def.settings ?? {})\n\n if (existing) {\n const schemaChanged = schemaJson !== JSON.stringify(existing.schema)\n const newVersion = schemaChanged ? existing.schemaVersion + 1 : existing.schemaVersion\n\n await this.db\n .prepare(\n `UPDATE document_types SET\n display_name = ?,\n description = ?,\n schema = ?,\n queryable_fields = ?,\n settings = ?,\n plugin_id = ?,\n schema_version = ?,\n is_active = 1,\n is_auth = ?,\n updated_at = ?\n WHERE id = ?`,\n )\n .bind(\n def.displayName,\n def.description ?? null,\n schemaJson,\n queryableJson,\n settingsJson,\n def.pluginId ?? null,\n newVersion,\n def.isAuth ? 1 : 0,\n now,\n def.id,\n )\n .run()\n\n // Auto-DDL: ensure VIRTUAL generated columns + indexes for scalar fields.\n await ensureScalarSchema(this.db, def.id, def.queryableFields ?? [])\n\n const updated = await this.findById(def.id)\n this.cache.set(def.id, updated!)\n return updated!\n }\n\n await this.db\n .prepare(\n `INSERT INTO document_types (id, name, display_name, description, schema, queryable_fields, settings, plugin_id, source, schema_version, is_system, is_active, is_auth, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 1, 0, 1, ?, ?, ?)`,\n )\n .bind(\n def.id,\n def.name ?? def.id,\n def.displayName,\n def.description ?? null,\n schemaJson,\n queryableJson,\n settingsJson,\n def.pluginId ?? null,\n def.source ?? 'code',\n def.isAuth ? 1 : 0,\n now,\n now,\n )\n .run()\n\n // Auto-DDL: ensure VIRTUAL generated columns + indexes for scalar fields.\n await ensureScalarSchema(this.db, def.id, def.queryableFields ?? [])\n\n const created = await this.findById(def.id)\n this.cache.set(def.id, created!)\n return created!\n }\n\n async findById(id: string): Promise<DocumentType | null> {\n if (this.cache.has(id)) return this.cache.get(id)!\n\n const row = await this.db\n .prepare('SELECT * FROM document_types WHERE id = ?')\n .bind(id)\n .first<DocumentTypeRow>()\n\n if (!row) return null\n const dt = rowToDocumentType(row)\n this.cache.set(id, dt)\n return dt\n }\n\n async findAll(activeOnly = true): Promise<DocumentType[]> {\n const sql = activeOnly\n ? 'SELECT * FROM document_types WHERE is_active = 1 ORDER BY name'\n : 'SELECT * FROM document_types ORDER BY name'\n\n const result = await this.db.prepare(sql).all<DocumentTypeRow>()\n return (result.results ?? []).map(rowToDocumentType)\n }\n\n async deactivate(id: string): Promise<void> {\n const now = Math.floor(Date.now() / 1000)\n await this.db\n .prepare('UPDATE document_types SET is_active = 0, updated_at = ? WHERE id = ?')\n .bind(now, id)\n .run()\n this.cache.delete(id)\n }\n\n clearCache(): void {\n this.cache.clear()\n }\n}\n","import { D1Database } from '@cloudflare/workers-types'\nimport { z } from 'zod'\nimport { DocumentTypeRegistry } from './document-type-registry'\nimport { getCollectionRegistry } from './collection-registry'\n\n// Passthrough schema: accepts any JSON object for POC types.\n// Individual fields are validated at the queryable-field level; the full\n// payload schema is a future enhancement (addDocumentType will accept Zod schemas).\nconst anyObject = z.record(z.string(), z.unknown())\n\n// Registers the POC document types idempotently during bootstrap.\n// These are the candidate types from the document model plan.\n// Each call is a no-op if the type already exists and the schema hasn't changed.\nexport async function bootstrapDocumentTypes(db: D1Database): Promise<void> {\n const registry = new DocumentTypeRegistry(db)\n\n // Site settings: internal singleton config — never surfaced in content admin.\n await registry.register({\n id: 'site_settings',\n name: 'site_settings',\n displayName: 'Site Settings',\n description: 'Global site configuration (internal; managed via admin settings UI)',\n source: 'system',\n schema: anyObject,\n settings: {\n internal: true,\n maxVersionsPerRoot: 1,\n baseGrants: { admin: ['read', 'create', 'update', 'delete', 'manage'] },\n },\n queryableFields: [],\n })\n\n // Blog post: the code-managed `blog_post` collection is backed by the document model.\n // The matching id (`blog_post` == collection name) is how content admin detects doc-backing.\n await registry.register({\n id: 'blog_post',\n name: 'blog_post',\n displayName: 'Blog Post',\n description: 'Blog post (document-backed; edited via the content collection UI)',\n source: 'system',\n schema: anyObject,\n settings: {\n baseGrants: { public: ['read'], admin: ['read', 'create', 'update', 'delete', 'publish', 'manage'], editor: ['read', 'create', 'update', 'publish'], viewer: ['read'] },\n maxVersionsPerRoot: 50,\n },\n queryableFields: [\n { name: 'difficulty', kind: 'scalar', type: 'text', column: 'q_blog_difficulty' },\n { name: 'author', kind: 'scalar', type: 'text', column: 'q_blog_author' },\n ],\n })\n\n // Plugin registry (document-backed plugin management)\n await registry.register({\n id: 'plugin',\n name: 'plugin',\n displayName: 'Plugin',\n description: 'System plugin record (managed by the plugin bootstrap service)',\n source: 'system',\n schema: anyObject,\n settings: {\n baseGrants: { admin: ['read', 'create', 'update', 'delete', 'publish', 'manage'] },\n maxVersionsPerRoot: 1,\n internal: true,\n },\n queryableFields: [\n { name: 'status', kind: 'scalar', type: 'text', column: 'q_plugin_status' },\n { name: 'category', kind: 'scalar', type: 'text', column: 'q_plugin_category' },\n { name: 'isCore', kind: 'scalar', type: 'integer', column: 'q_plugin_is_core' },\n ],\n })\n\n // Tenant registry (document-backed multi-tenancy; rows managed by the multi-tenant plugin).\n // Tenant records are platform metadata and live under the 'default' tenant themselves.\n // Zero rows until the multi-tenant plugin is activated and used.\n await registry.register({\n id: 'tenant',\n name: 'tenant',\n displayName: 'Tenant',\n description: 'Tenant record (managed by the multi-tenant plugin; slug = tenant id)',\n source: 'system',\n schema: anyObject,\n settings: {\n baseGrants: { admin: ['read', 'create', 'update', 'delete', 'manage'] },\n maxVersionsPerRoot: 1,\n internal: true,\n },\n queryableFields: [\n { name: 'status', kind: 'scalar', type: 'text', column: 'q_tenant_status' },\n { name: 'domain', kind: 'scalar', type: 'text', column: 'q_tenant_domain' },\n ],\n })\n\n // User profile (auth-owned). One document per user, addressed by slug = userId.\n // Replaces the auth_user_profiles table. Typed fields + custom fields live in `data`.\n await registry.register({\n id: 'user_profile',\n name: 'user_profile',\n displayName: 'User Profile',\n description: 'Per-user profile record (auth-owned; one document per user, slug = userId)',\n source: 'system',\n isAuth: true,\n schema: anyObject,\n settings: {\n // Hidden from the content admin surfaces; a single mutable record (no version history).\n internal: true,\n maxVersionsPerRoot: 1,\n pii: true,\n baseGrants: { admin: ['read', 'create', 'update', 'delete', 'manage'] },\n },\n queryableFields: [],\n })\n\n // Media asset (document-authoritative media library). One document per uploaded R2 object.\n // Internal: managed via the media library + media selector, not offered as a content model.\n // Registering here both satisfies the documents.type_id FK and creates the q_media_* columns\n // (DocumentTypeRegistry.register → ensureScalarSchema). Must stay in sync with MEDIA_QUERYABLE\n // in services/media-documents.ts.\n await registry.register({\n id: 'media_asset',\n name: 'media_asset',\n displayName: 'Media Asset',\n description: 'Uploaded media file metadata (managed via the media library; backs an R2 object)',\n source: 'system',\n schema: anyObject,\n settings: {\n internal: true,\n maxVersionsPerRoot: 5,\n baseGrants: {\n admin: ['read', 'create', 'update', 'delete', 'manage'],\n editor: ['read', 'create', 'update'],\n author: ['read', 'create'],\n viewer: ['read'],\n },\n },\n queryableFields: [\n { name: 'mimeType', kind: 'scalar', type: 'text', column: 'q_media_mime' },\n { name: 'folder', kind: 'scalar', type: 'text', column: 'q_media_folder' },\n { name: 'size', kind: 'scalar', type: 'integer', column: 'q_media_size' },\n { name: 'tags', kind: 'facet', type: 'text' },\n ],\n })\n\n // Plugin activity log (document-backed; replaces legacy plugin_activity_log table which was never migrated)\n await registry.register({\n id: 'plugin_activity',\n name: 'plugin_activity',\n displayName: 'Plugin Activity',\n description: 'Plugin lifecycle event log (installed/activated/deactivated/settings_updated/error)',\n source: 'system',\n schema: anyObject,\n settings: {\n internal: true,\n maxVersionsPerRoot: 1,\n baseGrants: { admin: ['read', 'create', 'manage'] },\n },\n queryableFields: [\n { name: 'pluginId', kind: 'scalar', type: 'text', column: 'q_plugin_activity_plugin_id' },\n { name: 'action', kind: 'scalar', type: 'text', column: 'q_plugin_activity_action' },\n ],\n })\n\n // Security audit event (document-backed; replaces legacy security_events table)\n await registry.register({\n id: 'security_event',\n name: 'security_event',\n displayName: 'Security Event',\n description: 'Security audit event (login attempts, lockouts, suspicious activity)',\n source: 'system',\n schema: anyObject,\n settings: {\n internal: true,\n maxVersionsPerRoot: 1,\n baseGrants: { admin: ['read', 'create', 'manage'] },\n },\n queryableFields: [\n { name: 'eventType', kind: 'scalar', type: 'text', column: 'q_sa_event_type' },\n { name: 'severity', kind: 'scalar', type: 'text', column: 'q_sa_severity' },\n { name: 'userId', kind: 'scalar', type: 'text', column: 'q_sa_user_id' },\n { name: 'email', kind: 'scalar', type: 'text', column: 'q_sa_email' },\n { name: 'ipAddress', kind: 'scalar', type: 'text', column: 'q_sa_ip_address' },\n { name: 'blocked', kind: 'scalar', type: 'integer', column: 'q_sa_blocked' },\n ],\n })\n\n // Analytics event (document-backed; replaces legacy analytics_events table)\n await registry.register({\n id: 'analytics_event',\n name: 'analytics_event',\n displayName: 'Analytics Event',\n description: 'Tracked analytics event (page view, user action, custom event)',\n source: 'system',\n schema: anyObject,\n settings: {\n internal: true,\n maxVersionsPerRoot: 1,\n baseGrants: { admin: ['read', 'create', 'manage'] },\n },\n queryableFields: [\n { name: 'event', kind: 'scalar', type: 'text', column: 'q_evt_event' },\n { name: 'category', kind: 'scalar', type: 'text', column: 'q_evt_category' },\n { name: 'userId', kind: 'scalar', type: 'text', column: 'q_evt_user_id' },\n { name: 'sessionId', kind: 'scalar', type: 'text', column: 'q_evt_session_id' },\n { name: 'path', kind: 'scalar', type: 'text', column: 'q_evt_path' },\n ],\n })\n\n // Media asset: every file upload creates a media_asset document (document-authoritative).\n // File bytes stay in R2; this document holds intrinsic metadata (dimensions, mime, r2Key…).\n await registry.register({\n id: 'media_asset',\n name: 'media_asset',\n displayName: 'Media Asset',\n description: 'Media file metadata (R2 object key + intrinsic properties; URL derived at read time)',\n source: 'system',\n schema: anyObject,\n settings: {\n baseGrants: { public: ['read'], admin: ['read', 'create', 'update', 'delete', 'publish', 'manage'], editor: ['read', 'create', 'update'] },\n maxVersionsPerRoot: 5,\n },\n queryableFields: [\n { name: 'mimeType', kind: 'scalar', type: 'text', column: 'q_media_mime' },\n { name: 'folder', kind: 'scalar', type: 'text', column: 'q_media_folder' },\n { name: 'size', kind: 'scalar', type: 'integer', column: 'q_media_size' },\n { name: 'tags', kind: 'facet', type: 'text' },\n ],\n })\n\n // ── RBAC (auth-owned). 3 document types replace 4 relational tables: ──────────\n // rbac_role slug = roleId, data.grants[] embedded (replaces role_grants)\n // rbac_verb slug = verbId\n // rbac_user_roles slug = userId, data.roleIds[] embedded (replaces user_roles)\n // All internal + is_auth so they never surface in content. See services/rbac.ts.\n for (const [id, displayName, description] of [\n ['rbac_role', 'RBAC Role', 'Role record with embedded grants (auth-owned)'],\n ['rbac_verb', 'RBAC Verb', 'Permission verb (auth-owned)'],\n ['rbac_user_roles', 'RBAC User Roles', \"Per-user role assignments (auth-owned; slug = userId)\"],\n ] as const) {\n await registry.register({\n id,\n name: id,\n displayName,\n description,\n source: 'system',\n isAuth: true,\n schema: anyObject,\n settings: {\n internal: true,\n maxVersionsPerRoot: 1,\n baseGrants: { admin: ['read', 'create', 'update', 'delete', 'manage'] },\n },\n queryableFields: [],\n })\n }\n}\n\n/**\n * Register a document type for every code-defined collection in the registry.\n *\n * Code-defined collections become document-backed automatically so that all\n * content writes against them flow through the documents repository. The\n * document type's id == collection name, matching how content admin detects\n * doc-backing.\n */\nexport async function autoRegisterCollectionDocumentTypes(db: D1Database): Promise<string[]> {\n const registry = new DocumentTypeRegistry(db)\n const collections = getCollectionRegistry().listActive()\n const registered: string[] = []\n\n for (const collection of collections) {\n // Skip system/internal collections that already have explicit document type\n // definitions in bootstrapDocumentTypes (e.g. blog_post is seeded above\n // with its own queryable fields). The explicit registration wins.\n if (collection.internal) continue\n if (collection.name === 'blog_post') continue\n\n try {\n await registry.register({\n id: collection.name,\n name: collection.name,\n displayName: collection.displayName,\n description: collection.description,\n source: 'system',\n schema: anyObject,\n settings: {\n baseGrants: {\n public: ['read'],\n admin: ['read', 'create', 'update', 'delete', 'publish', 'manage'],\n editor: ['read', 'create', 'update', 'publish'],\n viewer: ['read'],\n },\n maxVersionsPerRoot: 50,\n ...(collection.versioning ? { versioning: true } : {}),\n },\n queryableFields: [],\n })\n registered.push(collection.name)\n } catch (error) {\n console.error(`[document-types-seed] Failed to register collection \"${collection.name}\":`, error)\n }\n }\n\n return registered\n}\n","import { Context, Next } from \"hono\";\nimport { loadCollectionConfigs } from \"../services/collection-loader\";\nimport { getCollectionRegistry } from \"../services/collection-registry\";\nimport { MigrationService } from \"../services/migrations\";\nimport { PluginBootstrapService } from \"../services/plugin-bootstrap\";\nimport { bootstrapDocumentTypes, autoRegisterCollectionDocumentTypes } from \"../services/document-types-seed\";\nimport { getHookSystem, hasHookSystem } from \"../plugins/hooks/hook-system-singleton\";\nimport { getTelemetryService } from \"../services/telemetry-service\";\nimport type { SonicJSConfig } from \"../app\";\n\ntype Bindings = {\n DB: D1Database;\n KV: KVNamespace;\n JWT_SECRET?: string;\n CORS_ORIGINS?: string;\n ENVIRONMENT?: string;\n};\n\n// Track if bootstrap has been run in this worker instance\nlet bootstrapComplete = false;\n\n/**\n * Verify security-critical environment configuration at startup.\n * Logs warnings in development, throws in production to prevent\n * insecure deployments from silently running.\n */\nexport function verifySecurityConfig(env: Bindings): void {\n const warnings: string[] = [];\n\n // Check JWT secret\n if (!env.JWT_SECRET) {\n warnings.push(\n \"JWT_SECRET is not set — using hardcoded fallback. Set via `wrangler secret put JWT_SECRET`\"\n );\n } else if (env.JWT_SECRET.includes(\"change-in-production\")) {\n warnings.push(\n \"JWT_SECRET contains the default value — tokens are forgeable. Generate a strong random secret\"\n );\n }\n\n // Check CORS origins\n if (!env.CORS_ORIGINS) {\n warnings.push(\n \"CORS_ORIGINS is not set — all cross-origin API requests will be rejected\"\n );\n }\n\n // Check environment designation\n if (!env.ENVIRONMENT) {\n warnings.push(\n \"ENVIRONMENT is not set — HSTS header will not be applied. Set to \\\"production\\\" or \\\"development\\\"\"\n );\n }\n\n if (warnings.length === 0) {\n return;\n }\n\n const isProduction = env.ENVIRONMENT === \"production\";\n\n for (const warning of warnings) {\n console.warn(`[SonicJS Security] ${warning}`);\n }\n\n if (isProduction) {\n // In production, a missing or default JWT_SECRET is a hard failure —\n // every token issued would be forgeable by anyone reading the source code.\n const hasCritical =\n !env.JWT_SECRET || env.JWT_SECRET.includes(\"change-in-production\");\n if (hasCritical) {\n throw new Error(\n \"[SonicJS Security] CRITICAL: Production deployment is missing a secure JWT_SECRET. \" +\n \"Set it via `wrangler secret put JWT_SECRET` before deploying.\"\n );\n }\n }\n}\n\n/**\n * Bootstrap middleware that ensures system initialization\n * Runs once per worker instance\n */\nexport function bootstrapMiddleware(config: SonicJSConfig = {}) {\n return async (c: Context<{ Bindings: Bindings; Variables: { hookSystem?: unknown } }>, next: Next) => {\n // Attach the hook system to the request BEFORE any heavy bootstrap work\n // runs, so anything that emits a hook during bootstrap (cron cold starts,\n // RBAC seed, document-type registration, plugin onBoot via createPluginWirer)\n // sees a live bus instead of a no-op. The process singleton was published at\n // app-factory time (app.ts); we only forward it onto the request here.\n if (hasHookSystem()) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Variables typed loosely here; concrete type lives in app.ts\n (c as any).set(\"hookSystem\", getHookSystem());\n }\n\n // Skip if already bootstrapped in this worker instance\n if (bootstrapComplete) {\n return next();\n }\n\n // Skip bootstrap for static assets and health checks\n const path = c.req.path;\n if (\n path.startsWith(\"/images/\") ||\n path.startsWith(\"/assets/\") ||\n path === \"/health\" ||\n path.endsWith(\".js\") ||\n path.endsWith(\".css\") ||\n path.endsWith(\".png\") ||\n path.endsWith(\".jpg\") ||\n path.endsWith(\".ico\")\n ) {\n return next();\n }\n\n try {\n console.log(\"[Bootstrap] Starting system initialization...\");\n\n // 1. Run idempotent schema compatibility repairs. Migration state and\n // migration execution are owned by Cloudflare D1/Wrangler.\n console.log(\"[Bootstrap] Checking schema compatibility...\");\n const migrationService = new MigrationService(c.env.DB);\n await migrationService.ensureSchemaCompatibility();\n\n // 1a. Wire the CACHE_KV binding into the cache plugin's singleton store so\n // cache writes survive isolate evictions. Memory-only cache is per-isolate\n // and ephemeral, which makes /admin/cache appear \"empty\" after restarts.\n try {\n const kv = (c.env as any).CACHE_KV;\n if (kv) {\n const { setGlobalKVNamespace } = await import(\n \"../plugins/cache/services/cache\"\n );\n setGlobalKVNamespace(kv);\n }\n } catch (error) {\n console.error(\"[Bootstrap] Error wiring CACHE_KV namespace:\", error);\n }\n\n // 2. Populate the in-memory collection registry from code-defined configs.\n // This is the source of truth going forward; the DB `collections` table is\n // being decommissioned (see docs/ai/plans/drop-db-collections-plan.md).\n console.log(\"[Bootstrap] Populating collection registry...\");\n try {\n const configs = await loadCollectionConfigs();\n getCollectionRegistry().register(configs);\n console.log(`[Bootstrap] Registry populated with ${configs.length} collection(s)`);\n } catch (error) {\n console.error(\"[Bootstrap] Error populating collection registry:\", error);\n }\n\n // 3. Register document types (idempotent)\n console.log(\"[Bootstrap] Registering document types...\");\n try {\n await bootstrapDocumentTypes(c.env.DB);\n } catch (error) {\n console.error(\"[Bootstrap] Error registering document types:\", error);\n }\n\n // 2c. Repair legacy users that have password_hash in auth_user but no\n // auth_account credential row (registered before Better Auth migration).\n try {\n await repairMissingCredentialAccounts(c.env.DB)\n } catch (error) {\n console.error('[Bootstrap] Error repairing credential accounts:', error)\n }\n\n // 3a. Seed system RBAC roles/verbs/grants as documents (idempotent).\n try {\n const { RbacService } = await import(\"../services/rbac\");\n await new RbacService(c.env.DB, (c.env as any).CACHE_KV).ensureSystemRbacSeed();\n } catch (error) {\n console.error(\"[Bootstrap] Error seeding RBAC documents:\", error);\n }\n\n // 3b. Make every content collection document-backed (so all new content goes to `documents`).\n try {\n const auto = await autoRegisterCollectionDocumentTypes(c.env.DB);\n if (auto.length) console.log(`[Bootstrap] Document-backed collections registered: ${auto.join(\", \")}`);\n } catch (error) {\n console.error(\"[Bootstrap] Error auto-registering collection document types:\", error);\n }\n\n // 4. Bootstrap core plugins (unless disableAll is set)\n if (!config.plugins?.disableAll) {\n console.log(\"[Bootstrap] Bootstrapping core plugins...\");\n const bootstrapService = new PluginBootstrapService(c.env.DB);\n\n // Check if bootstrap is needed\n const needsBootstrap = await bootstrapService.isBootstrapNeeded();\n if (needsBootstrap) {\n await bootstrapService.bootstrapCorePlugins();\n }\n } else {\n console.log(\"[Bootstrap] Plugin bootstrap skipped (disableAll is true)\");\n }\n\n // Mark bootstrap as complete for this worker instance\n bootstrapComplete = true;\n console.log(\"[Bootstrap] System initialization completed\");\n\n // Fire project snapshot telemetry (fire-and-forget, never blocks boot)\n try {\n const registry = getCollectionRegistry();\n const collections = registry.listActive();\n\n // Count docs per collection type from D1\n const countResult = await c.env.DB.prepare(\n `SELECT type_id, COUNT(*) AS cnt FROM documents\n WHERE is_current_draft = 1 AND deleted_at IS NULL GROUP BY type_id`\n ).all<{ type_id: string; cnt: number }>();\n const countMap: Record<string, number> = {};\n let docTotal = 0;\n for (const row of (countResult.results ?? [])) {\n countMap[row.type_id] = row.cnt;\n docTotal += row.cnt;\n }\n\n // Field type histogram across all collection schemas\n const fieldTypeHistogram: Record<string, number> = {};\n for (const col of collections) {\n const props = (col.schema as any)?.properties ?? {};\n for (const field of Object.values(props) as any[]) {\n const ft: string = field?.type ?? 'unknown';\n fieldTypeHistogram[ft] = (fieldTypeHistogram[ft] ?? 0) + 1;\n }\n }\n\n // Plugin names from config\n const activePlugins = (config.plugins?.register ?? []).map((p: any) => p.name ?? 'unknown');\n\n // Stable installation ID via KV (generated once, persisted)\n let installationId = 'unknown';\n try {\n const kv = c.env.KV as KVNamespace | undefined;\n if (kv) {\n installationId = (await kv.get('_sonicjs_installation_id')) ?? '';\n if (!installationId) {\n installationId = crypto.randomUUID();\n await kv.put('_sonicjs_installation_id', installationId);\n }\n }\n } catch { /* KV not available */ }\n\n const telemetry = getTelemetryService();\n await telemetry.trackProjectSnapshot({\n installation_id: installationId,\n collection_names: collections.map(c => c.name),\n collection_counts: countMap,\n active_plugins: activePlugins,\n field_type_histogram: fieldTypeHistogram,\n doc_total: docTotal,\n sonicjs_version: (c.env as any).SONICJS_VERSION ?? 'unknown',\n });\n } catch { /* silent — telemetry must never break boot */ }\n } catch (error) {\n console.error(\"[Bootstrap] Error during system initialization:\", error);\n // Don't prevent the app from starting, but log the error\n }\n\n // 4. Verify security configuration (outside try/catch so critical\n // errors in production propagate and prevent insecure deployments)\n verifySecurityConfig(c.env as Bindings);\n\n return next();\n };\n}\n\n/**\n * Reset bootstrap flag (useful for testing)\n */\nexport function resetBootstrap() {\n bootstrapComplete = false;\n}\n\n/**\n * Find auth_user rows that have a password_hash but no auth_account credential\n * row (created before Better Auth migration) and repair them. Idempotent —\n * INSERT OR IGNORE means re-runs are safe.\n */\nasync function repairMissingCredentialAccounts(db: D1Database): Promise<void> {\n const { results } = await db.prepare(`\n SELECT u.id, u.password_hash\n FROM auth_user u\n WHERE u.password_hash IS NOT NULL AND u.password_hash != ''\n AND NOT EXISTS (\n SELECT 1 FROM auth_account a\n WHERE a.user_id = u.id AND a.provider_id = 'credential'\n )\n `).all()\n\n if (!results.length) return\n\n console.log(`[Bootstrap] Repairing ${results.length} user(s) missing credential auth_account rows`)\n const nowSec = Math.floor(Date.now() / 1000)\n for (const user of results as Array<{ id: string; password_hash: string }>) {\n await db.prepare(`\n INSERT OR IGNORE INTO auth_account (id, user_id, account_id, provider_id, password, created_at, updated_at)\n VALUES (?, ?, ?, 'credential', ?, ?, ?)\n `).bind(`cred-${user.id}`, user.id, user.id, user.password_hash, nowSec, nowSec).run()\n }\n console.log(`[Bootstrap] Credential account repair complete (${results.length} repaired)`)\n}\n","import { sign, verify } from 'hono/jwt'\nimport { Context, Next } from 'hono'\nimport { getCookie, setCookie } from 'hono/cookie'\nimport { RbacService } from '../services/rbac'\n\ntype JWTPayload = {\n userId: string\n email: string\n role: string\n exp: number\n iat: number\n}\n\n// Fallback JWT secret for local development only (no wrangler secret set)\nconst JWT_SECRET_FALLBACK = 'your-super-secret-jwt-key-change-in-production'\n\n// Default JWT TTL: 30 days. Can be overridden via JWT_EXPIRES_IN env var.\nconst DEFAULT_JWT_EXPIRES_IN_SECONDS = 60 * 60 * 24 * 30\n\n/**\n * Parse a TTL string like \"30d\", \"12h\", \"3600s\", or a bare number-of-seconds\n * into a seconds value. Returns null if the input is missing/unparseable.\n */\nfunction parseDuration(input: string | number | undefined | null): number | null {\n if (input === undefined || input === null || input === '') return null\n if (typeof input === 'number' && Number.isFinite(input) && input > 0) {\n return Math.floor(input)\n }\n const raw = String(input).trim()\n if (/^\\d+$/.test(raw)) {\n const n = parseInt(raw, 10)\n return n > 0 ? n : null\n }\n const match = raw.match(/^(\\d+)\\s*(s|sec|secs|seconds|m|min|mins|minutes|h|hr|hrs|hours|d|day|days)$/i)\n if (!match) return null\n const value = parseInt(match[1]!, 10)\n const unit = match[2]!.toLowerCase()\n if (unit.startsWith('s')) return value\n if (unit.startsWith('m')) return value * 60\n if (unit.startsWith('h')) return value * 60 * 60\n if (unit.startsWith('d')) return value * 60 * 60 * 24\n return null\n}\n\n/**\n * Resolve the JWT expiry in seconds from the environment.\n * Honors `JWT_EXPIRES_IN` (seconds or \"30d\"/\"12h\"/\"3600s\") with a 30-day default.\n */\nexport function getJwtExpirySeconds(env?: Record<string, any> | null): number {\n const configured = parseDuration(env?.JWT_EXPIRES_IN)\n return configured ?? DEFAULT_JWT_EXPIRES_IN_SECONDS\n}\n\n/**\n * Resolve the JWT expiry in seconds. Precedence: `JWT_EXPIRES_IN` env var\n * (authoritative ceiling) → `settings.security.jwtExpiresIn` DB value\n * (admin-configurable) → 30-day default.\n *\n * The env var wins so operators can cap runtime overrides — admins can adjust\n * the TTL from /admin/settings/security, but an env var, if set, always wins.\n * DB failures fall back to env/default so auth never breaks if the settings\n * table is unreachable.\n */\nexport async function getJwtExpirySecondsFromDb(\n db: { prepare: (query: string) => any } | null | undefined,\n env?: Record<string, any> | null\n): Promise<number> {\n const envParsed = parseDuration(env?.JWT_EXPIRES_IN)\n if (envParsed) return envParsed\n\n if (db) {\n try {\n const row = await db\n .prepare(\"SELECT data FROM documents WHERE type_id = 'site_settings' AND slug = 'security' AND tenant_id = 'default' AND is_current_draft = 1 AND deleted_at IS NULL\")\n .first() as { data: string } | null\n if (row?.data) {\n const data = JSON.parse(row.data)\n const parsed = parseDuration(data.jwtExpiresIn)\n if (parsed) return parsed\n }\n } catch (err) {\n console.warn('Failed to read jwtExpiresIn from settings, falling back to default:', err)\n }\n }\n return DEFAULT_JWT_EXPIRES_IN_SECONDS\n}\n\n/**\n * Resolve the refresh grace window (seconds) for `/auth/refresh`. Precedence:\n * `JWT_REFRESH_GRACE_SECONDS` env var → `settings.security.jwtRefreshGraceSeconds`\n * DB value → 7-day default.\n */\nexport async function getJwtRefreshGraceSecondsFromDb(\n db: { prepare: (query: string) => any } | null | undefined,\n env?: Record<string, any> | null\n): Promise<number> {\n const DEFAULT_GRACE = 60 * 60 * 24 * 7\n const envParsed = parseDuration(env?.JWT_REFRESH_GRACE_SECONDS)\n if (envParsed) return envParsed\n\n if (db) {\n try {\n const row = await db\n .prepare(\"SELECT data FROM documents WHERE type_id = 'site_settings' AND slug = 'security' AND tenant_id = 'default' AND is_current_draft = 1 AND deleted_at IS NULL\")\n .first() as { data: string } | null\n if (row?.data) {\n const data = JSON.parse(row.data)\n const parsed = parseDuration(data.jwtRefreshGraceSeconds?.toString())\n if (parsed) return parsed\n }\n } catch (err) {\n console.warn('Failed to read jwtRefreshGraceSeconds from settings:', err)\n }\n }\n return DEFAULT_GRACE\n}\n\n/**\n * Decode a JWT payload without verifying the signature. Returns null on any\n * parsing failure. Callers MUST independently verify the signature before\n * trusting this value — used from the grace-window refresh path where the\n * signature is verified explicitly via `verifyHs256Signature`.\n */\nfunction decodeJwtPayload(token: string): JWTPayload | null {\n try {\n const parts = token.split('.')\n if (parts.length !== 3) return null\n const b64 = parts[1]!.replace(/-/g, '+').replace(/_/g, '/')\n const padded = b64 + '='.repeat((4 - (b64.length % 4)) % 4)\n const json = atob(padded)\n const obj = JSON.parse(json)\n if (!obj || typeof obj.exp !== 'number') return null\n return obj as JWTPayload\n } catch {\n return null\n }\n}\n\nfunction base64UrlToBytes(b64url: string): Uint8Array {\n const b64 = b64url.replace(/-/g, '+').replace(/_/g, '/')\n const padded = b64 + '='.repeat((4 - (b64.length % 4)) % 4)\n const bin = atob(padded)\n const bytes = new Uint8Array(bin.length)\n for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i)\n return bytes\n}\n\n/**\n * Verify a JWT's HS256 signature using Web Crypto, independent of hono/jwt.\n * Returns true iff the signature matches the header.payload portion.\n */\nasync function verifyHs256Signature(token: string, secret: string): Promise<boolean> {\n try {\n const parts = token.split('.')\n if (parts.length !== 3) return false\n const encoder = new TextEncoder()\n const key = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['verify']\n )\n const signature = base64UrlToBytes(parts[2]!)\n const message = encoder.encode(`${parts[0]}.${parts[1]}`)\n return await crypto.subtle.verify('HMAC', key, signature, message)\n } catch {\n return false\n }\n}\n\nexport class AuthManager {\n static async generateToken(\n userId: string,\n email: string,\n role: string,\n secret?: string,\n expiresInSeconds?: number\n ): Promise<string> {\n const ttl = expiresInSeconds && expiresInSeconds > 0\n ? Math.floor(expiresInSeconds)\n : DEFAULT_JWT_EXPIRES_IN_SECONDS\n const now = Math.floor(Date.now() / 1000)\n const payload: JWTPayload = {\n userId,\n email,\n role,\n exp: now + ttl,\n iat: now\n }\n\n return await sign(payload, secret || JWT_SECRET_FALLBACK, 'HS256')\n }\n\n /**\n * Verify a token's signature and expiration.\n *\n * IMPORTANT: pass the `JWT_SECRET` binding (e.g. `c.env.JWT_SECRET`) as the\n * `secret` argument. If omitted, this falls back to a development-only\n * placeholder secret — tokens signed with the real `JWT_SECRET` will then\n * silently fail verification. From inside a Hono handler prefer\n * `AuthManager.verifyAuthRequest(c)`, which handles header/cookie extraction\n * and pulls the secret from `c.env` for you.\n *\n * If `graceSeconds` > 0, tokens whose `exp` is within the grace window\n * (i.e. expired by no more than `graceSeconds`) are still returned. This\n * supports a sliding-session refresh endpoint that accepts recently-expired\n * tokens. Signature failures always return null.\n */\n static async verifyToken(\n token: string,\n secret?: string,\n graceSeconds: number = 0\n ): Promise<JWTPayload | null> {\n const effectiveSecret = secret || JWT_SECRET_FALLBACK\n try {\n let payload: JWTPayload | null = null\n try {\n payload = await verify(token, effectiveSecret, 'HS256') as JWTPayload\n } catch (verifyError: any) {\n // hono/jwt checks `exp` before signature, so a bad-signature token\n // that happens to be expired will throw JwtTokenExpired here. For\n // the grace window, we still require a valid HS256 signature before\n // accepting the payload.\n const name = verifyError?.name || ''\n const message = String(verifyError?.message || '')\n const isExpired = name === 'JwtTokenExpired' || message.includes('expired')\n if (!isExpired || graceSeconds <= 0) {\n throw verifyError\n }\n const signatureValid = await verifyHs256Signature(token, effectiveSecret)\n if (!signatureValid) return null\n const decoded = decodeJwtPayload(token)\n if (!decoded) return null\n payload = decoded\n }\n\n if (!payload) return null\n\n const now = Math.floor(Date.now() / 1000)\n if (payload.exp < now - Math.max(0, Math.floor(graceSeconds))) {\n return null\n }\n\n return payload\n } catch (error) {\n console.error('Token verification failed:', error)\n return null\n }\n }\n\n /**\n * Verify the JWT on an incoming Hono request using the `JWT_SECRET`\n * binding from `c.env`. Reads the token from the `Authorization: Bearer …`\n * header first, then falls back to the `auth_token` cookie. Returns the\n * decoded payload, or null when the token is missing, malformed, expired,\n * or signed with a different secret.\n *\n * Use this from custom Hono routes mounted alongside SonicJS — it\n * resolves the secret the same way `requireAuth()` does, without forcing\n * the caller to plumb it through manually.\n */\n static async verifyAuthRequest(c: Context): Promise<JWTPayload | null> {\n let token = c.req.header('Authorization')?.replace('Bearer ', '')\n if (!token) {\n token = getCookie(c, 'auth_token')\n }\n if (!token) return null\n const secret = (c.env as any)?.JWT_SECRET\n return await AuthManager.verifyToken(token, secret)\n }\n\n static async hashPassword(password: string): Promise<string> {\n const iterations = 100000\n const salt = new Uint8Array(16)\n crypto.getRandomValues(salt)\n\n const encoder = new TextEncoder()\n const keyMaterial = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(password),\n 'PBKDF2',\n false,\n ['deriveBits']\n )\n\n const hashBuffer = await crypto.subtle.deriveBits(\n {\n name: 'PBKDF2',\n salt,\n iterations,\n hash: 'SHA-256'\n },\n keyMaterial,\n 256\n )\n\n const saltHex = Array.from(salt).map(b => b.toString(16).padStart(2, '0')).join('')\n const hashHex = Array.from(new Uint8Array(hashBuffer)).map(b => b.toString(16).padStart(2, '0')).join('')\n\n return `pbkdf2:${iterations}:${saltHex}:${hashHex}`\n }\n\n static async hashPasswordLegacy(password: string): Promise<string> {\n const encoder = new TextEncoder()\n const data = encoder.encode(password + 'salt-change-in-production')\n const hashBuffer = await crypto.subtle.digest('SHA-256', data)\n const hashArray = Array.from(new Uint8Array(hashBuffer))\n return hashArray.map(b => b.toString(16).padStart(2, '0')).join('')\n }\n\n static async verifyPassword(password: string, storedHash: string): Promise<boolean> {\n if (storedHash.startsWith('pbkdf2:')) {\n // PBKDF2 format: pbkdf2:<iterations>:<salt_hex>:<hash_hex>\n const parts = storedHash.split(':')\n if (parts.length !== 4) return false\n\n const iterationsStr = parts[1]!\n const saltHex = parts[2]!\n const expectedHashHex = parts[3]!\n const iterations = parseInt(iterationsStr, 10)\n\n const saltBytes = saltHex.match(/.{2}/g)\n if (!saltBytes) return false\n const salt = new Uint8Array(saltBytes.map(byte => parseInt(byte, 16)))\n\n const encoder = new TextEncoder()\n const keyMaterial = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(password),\n 'PBKDF2',\n false,\n ['deriveBits']\n )\n\n const hashBuffer = await crypto.subtle.deriveBits(\n {\n name: 'PBKDF2',\n salt,\n iterations,\n hash: 'SHA-256'\n },\n keyMaterial,\n 256\n )\n\n const actualHashHex = Array.from(new Uint8Array(hashBuffer)).map(b => b.toString(16).padStart(2, '0')).join('')\n\n // Constant-time comparison\n if (actualHashHex.length !== expectedHashHex.length) return false\n let result = 0\n for (let i = 0; i < actualHashHex.length; i++) {\n result |= actualHashHex.charCodeAt(i) ^ expectedHashHex.charCodeAt(i)\n }\n return result === 0\n }\n\n // Legacy SHA-256 format (no colons in hash)\n const legacyHash = await this.hashPasswordLegacy(password)\n // Constant-time comparison for legacy too\n if (legacyHash.length !== storedHash.length) return false\n let result = 0\n for (let i = 0; i < legacyHash.length; i++) {\n result |= legacyHash.charCodeAt(i) ^ storedHash.charCodeAt(i)\n }\n return result === 0\n }\n\n static isLegacyHash(storedHash: string): boolean {\n return !storedHash.startsWith('pbkdf2:')\n }\n\n /**\n * Set authentication cookie - useful for plugins implementing alternative auth methods\n * @param c - Hono context\n * @param token - JWT token to set in cookie\n * @param options - Optional cookie configuration\n */\n static setAuthCookie(c: Context, token: string, options?: {\n maxAge?: number\n secure?: boolean\n httpOnly?: boolean\n sameSite?: 'Strict' | 'Lax' | 'None'\n }): void {\n setCookie(c, 'auth_token', token, {\n httpOnly: options?.httpOnly ?? true,\n secure: options?.secure ?? true,\n sameSite: options?.sameSite ?? 'Strict',\n maxAge: options?.maxAge ?? getJwtExpirySeconds((c as any)?.env)\n })\n }\n}\n\n// Middleware to require authentication.\n// The Better Auth session middleware (app.ts) has already populated c.get('user')\n// from the session cookie; here we just enforce its presence.\nexport const requireAuth = () => {\n return async (c: Context, next: Next) => {\n const user = c.get('user') as JWTPayload | undefined\n\n if (!user) {\n const acceptHeader = c.req.header('Accept') || ''\n if (acceptHeader.includes('text/html')) {\n return c.redirect('/auth/login?error=Please login to access the admin area')\n }\n return c.json({ error: 'Authentication required' }, 401)\n }\n\n return await next()\n }\n}\n\n// Middleware to require specific role. Must run after requireAuth / the session\n// middleware so c.get('user') is set.\nexport const requireRole = (requiredRole: string | string[]) => {\n return async (c: Context, next: Next) => {\n const user = c.get('user') as JWTPayload | undefined\n\n if (!user) {\n const acceptHeader = c.req.header('Accept') || ''\n if (acceptHeader.includes('text/html')) {\n return c.redirect('/auth/login?error=Please login to access the admin area')\n }\n return c.json({ error: 'Authentication required' }, 401)\n }\n\n const roles = Array.isArray(requiredRole) ? requiredRole : [requiredRole]\n\n if (!roles.includes(user.role)) {\n const acceptHeader = c.req.header('Accept') || ''\n if (acceptHeader.includes('text/html')) {\n return c.redirect('/auth/login?error=You do not have permission to access this area')\n }\n return c.json({ error: 'Insufficient permissions' }, 403)\n }\n\n return await next()\n }\n}\n\n// Middleware to require a live RBAC grant for the signed-in user. This is the\n// dynamic replacement for legacy `users.role` checks on admin routes.\nexport const requireRbac = (resource: string, verb: string) => {\n return async (c: Context, next: Next) => {\n const user = c.get('user') as JWTPayload | undefined\n\n if (!user) {\n const acceptHeader = c.req.header('Accept') || ''\n if (acceptHeader.includes('text/html')) {\n return c.redirect('/auth/login?error=Please login to access the admin area')\n }\n return c.json({ error: 'Authentication required' }, 401)\n }\n\n // Fast path: use pre-computed perms from the /admin/* middleware (avoids DB hit).\n const cachedPerms = (c as any).get('rbacPerms') as string[] | undefined\n let allowed: boolean\n if (cachedPerms !== undefined) {\n allowed = cachedPerms.includes(`${resource}:${verb}`)\n } else {\n allowed = await new RbacService((c.env as any).DB).can(user.userId, resource, verb)\n }\n\n if (!allowed) {\n const acceptHeader = c.req.header('Accept') || ''\n if (acceptHeader.includes('text/html')) {\n return c.redirect('/auth/login?error=You do not have permission to access this area')\n }\n return c.json({ error: 'Insufficient permissions' }, 403)\n }\n\n return await next()\n }\n}\n\n// Optional auth middleware. The session middleware already sets c.get('user')\n// when a valid session exists, so this is a no-op kept for API compatibility.\nexport const optionalAuth = () => {\n return async (_c: Context, next: Next) => {\n return await next()\n }\n}\n","import { MiddlewareHandler } from 'hono'\nimport { metricsTracker } from '../utils/metrics'\n\n/**\n * Middleware to track all HTTP requests for real-time analytics\n * Excludes the metrics endpoint itself to avoid inflating the count\n */\nexport const metricsMiddleware = (): MiddlewareHandler => {\n return async (c, next) => {\n const path = new URL(c.req.url).pathname\n\n // Don't track the metrics endpoint itself to avoid self-inflating counts\n if (path !== '/admin/dashboard/api/metrics') {\n metricsTracker.recordRequest()\n }\n\n // Continue with the request\n await next()\n }\n}\n","/**\n * CSRF Protection Middleware — Signed Double-Submit Cookie\n *\n * Stateless CSRF protection for Cloudflare Workers (no session store needed).\n * Token format: `<nonce>.<hmac>` where HMAC-SHA256 is keyed with JWT_SECRET.\n *\n * Flow:\n * GET — ensureCsrfCookie(): reuse existing valid cookie or set a new one\n * POST/PUT/DELETE/PATCH — validate X-CSRF-Token header === csrf_token cookie, HMAC valid\n *\n * Exempt:\n * - Safe methods (GET, HEAD, OPTIONS)\n * - Auth routes that create sessions (/auth/login*, /auth/register*, etc.)\n * - Public form submissions (/forms/*, /api/forms/*) — NOT /admin/forms/*\n * - Requests with no auth_token cookie (Bearer-only or API-key-only)\n */\n\nimport type { Context, Next } from 'hono'\nimport { getCookie, setCookie } from 'hono/cookie'\n\n// Fallback secret — mirrors auth.ts behavior for local dev without wrangler secret\nconst JWT_SECRET_FALLBACK = 'your-super-secret-jwt-key-change-in-production'\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/** Convert ArrayBuffer to URL-safe base64 (no padding). */\nexport function arrayBufferToBase64Url(buffer: ArrayBuffer): string {\n const bytes = new Uint8Array(buffer)\n let binary = ''\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]!)\n }\n return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '')\n}\n\n/** Import a string key for HMAC-SHA256. */\nasync function getHmacKey(secret: string): Promise<CryptoKey> {\n const encoder = new TextEncoder()\n return crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign', 'verify']\n )\n}\n\n// ============================================================================\n// Token Generation & Validation\n// ============================================================================\n\n/**\n * Generate a signed CSRF token: `<nonce>.<hmac_signature>`\n * - nonce = 32 random bytes, base64url-encoded\n * - signature = HMAC-SHA256(nonce, secret), base64url-encoded\n */\nexport async function generateCsrfToken(secret: string): Promise<string> {\n const nonceBytes = new Uint8Array(32)\n crypto.getRandomValues(nonceBytes)\n const nonce = arrayBufferToBase64Url(nonceBytes.buffer)\n\n const key = await getHmacKey(secret)\n const encoder = new TextEncoder()\n const signatureBuffer = await crypto.subtle.sign('HMAC', key, encoder.encode(nonce))\n const signature = arrayBufferToBase64Url(signatureBuffer)\n\n return `${nonce}.${signature}`\n}\n\n/**\n * Validate a signed CSRF token.\n *\n * Checks that the token has the correct `<nonce>.<signature>` format and that\n * the HMAC signature is valid for the given secret. Uses crypto.subtle.verify\n * which provides constant-time comparison.\n *\n * NOTE: No expiry check here — by design. The security property of signed\n * double-submit comes from the unpredictability of the nonce + the\n * secret-bound HMAC, not from time-bounding. The cookie's maxAge (86400s)\n * handles expiry at the browser level.\n */\nexport async function validateCsrfToken(token: string, secret: string): Promise<boolean> {\n if (!token || typeof token !== 'string') return false\n\n const dotIndex = token.indexOf('.')\n if (dotIndex === -1) return false\n\n const nonce = token.substring(0, dotIndex)\n const signature = token.substring(dotIndex + 1)\n\n if (!nonce || !signature) return false\n\n try {\n const key = await getHmacKey(secret)\n const encoder = new TextEncoder()\n\n // Decode the signature from base64url\n const sigPadded = signature.replace(/-/g, '+').replace(/_/g, '/')\n const sigBinary = atob(sigPadded)\n const sigBytes = new Uint8Array(sigBinary.length)\n for (let i = 0; i < sigBinary.length; i++) {\n sigBytes[i] = sigBinary.charCodeAt(i)\n }\n\n // crypto.subtle.verify is constant-time\n return await crypto.subtle.verify('HMAC', key, sigBytes.buffer, encoder.encode(nonce))\n } catch {\n return false\n }\n}\n\n// ============================================================================\n// Default Exempt Paths\n// ============================================================================\n\nconst DEFAULT_EXEMPT_PATHS = [\n '/auth/login',\n '/auth/register',\n '/auth/seed-admin',\n '/test-seed-defaults',\n '/test-cleanup',\n '/auth/accept-invitation',\n '/auth/reset-password',\n '/auth/request-password-reset',\n '/auth/otp',\n '/auth/magic-link',\n '/auth/sign-out',\n '/auth/sign-in',\n '/auth/sign-up',\n '/auth/get-session',\n '/auth/verify',\n '/api/stripe/webhook',\n '/api/events',\n]\n\n/**\n * Check whether a request path is exempt from CSRF validation.\n * - Exact match or startsWith for auth routes (e.g. /auth/login/form)\n * - /forms/* and /api/forms/* are exempt (public submissions)\n * - /api/search* is exempt (read-only POST for complex query params)\n * - /admin/forms/* is NOT exempt\n */\nfunction isExemptPath(path: string, extraExemptPaths: string[] = []): boolean {\n // Public form routes — NOT /admin/forms/*\n if (path.startsWith('/forms/') || path.startsWith('/api/forms/') || path === '/forms' || path === '/api/forms') {\n return true\n }\n\n // Search API — read-only POST (includes /api/search/click, /api/search/facet-click)\n if (path.startsWith('/api/search')) {\n return true\n }\n\n const allExempt = [...DEFAULT_EXEMPT_PATHS, ...extraExemptPaths]\n for (const exempt of allExempt) {\n if (path === exempt || path.startsWith(exempt + '/')) {\n return true\n }\n }\n\n return false\n}\n\n// ============================================================================\n// Middleware\n// ============================================================================\n\nexport interface CsrfOptions {\n /** Additional paths to exempt from CSRF validation. */\n exemptPaths?: string[]\n}\n\n/**\n * CSRF protection middleware (Signed Double-Submit Cookie).\n *\n * - GET/HEAD/OPTIONS: ensure a valid csrf_token cookie exists\n * - POST/PUT/DELETE/PATCH: validate X-CSRF-Token header matches cookie, HMAC valid\n * - Exempt: auth routes, public /forms/*, Bearer-only, API-key-only\n */\nexport function csrfProtection(options: CsrfOptions = {}) {\n return async (c: Context, next: Next): Promise<Response | void> => {\n const method = c.req.method.toUpperCase()\n const path = new URL(c.req.url).pathname\n const secret = c.env?.JWT_SECRET || JWT_SECRET_FALLBACK\n\n // Warn if using fallback secret in production\n if (c.env?.ENVIRONMENT === 'production' && !c.env?.JWT_SECRET) {\n console.warn(\n '[CSRF] WARNING: JWT_SECRET is not set in production. ' +\n 'CSRF tokens are signed with the fallback key, which is insecure.'\n )\n }\n\n // Safe methods — just ensure cookie, then pass through\n if (method === 'GET' || method === 'HEAD' || method === 'OPTIONS') {\n await ensureCsrfCookie(c, secret)\n await next()\n return\n }\n\n // Exempt paths — pass through without validation\n if (isExemptPath(path, options.exemptPaths)) {\n await next()\n return\n }\n\n // Bearer-only or API-key-only requests (no auth_token cookie) — exempt\n const authCookie = getCookie(c, 'auth_token')\n if (!authCookie) {\n await next()\n return\n }\n\n // Requests with an Authorization header use token-based auth — the cookie\n // is incidental and CSRF protection is unnecessary (the attacker cannot\n // forge the Authorization header from a cross-origin page).\n const authHeader = c.req.header('Authorization')\n if (authHeader) {\n await next()\n return\n }\n\n // State-changing request with cookie auth — validate CSRF\n const cookieToken = getCookie(c, 'csrf_token')\n let headerToken = c.req.header('X-CSRF-Token')\n\n // Fallback: check _csrf field in form-encoded body (regular HTML form submissions)\n if (!headerToken) {\n const contentType = c.req.header('Content-Type') || ''\n if (contentType.includes('application/x-www-form-urlencoded') || contentType.includes('multipart/form-data')) {\n try {\n const body = await c.req.parseBody()\n headerToken = body['_csrf'] as string | undefined\n } catch {\n // Body not parseable — leave headerToken undefined\n }\n }\n }\n\n if (!cookieToken || !headerToken) {\n return csrfError(c, 'CSRF token missing')\n }\n\n if (cookieToken !== headerToken) {\n return csrfError(c, 'CSRF token mismatch')\n }\n\n const isValid = await validateCsrfToken(cookieToken, secret)\n if (!isValid) {\n return csrfError(c, 'CSRF token invalid')\n }\n\n await next()\n }\n}\n\n/**\n * Ensure a valid CSRF cookie exists. Check-then-reuse: if the existing cookie\n * has a valid HMAC signature, reuse it (no new Set-Cookie header). Only\n * generate a fresh token when the cookie is missing or has an invalid signature.\n */\nasync function ensureCsrfCookie(c: Context, secret: string): Promise<void> {\n const existing = getCookie(c, 'csrf_token')\n\n if (existing) {\n const isValid = await validateCsrfToken(existing, secret)\n if (isValid) {\n // Reuse existing valid token — no Set-Cookie needed\n c.set('csrfToken', existing)\n return\n }\n }\n\n // Generate fresh token\n const token = await generateCsrfToken(secret)\n c.set('csrfToken', token)\n\n const isDev = c.env?.ENVIRONMENT === 'development' || !c.env?.ENVIRONMENT\n setCookie(c, 'csrf_token', token, {\n httpOnly: false, // JS must read this cookie\n secure: !isDev,\n sameSite: 'Strict',\n path: '/',\n maxAge: 86400, // 24 hours — browser-side expiry\n })\n}\n\n/** Return a 403 CSRF error — HTML for browser requests, JSON for API. */\nfunction csrfError(c: Context, message: string): Response {\n const accept = c.req.header('Accept') || ''\n if (accept.includes('text/html')) {\n return c.html(\n `<!DOCTYPE html><html><head><title>403 Forbidden</title></head>` +\n `<body><h1>403 Forbidden</h1><p>${message}</p></body></html>`,\n 403\n )\n }\n return c.json({ error: message, status: 403 }, 403)\n}\n","import { Context, Next } from 'hono'\n\ninterface RateLimitOptions {\n max: number\n windowMs: number\n keyPrefix: string\n}\n\ninterface RateLimitEntry {\n count: number\n resetAt: number\n}\n\n/**\n * KV-based sliding window rate limiter middleware.\n * Gracefully skips if CACHE_KV binding is not available.\n */\nexport function rateLimit(options: RateLimitOptions) {\n const { max, windowMs, keyPrefix } = options\n\n return async (c: Context, next: Next) => {\n const kv = (c.env as any)?.CACHE_KV\n if (!kv) {\n // No KV binding available — skip rate limiting\n return await next()\n }\n\n const ip = c.req.header('cf-connecting-ip') || c.req.header('x-forwarded-for') || 'unknown'\n const key = `ratelimit:${keyPrefix}:${ip}`\n\n try {\n const now = Date.now()\n const stored = await kv.get(key, 'json') as RateLimitEntry | null\n\n let entry: RateLimitEntry\n if (stored && stored.resetAt > now) {\n entry = stored\n } else {\n entry = { count: 0, resetAt: now + windowMs }\n }\n\n entry.count++\n\n // Calculate TTL in seconds (KV expiration)\n const ttlSeconds = Math.ceil((entry.resetAt - now) / 1000)\n\n if (entry.count > max) {\n // Store the updated count even when rejecting\n await kv.put(key, JSON.stringify(entry), { expirationTtl: Math.max(ttlSeconds, 60) })\n\n const retryAfter = Math.ceil((entry.resetAt - now) / 1000)\n c.header('Retry-After', String(retryAfter))\n c.header('X-RateLimit-Limit', String(max))\n c.header('X-RateLimit-Remaining', '0')\n c.header('X-RateLimit-Reset', String(Math.ceil(entry.resetAt / 1000)))\n return c.json({ error: 'Too many requests. Please try again later.' }, 429)\n }\n\n await kv.put(key, JSON.stringify(entry), { expirationTtl: Math.max(ttlSeconds, 60) })\n\n c.header('X-RateLimit-Limit', String(max))\n c.header('X-RateLimit-Remaining', String(max - entry.count))\n c.header('X-RateLimit-Reset', String(Math.ceil(entry.resetAt / 1000)))\n\n return await next()\n } catch (error) {\n // Rate limiting should never break the app\n console.error('Rate limiter error (non-fatal):', error)\n return await next()\n }\n }\n}\n","import { Context, Next } from 'hono'\n\n/**\n * Security headers middleware.\n * Sets standard security headers on every response.\n * Skips HSTS in development to avoid local dev issues.\n */\nexport const securityHeadersMiddleware = () => {\n return async (c: Context, next: Next) => {\n await next()\n\n c.header('X-Content-Type-Options', 'nosniff')\n c.header('X-Frame-Options', 'SAMEORIGIN')\n c.header('Referrer-Policy', 'strict-origin-when-cross-origin')\n c.header('Permissions-Policy', 'camera=(), microphone=(), geolocation=()')\n\n // Only set HSTS in non-development environments\n const environment = (c.env as any)?.ENVIRONMENT\n if (environment !== 'development') {\n c.header('Strict-Transport-Security', 'max-age=31536000; includeSubDomains')\n }\n }\n}\n","/**\n * Plugin Middleware\n *\n * Provides middleware functions for checking plugin status and enforcing plugin requirements\n */\n\nimport type { D1Database } from '@cloudflare/workers-types'\n\n/**\n * Check if a plugin is active\n * @param db - The D1 database instance\n * @param pluginId - The plugin ID to check\n * @returns Promise<boolean> - True if the plugin is active, false otherwise\n */\nexport async function isPluginActive(db: D1Database, pluginId: string): Promise<boolean> {\n try {\n // documents table is the authoritative source — PluginService writes here on install/activate.\n // Sidebar nav uses the same query pattern; plugins table is unreliable (may not exist).\n const docResult = await db\n .prepare(\n `SELECT json_extract(data, '$.status') as status FROM documents\n WHERE slug = ? AND type_id = 'plugin' AND tenant_id = 'default'\n AND is_current_draft = 1 AND deleted_at IS NULL`\n )\n .bind(pluginId)\n .first()\n return (docResult as any)?.status === 'active'\n } catch (error) {\n console.error(`[isPluginActive] Error checking plugin status for ${pluginId}:`, error)\n return false\n }\n}\n\n/**\n * Middleware to require a plugin to be active\n * Throws an error if the plugin is not active\n * @param db - The D1 database instance\n * @param pluginId - The plugin ID to check\n * @throws Error if plugin is not active\n */\nexport async function requireActivePlugin(db: D1Database, pluginId: string): Promise<void> {\n const isActive = await isPluginActive(db, pluginId)\n if (!isActive) {\n throw new Error(`Plugin '${pluginId}' is required but is not active`)\n }\n}\n\n/**\n * Middleware to require multiple plugins to be active\n * Throws an error if any plugin is not active\n * @param db - The D1 database instance\n * @param pluginIds - Array of plugin IDs to check\n * @throws Error if any plugin is not active\n */\nexport async function requireActivePlugins(db: D1Database, pluginIds: string[]): Promise<void> {\n for (const pluginId of pluginIds) {\n await requireActivePlugin(db, pluginId)\n }\n}\n\n/**\n * Get all active plugins\n * @param db - The D1 database instance\n * @returns Promise<any[]> - Array of active plugin records\n */\nexport async function getActivePlugins(db: D1Database): Promise<any[]> {\n try {\n const { results } = await db\n .prepare(\n `SELECT slug as id, json_extract(data, '$.status') as status, data FROM documents\n WHERE type_id = 'plugin' AND tenant_id = 'default'\n AND q_plugin_status = 'active' AND is_current_draft = 1 AND deleted_at IS NULL`\n )\n .all()\n\n return results || []\n } catch (error) {\n console.error('[getActivePlugins] Error fetching active plugins:', error)\n return []\n }\n}\n","/**\n * Middleware Module Exports\n *\n * Request processing middleware for SonicJS\n *\n * Note: Most middleware is currently in the monolith and will be migrated later.\n * For now, we only export the bootstrap middleware which is used for system initialization.\n */\n\n// Bootstrap middleware\nexport { bootstrapMiddleware, verifySecurityConfig } from './bootstrap'\n\n// Auth middleware\nexport {\n AuthManager,\n requireAuth,\n requireRole,\n optionalAuth,\n getJwtExpirySeconds,\n getJwtExpirySecondsFromDb,\n getJwtRefreshGraceSecondsFromDb,\n} from './auth'\n\n// Metrics middleware\nexport { metricsMiddleware } from './metrics'\n\n// CSRF protection middleware\nexport { csrfProtection, generateCsrfToken, validateCsrfToken } from './csrf'\n\n// Rate limiting middleware\nexport { rateLimit } from './rate-limit'\n\n// Re-export types and functions that are referenced but implemented in monolith\n// These are placeholder exports to maintain API compatibility\nexport type Permission = string\nexport type UserPermissions = {\n userId: string\n permissions: Permission[]\n}\n\n// Middleware stubs - these return pass-through middleware that call next()\nexport const loggingMiddleware: any = () => async (_c: any, next: any) => await next()\nexport const detailedLoggingMiddleware: any = () => async (_c: any, next: any) => await next()\nexport const securityLoggingMiddleware: any = () => async (_c: any, next: any) => await next()\nexport const performanceLoggingMiddleware: any = () => async (_c: any, next: any) => await next()\nexport const cacheHeaders: any = () => async (_c: any, next: any) => await next()\nexport const compressionMiddleware: any = async (_c: any, next: any) => await next()\nexport { securityHeadersMiddleware as securityHeaders } from './security-headers'\n\n// Other stubs\nexport const PermissionManager: any = {}\nexport const requirePermission: any = () => async (_c: any, next: any) => await next()\nexport const requireAnyPermission: any = () => async (_c: any, next: any) => await next()\nexport const logActivity: any = () => {}\nexport { requireActivePlugin, requireActivePlugins, getActivePlugins, isPluginActive } from './plugin-middleware'\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createTypedHooks } from './chunk-RNZFGN4R.js';
|
|
2
|
-
import { getCoreVersion } from './chunk-
|
|
2
|
+
import { getCoreVersion } from './chunk-ZHPOJZRR.js';
|
|
3
3
|
import { escapeHtml } from './chunk-TQABQWOP.js';
|
|
4
4
|
|
|
5
5
|
// src/plugins/singletons/service-singleton.ts
|
|
@@ -383,5 +383,5 @@ function getPluginDefinition(id) {
|
|
|
383
383
|
}
|
|
384
384
|
|
|
385
385
|
export { CAPABILITY_RENAMES, FIXED_CAPABILITIES, HOOK_CAPABILITY_MAP, SonicCapabilityError, applySchemaDefaults, assertCapability, createCapabilityContext, createServiceSingleton, definePlugin, getPluginDefinition, hasCapability, isDefinedPlugin, isKnownCapability, normalizeCapabilities, normalizeCapability, parseConfigSchema, parseFormDataToSettings, renderSchemaFields, setPluginDefinitions, validateCapabilities };
|
|
386
|
-
//# sourceMappingURL=chunk-
|
|
387
|
-
//# sourceMappingURL=chunk-
|
|
386
|
+
//# sourceMappingURL=chunk-E2LLKPFQ.js.map
|
|
387
|
+
//# sourceMappingURL=chunk-E2LLKPFQ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/plugins/singletons/service-singleton.ts","../src/plugins/capabilities.ts","../src/plugins/sdk/define-plugin.ts","../src/plugins/sdk/config-schema.ts","../src/services/plugin-definition-registry.ts"],"names":[],"mappings":"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","file":"chunk-2JOMHEKO.js","sourcesContent":["/**\n * Generic service-singleton factory\n *\n * Generalizes the hook-system-singleton pattern: a process-wide slot for a\n * service that code outside the HTTP request context — most importantly cron /\n * `scheduled()` handlers, which have no per-request `c.env` — can reach without\n * threading it through every call.\n *\n * Contract (same as the hook-system singleton):\n * - `get()` throws if read before `set()` (throw-before-get) so wiring-order\n * bugs surface loudly rather than silently no-oping.\n * - `set()` is idempotent (last write wins) so constructing multiple apps in one\n * process (e.g. across tests) never throws.\n * - `reset()` clears the slot for test isolation.\n */\n\nexport interface ServiceSingleton<T> {\n /** Set the process-wide instance. Last write wins. */\n set(instance: T): void\n /** Get the instance; throws if not yet set. */\n get(): T\n /** True if an instance has been set. */\n has(): boolean\n /** Clear the slot (test isolation). */\n reset(): void\n}\n\n/**\n * Create a service singleton.\n *\n * @param label Human-readable name used in the throw-before-get error message\n * (e.g. `'EmailService'`).\n */\nexport function createServiceSingleton<T>(label: string): ServiceSingleton<T> {\n let current: T | undefined\n return {\n set(instance: T) {\n current = instance\n },\n get(): T {\n if (current === undefined) {\n throw new Error(\n `${label} has not been initialized. Its setter must be called (the app factory does this at construction) before reading it.`\n )\n }\n return current\n },\n has(): boolean {\n return current !== undefined\n },\n reset() {\n current = undefined\n },\n }\n}\n","/**\n * Plugin capabilities\n *\n * A plugin declares the capabilities it needs (`capabilities: ['email:send']`).\n * The host then hands it a context whose powerful accessors are *gated* by those\n * declarations: reaching `ctx.email` without having declared `email:send` throws\n * `SonicCapabilityError` immediately, instead of failing deep inside a send.\n *\n * This is the isolation boundary that Strapi (namespacing only) and Payload (full\n * config access) don't have: capabilities make a plugin's blast radius explicit\n * and enforceable, and double as documentation of what a plugin can touch.\n *\n * Phase 1 vocabulary. Payment/queue/scheduled-fetch capabilities are intentionally\n * deferred to Phase 2 (see the overhaul plan §8.4 / open question 2).\n */\n\n// Type-only import (no runtime coupling) so a const-narrowed `ctx.cap.email`\n// resolves to the real EmailService type instead of `unknown`.\nimport type { EmailService } from '../services/email/email-service'\nimport type { HookEventName } from './hooks/catalog'\n\n/**\n * Fixed capability names. `db:<table>` is parameterized (a plugin owns specific\n * tables), so it is matched by pattern rather than listed here.\n */\nexport const FIXED_CAPABILITIES = [\n 'email:send',\n 'cache:read',\n 'cache:write',\n 'media:read',\n 'media:write',\n 'http:fetch',\n 'cron:register',\n 'admin:menu',\n 'hooks.auth:subscribe',\n 'hooks.content:subscribe',\n // Reserved: gates subscription to the email event family once those events are\n // dispatched. Declared now so the canonical vocabulary is stable and the\n // Infowall rename target resolves.\n 'hooks.email:subscribe',\n] as const\n\nexport type FixedCapability = (typeof FIXED_CAPABILITIES)[number]\n\n/** A scoped database capability, e.g. `db:email_log`. */\nexport type DbCapability = `db:${string}`\n\n/** Any declarable capability. */\nexport type Capability = FixedCapability | DbCapability\n\nconst DB_CAPABILITY_RE = /^db:[a-zA-Z_][a-zA-Z0-9_]*$/\n\n/** True if `name` is a recognized capability (fixed name or a valid `db:<table>`). */\nexport function isKnownCapability(name: string): name is Capability {\n return (FIXED_CAPABILITIES as readonly string[]).includes(name) || DB_CAPABILITY_RE.test(name)\n}\n\n/**\n * Thrown when a plugin uses a capability it did not declare.\n */\nexport class SonicCapabilityError extends Error {\n readonly capability: string\n readonly plugin?: string\n /** The API surface the plugin tried to access (e.g. 'ctx.cap.email'). Optional. */\n readonly accessedApi?: string\n constructor(capability: string, plugin?: string, accessedApi?: string) {\n super(\n `${plugin ? `Plugin \"${plugin}\"` : 'Plugin'} used capability \"${capability}\" without declaring it. ` +\n `Add \"${capability}\" to the plugin's capabilities.`\n )\n this.name = 'SonicCapabilityError'\n this.capability = capability\n this.plugin = plugin\n this.accessedApi = accessedApi\n }\n}\n\n/** True if `capability` is in the granted set. */\nexport function hasCapability(granted: readonly string[], capability: string): boolean {\n return granted.includes(capability)\n}\n\n/**\n * Assert a capability is granted, throwing {@link SonicCapabilityError} otherwise.\n */\nexport function assertCapability(granted: readonly string[], capability: string, plugin?: string): void {\n if (!hasCapability(granted, capability)) {\n throw new SonicCapabilityError(capability, plugin)\n }\n}\n\n/**\n * Validate a plugin's declared capability list. Returns the unknown entries (empty\n * array = all valid). Callers decide whether to warn or hard-fail.\n *\n * Apply {@link normalizeCapabilities} first if the input may contain deprecated\n * spellings (e.g. from an older SDK or a sibling fork's manifest).\n */\nexport function validateCapabilities(declared: readonly string[]): string[] {\n return declared.filter((c) => !isKnownCapability(c))\n}\n\n// ── Capability rename / normalization (cross-version & cross-fork portability) ─\n//\n// Lets a plugin authored against a different/older SDK spelling load against the\n// canonical vocabulary without code changes. The map is deprecated→canonical; it\n// is applied before the known-capability check. Seeded with the sibling fork's\n// (Infowall) spellings so plugins built there are portable here.\n\nexport const CAPABILITY_RENAMES = {\n // storage:* → media:* (this fork scopes the media library as `media`)\n 'storage:read': 'media:read',\n 'storage:write': 'media:write',\n // cron is a direct registration, not a hook subscription, here\n 'hooks.cron:register': 'cron:register',\n // `:register` → `:subscribe` verb; content read/write granularity lives in the\n // event name (before/after), so both collapse to one subscription capability\n 'hooks.auth:register': 'hooks.auth:subscribe',\n 'hooks.content-read:register': 'hooks.content:subscribe',\n 'hooks.content-write:register': 'hooks.content:subscribe',\n 'hooks.email-events:register': 'hooks.email:subscribe',\n // NOTE: Infowall's `request:intercept` has no canonical target — there is no\n // middleware-insertion surface to gate yet, so it is intentionally absent\n // (a plugin declaring it will surface as unknown rather than silently no-op).\n} as const satisfies Record<string, Capability>\n\n/**\n * Resolve a (possibly deprecated) capability string to its canonical form, or\n * `null` if it is unknown after rename resolution. Renames apply first, then the\n * result is checked against the known vocabulary.\n */\nexport function normalizeCapability(input: string): Capability | null {\n const renamed: string = (CAPABILITY_RENAMES as Record<string, Capability>)[input] ?? input\n return isKnownCapability(renamed) ? (renamed as Capability) : null\n}\n\n/**\n * Normalize a list of capability strings. Returns the canonical capabilities plus\n * the inputs that remained unknown after rename resolution, so the caller can warn\n * (production) or reject (strict).\n */\nexport function normalizeCapabilities(declared: readonly string[]): {\n capabilities: Capability[]\n unknown: string[]\n} {\n const capabilities: Capability[] = []\n const unknown: string[] = []\n for (const raw of declared) {\n const canonical = normalizeCapability(raw)\n if (canonical) {\n if (!capabilities.includes(canonical)) capabilities.push(canonical)\n } else {\n unknown.push(raw)\n }\n }\n return { capabilities, unknown }\n}\n\n// ── Capability-gated context ─────────────────────────────────────────────────\n\n/** Provider factories for capability-backed accessors. Each is called lazily. */\nexport interface CapabilityProviders {\n email?: () => EmailService\n cache?: () => unknown\n http?: () => typeof fetch\n}\n\n// ── Type-level capability narrowing ──────────────────────────────────────────\ndeclare const CAP_NOT_DECLARED: unique symbol\n/**\n * The type of a capability accessor the plugin did NOT declare. Deliberately a\n * branded type (not `never`, which is assignable to everything): using it where a\n * service is expected is a compile error, so `ctx.cap.email` without `email:send`\n * fails to type-check instead of silently passing.\n */\nexport type CapabilityNotDeclared<C extends string = string> = {\n readonly [CAP_NOT_DECLARED]: C\n}\n\n// `T` if the declared tuple `Caps` contains `C`, else the branded not-declared type.\ntype WhenGranted<Caps extends readonly Capability[], C extends string, T> =\n C extends Caps[number] ? T : CapabilityNotDeclared<C>\n// `T` if `Caps` contains ANY of the union `C`, else the branded not-declared type.\ntype WhenGrantedAny<Caps extends readonly Capability[], C extends string, T> =\n Extract<Caps[number], C> extends never ? CapabilityNotDeclared<C> : T\n\n/**\n * The gated context handed to a plugin. Accessors throw at runtime unless the\n * backing capability was declared; with a const-narrowed `Caps` tuple they are\n * also *typed* to the service (or `never`) at compile time, so `ctx.cap.email`\n * is `EmailService` only when `'email:send'` was declared.\n */\nexport interface CapabilityContext<Caps extends readonly Capability[] = readonly Capability[]> {\n /** The capabilities granted to this plugin. */\n readonly capabilities: readonly string[]\n /** True if the plugin declared `capability`. */\n has(capability: string): boolean\n /** Throw {@link SonicCapabilityError} unless `capability` was declared. */\n require(capability: string): void\n /** Email service. `EmailService` when `email:send` is declared, else `never`. */\n readonly email: WhenGranted<Caps, 'email:send', EmailService>\n /** Cache service. Present when `cache:read` or `cache:write` is declared. */\n readonly cache: WhenGrantedAny<Caps, 'cache:read' | 'cache:write', unknown>\n /** Outbound fetch. Present when `http:fetch` is declared. */\n readonly http: WhenGranted<Caps, 'http:fetch', typeof fetch>\n}\n\n/** The un-narrowed gated context (every accessor typed as its service). */\nexport type PluginCapabilityContext = CapabilityContext</** all */ readonly Capability[]>\n\n\n/**\n * Build a capability-gated context.\n *\n * Accessors are lazy getters: they check the grant (and that a provider was\n * supplied) at access time, so merely constructing the context is cheap and\n * holding a reference to a capability you never use costs nothing.\n *\n * @param granted Capabilities the plugin declared.\n * @param providers Backing service factories (only the granted ones get called).\n * @param plugin Plugin name, for clearer errors.\n */\nexport function createCapabilityContext<const Caps extends readonly Capability[]>(\n granted: Caps,\n providers: CapabilityProviders = {},\n plugin?: string\n): CapabilityContext<Caps> {\n // `any` so the lazy getters satisfy the narrowed accessor types (the provider\n // returns the real service at runtime; gating is enforced dynamically below).\n const gate = (capability: string, anyOf: string[], provider: (() => unknown) | undefined): any => {\n const ok = anyOf.some((c) => hasCapability(granted, c))\n if (!ok) throw new SonicCapabilityError(capability, plugin)\n if (!provider) {\n throw new Error(\n `Capability \"${capability}\" is declared by ${plugin ?? 'the plugin'} but no provider was supplied by the host.`\n )\n }\n return provider()\n }\n\n const ctx: CapabilityContext<Caps> = {\n capabilities: [...granted],\n has: (capability) => hasCapability(granted, capability),\n require: (capability) => assertCapability(granted, capability, plugin),\n get email() {\n return gate('email:send', ['email:send'], providers.email)\n },\n get cache() {\n return gate('cache:read', ['cache:read', 'cache:write'], providers.cache)\n },\n get http() {\n return gate('http:fetch', ['http:fetch'], providers.http)\n },\n }\n return ctx\n}\n\n// ── Hook-subscription capability map ────────────────────────────────────────\n//\n// Maps each catalog event to the capability a plugin must declare in order to\n// subscribe to it. Used by the wire phase (Phase A) to gate declarative hook\n// registrations. Plugins that don't declare the required capability have the\n// offending hook skipped (warn in prod, error in strict).\n\nexport const HOOK_CAPABILITY_MAP: Record<HookEventName, Capability> = {\n 'content:read': 'hooks.content:subscribe',\n 'content:before:create': 'hooks.content:subscribe',\n 'content:before:update': 'hooks.content:subscribe',\n 'content:before:delete': 'hooks.content:subscribe',\n 'content:after:create': 'hooks.content:subscribe',\n 'content:after:update': 'hooks.content:subscribe',\n 'content:after:delete': 'hooks.content:subscribe',\n 'content:after:publish': 'hooks.content:subscribe',\n 'auth:registration:completed': 'hooks.auth:subscribe',\n 'auth:password-reset:requested': 'hooks.auth:subscribe',\n 'auth:password-reset:completed': 'hooks.auth:subscribe',\n 'auth:magic-link:consumed': 'hooks.auth:subscribe',\n 'auth:otp:verified': 'hooks.auth:subscribe',\n}\n","/**\n * definePlugin() — the v3 plugin authoring entry point\n *\n * A plugin is authored as a single typed declaration and consumed, unchanged, by\n * every part of the runtime:\n *\n * export const emailPlugin = definePlugin({\n * id: 'email',\n * version: '3.0.0',\n * capabilities: ['email:send', 'hooks.auth:subscribe', 'cron:register'],\n * register(app) { app.route('/admin/plugins/email', emailRoutes) }, // SYNC\n * async onBoot(ctx) { // ASYNC\n * ctx.hooks.on('auth:registration:completed', (p) => { ... }) // typed\n * ctx.cap.email // gated\n * },\n * crons: [{ schedule: '*\\/15 * * * *', hookFamily: 'email-reconciliation' }],\n * async onCronTick(event, ctx) { ... },\n * })\n *\n * The object it returns satisfies the structural contracts the runtime already\n * uses — `MountablePlugin` (mount.ts), `WirablePlugin` (wire.ts), `CronablePlugin`\n * (cron.ts) — plus the legacy `Plugin` metadata fields the admin/registry read.\n * No adapters: a defined plugin drops straight into `plugins.register` or the core\n * plugin list.\n *\n * The value definePlugin adds over a hand-written object is the enriched context:\n * inside `onBoot`/`onCronTick` the author gets a *typed* hook facade (`ctx.hooks`)\n * and the *capability-gated* service context (`ctx.cap`), instead of the raw\n * string-keyed hook system. See the two-phase boot contract: `register` is\n * synchronous (routes only); everything env-dependent lives in `onBoot`.\n */\n\nimport type { Hono } from 'hono'\nimport type { Capability } from '../capabilities'\nimport {\n createCapabilityContext,\n normalizeCapabilities,\n type CapabilityProviders,\n type CapabilityContext,\n} from '../capabilities'\nimport { createTypedHooks, type TypedHooks, type TypedHookHandler } from '../hooks/typed-hooks'\nimport type { HookEventName } from '../hooks/catalog'\nimport type { PluginBootContext, WirableHook } from '../wire'\nimport type { CronContext, CronDeclaration, CronTickEvent } from '../cron'\nimport type { MountableRoute } from '../mount'\nimport { getCoreVersion } from '../../utils/version'\nimport type { ConfigSchema } from './config-schema'\nimport type { PluginMenuEntry } from '../../services/plugin-menu-singleton'\n\n// ── Minimal semver helpers (no external dep — Workers are bundle-size constrained) ─\n\n/** True if `v` is a valid semver string (X.Y.Z with optional pre-release). */\nfunction isSemver(v: string): boolean {\n return /^\\d+\\.\\d+\\.\\d+(-[\\w.]+)?(\\+[\\w.]+)?$/.test(v.trim())\n}\n\n/**\n * Very lightweight semver range satisfier. Handles the most common range forms:\n * exact (`1.2.3`), caret (`^1.2.3` = compatible major), tilde (`~1.2.3` = compatible\n * minor), comparators (`>=1.0.0`, `>1`, `<2.0.0`), and space-separated AND chains.\n * Not a full semver implementation — use the `semver` npm package if you need\n * full range syntax in a non-Workers environment.\n */\nfunction semverSatisfies(version: string, range: string): boolean {\n try {\n const [major, minor, patch] = version.trim().split('-')[0]!.split('.').map(Number)\n const v = major! * 1_000_000 + (minor ?? 0) * 1_000 + (patch ?? 0)\n\n const toInt = (s: string) => {\n const [a, b, c] = s.split('.').map(Number)\n return a! * 1_000_000 + (b ?? 0) * 1_000 + (c ?? 0)\n }\n\n // AND chain: all clauses must pass.\n return range\n .trim()\n .split(/\\s+(?=[><=^~])|\\s+(?=\\d)/)\n .filter(Boolean)\n .every((clause) => {\n const c = clause.trim()\n if (c.startsWith('^')) {\n const base = toInt(c.slice(1))\n const nextMajor = Math.floor(base / 1_000_000 + 1) * 1_000_000\n return v >= base && v < nextMajor\n }\n if (c.startsWith('~')) {\n const base = toInt(c.slice(1))\n const nextMinor = Math.floor(base / 1_000 + 1) * 1_000\n return v >= base && v < nextMinor\n }\n if (c.startsWith('>=')) return v >= toInt(c.slice(2))\n if (c.startsWith('<=')) return v <= toInt(c.slice(2))\n if (c.startsWith('>')) return v > toInt(c.slice(1))\n if (c.startsWith('<')) return v < toInt(c.slice(1))\n return v === toInt(c) // exact\n })\n } catch {\n return true // fail open — don't block a plugin on a parse error\n }\n}\n\n/**\n * Declarative typed hook subscriptions: a map of canonical event name → handler,\n * each narrowed to that event's payload. Flattened into the plugin's `hooks[]`\n * and subscribed during the wire phase. Use `onBoot`'s `ctx.hooks.on()` instead\n * for dynamic/conditional subscriptions.\n */\nexport type DeclarativeHooks = {\n [E in HookEventName]?: TypedHookHandler<E>\n}\n\n/**\n * Context handed to a defined plugin's `onBoot` / `onCronTick`.\n *\n * Enriches the raw boot/cron context with a typed hook facade and the gated\n * capability context, while keeping `raw` and `env` available as an escape hatch.\n */\nexport interface DefinedPluginContext<Caps extends readonly Capability[] = readonly Capability[]> {\n /** Typed hook facade — `ctx.hooks.on('auth:registration:completed', …)`. */\n hooks: TypedHooks\n /**\n * Capability-gated services. With a const-narrowed `Caps`, `ctx.cap.email` is\n * typed `EmailService` only when `'email:send'` was declared (else `never`),\n * and throws `SonicCapabilityError` at runtime if accessed undeclared.\n */\n cap: CapabilityContext<Caps>\n /** Runtime bindings, when available (absent during construction). */\n env?: Record<string, unknown>\n /** The unwrapped context the runtime passed. */\n raw: PluginBootContext | CronContext\n}\n\n/** Input to {@link definePlugin}. */\nexport interface DefinePluginInput<Caps extends readonly Capability[] = readonly []> {\n /** Unique, stable plugin id (kebab-case). Becomes the plugin `name`. */\n id: string\n /** Human-readable display name. Defaults to `id`. */\n name?: string\n /**\n * Semantic version of this plugin (e.g. `'1.2.3'`). Must be a valid semver\n * string — invalid values emit a console.warn at definition time.\n */\n version: string\n /**\n * A semver range expressing which SonicJS core versions this plugin supports\n * (e.g. `'^3.0.0'` or `'>=3.1.0 <4.0.0'`). Checked against the running\n * core version at registration; a mismatch logs a compatibility warning but\n * does not block activation (plugins remain resilient by default).\n */\n sonicjsVersionRange?: string\n description?: string\n author?: { name: string; email?: string; url?: string }\n /** Other plugin ids this one needs (load-order / activation). */\n dependencies?: string[]\n /**\n * Capabilities this plugin declares. The gated `ctx.cap` accessors throw for\n * anything not listed here. Pass as a literal (`['email:send'] as const` is not\n * needed — the `const` type param infers the tuple) to get `ctx.cap` narrowed.\n * Unknown/deprecated names are normalized then warned about at definition.\n */\n capabilities?: Caps\n\n // ── Synchronous registration (routes only) ──\n /** Declarative routes (mounted before the /admin catch-all). */\n routes?: MountableRoute[]\n /**\n * Imperative route registration. MUST be synchronous (Hono's router locks after\n * the first request). Async work belongs in `onBoot`.\n */\n register?: (app: Hono) => void\n\n // ── Asynchronous wiring ──\n /**\n * Declarative typed hook subscriptions (`{ 'content:after:create': (p) => … }`).\n * Subscribed during the wire phase; each handler is narrowed to its event payload.\n */\n hooks?: DeclarativeHooks\n /**\n * Run once on first request, after every plugin has registered. The place for\n * dynamic hook subscriptions (`ctx.hooks.on(...)`) and env-dependent setup.\n */\n onBoot?: (context: DefinedPluginContext<Caps>) => void | Promise<void>\n\n // ── Cron ──\n /** Scheduled-work declarations (also list the expressions in wrangler.toml). */\n crons?: CronDeclaration[]\n /** Handler for a fired cron; branch on `event.hookFamily`. */\n onCronTick?: (event: CronTickEvent, context: DefinedPluginContext<Caps>) => void | Promise<void>\n\n // ── Lifecycle (DB/schema only — never touches routes) ──\n install?: (context: unknown) => void | Promise<void>\n uninstall?: (context: unknown) => void | Promise<void>\n activate?: (context: unknown) => void | Promise<void>\n deactivate?: (context: unknown) => void | Promise<void>\n\n // ── Declarative admin surface ──\n /**\n * Declarative admin-sidebar entries collected by registerPlugins. The catalyst\n * sidebar renders them automatically; no per-plugin `addMenuItem(...)` call\n * required.\n */\n menu?: PluginMenuEntry[]\n /**\n * Schema-driven settings. Declaring this auto-renders the admin form at\n * `/admin/settings/plugins/:id`, parses FormData back into typed values, and\n * persists them via the plugin-service. Authors no longer hand-roll settings\n * routes/templates.\n */\n configSchema?: ConfigSchema\n}\n\n/**\n * The runtime shape produced by {@link definePlugin}. Carries the legacy metadata\n * fields plus the v3 surfaces; structurally satisfies `MountablePlugin`,\n * `WirablePlugin`, and `CronablePlugin`.\n */\nexport interface DefinedPlugin {\n id: string\n name: string\n version: string\n /** The semver range for SonicJS core compatibility declared by the author. */\n sonicjsVersionRange?: string\n description?: string\n author?: { name: string; email?: string; url?: string }\n dependencies?: string[]\n capabilities: Capability[]\n routes?: MountableRoute[]\n register?: (app: Hono) => void\n /** Declarative hook subscriptions, flattened for the wire phase. */\n hooks?: WirableHook[]\n /** Wrapped onBoot accepting the runtime's raw boot context. */\n onBoot?: (context: PluginBootContext) => void | Promise<void>\n crons?: CronDeclaration[]\n /** Wrapped onCronTick accepting the runtime's raw cron context. */\n onCronTick?: (event: CronTickEvent, context: CronContext) => void | Promise<void>\n install?: (context: unknown) => void | Promise<void>\n uninstall?: (context: unknown) => void | Promise<void>\n activate?: (context: unknown) => void | Promise<void>\n deactivate?: (context: unknown) => void | Promise<void>\n /** Declarative admin sidebar entries. registerPlugins collects + sets the menu singleton. */\n menu?: PluginMenuEntry[]\n /** Schema-driven settings. Renders the admin settings form for this plugin. */\n configSchema?: ConfigSchema\n /** Marker so tooling/tests can detect a v3-defined plugin. */\n // eslint-disable-next-line @typescript-eslint/naming-convention -- intentional internal marker\n readonly __sonicV3: true\n}\n\n/**\n * Build the enriched context from whatever raw context the runtime passed.\n *\n * Capability providers ride on the raw context (`raw.providers`) — the host\n * supplies real `email`/`cache`/`http` factories there. When none are supplied, a\n * declared-but-used capability throws \"no provider supplied by host\", which is the\n * correct signal during early bring-up.\n */\nfunction enrich<Caps extends readonly Capability[]>(\n raw: PluginBootContext | CronContext,\n runtimeCaps: readonly Capability[],\n pluginName: string\n): DefinedPluginContext<Caps> {\n const providers = (raw as { providers?: CapabilityProviders }).providers ?? {}\n return {\n hooks: createTypedHooks(raw.hooks),\n // Runtime gating uses the normalized capability set; the context TYPE reflects\n // the declared `Caps` tuple (the narrowing the author sees).\n cap: createCapabilityContext(runtimeCaps as unknown as Caps, providers, pluginName),\n env: raw.env,\n raw,\n }\n}\n\n/**\n * Define a v3 plugin. Validates declared capabilities (warns on unknown), then\n * returns a runtime-ready plugin whose `onBoot`/`onCronTick` receive the enriched,\n * typed, capability-gated context. The `const Caps` type parameter captures the\n * declared capability tuple so `ctx.cap` is narrowed at the author's call site.\n */\nexport function definePlugin<const Caps extends readonly Capability[] = readonly []>(\n input: DefinePluginInput<Caps>\n): DefinedPlugin {\n if (!input.id) throw new Error('definePlugin: `id` is required')\n if (!input.version) throw new Error(`definePlugin: \\`version\\` is required (plugin \"${input.id}\")`)\n\n // Semver validation: warn if the plugin's own version is not a valid semver string.\n if (!isSemver(input.version)) {\n // eslint-disable-next-line no-console\n console.warn(\n `[plugins] Plugin \"${input.id}\" has an invalid version: \"${input.version}\". ` +\n `Use a valid semver string (e.g. \"1.0.0\") to participate in version-range checks.`\n )\n }\n\n // SonicJS core compatibility range check.\n if (input.sonicjsVersionRange) {\n const coreVersion = getCoreVersion()\n if (!semverSatisfies(coreVersion, input.sonicjsVersionRange)) {\n // eslint-disable-next-line no-console\n console.warn(\n `[plugins] Plugin \"${input.id}\" declares sonicjsVersionRange \"${input.sonicjsVersionRange}\" ` +\n `but running core version is \"${coreVersion}\". ` +\n `The plugin may not work correctly. Consider updating the plugin or the version range.`\n )\n }\n }\n\n // Normalize declared capabilities to canonical names first (resolves deprecated\n // / cross-fork spellings like `storage:write` → `media:write`), then warn on any\n // that remain unknown. Strict-reject at registration is layered in Phase 5d.\n const { capabilities, unknown } = normalizeCapabilities(input.capabilities ?? [])\n if (unknown.length > 0) {\n // eslint-disable-next-line no-console\n console.warn(\n `[plugins] Plugin \"${input.id}\" declares unknown capabilities: ${unknown.join(', ')}. ` +\n `These will gate nothing. Check for typos or update the capability vocabulary.`\n )\n }\n\n const name = input.id\n\n const onBoot = input.onBoot\n ? (raw: PluginBootContext) => input.onBoot!(enrich(raw, capabilities, name))\n : undefined\n\n const onCronTick = input.onCronTick\n ? (event: CronTickEvent, raw: CronContext) => input.onCronTick!(event, enrich(raw, capabilities, name))\n : undefined\n\n // Flatten the declarative typed `hooks` map into the wirable `hooks[]` array.\n // Each handler is wrapped to the raw (data, context) shape, coalescing a void\n // return back to the incoming payload (matching createTypedHooks().on()).\n const hooks: WirableHook[] | undefined = input.hooks\n ? Object.entries(input.hooks)\n .filter(([, h]) => typeof h === 'function')\n .map(([eventName, h]) => ({\n name: eventName,\n handler: async (data: any, context: any) => {\n const result = await (h as TypedHookHandler<HookEventName>)(data, context ?? {})\n return result === undefined ? data : result\n },\n }))\n : undefined\n\n return {\n id: input.id,\n name,\n version: input.version,\n sonicjsVersionRange: input.sonicjsVersionRange,\n description: input.description,\n author: input.author,\n dependencies: input.dependencies,\n capabilities,\n routes: input.routes,\n register: input.register,\n hooks,\n onBoot,\n crons: input.crons,\n onCronTick,\n install: input.install,\n uninstall: input.uninstall,\n activate: input.activate,\n deactivate: input.deactivate,\n menu: input.menu,\n configSchema: input.configSchema,\n // eslint-disable-next-line @typescript-eslint/naming-convention -- intentional internal marker\n __sonicV3: true,\n }\n}\n\n/** True if `plugin` was produced by {@link definePlugin}. */\nexport function isDefinedPlugin(plugin: unknown): plugin is DefinedPlugin {\n // eslint-disable-next-line @typescript-eslint/naming-convention -- intentional internal marker\n return !!plugin && typeof plugin === 'object' && (plugin as { __sonicV3?: unknown }).__sonicV3 === true\n}\n","/**\n * Schema-driven plugin settings.\n *\n * Plugins declare `configSchema: { key: ConfigSchemaField }` on definePlugin.\n * The host renders the admin settings UI from the schema, parses FormData back\n * into typed values, and exposes the resulting record via `ctx.settings.load()`.\n *\n * Field kinds: 'string' | 'number' | 'boolean' | 'select'. New kinds get added\n * here once and every consumer picks them up.\n *\n * Phase 1 — settings UI only. The renderer emits plain HTML strings designed to\n * compose into the existing admin layout (no client-side JS). FormData parsing\n * coalesces unchecked-checkbox omission into `false` (the only browser quirk\n * the renderer must account for).\n */\n\nimport { escapeHtml } from '../../utils/sanitize'\n\n// ── Field model ──────────────────────────────────────────────────────────────\n\ninterface BaseField {\n label: string\n description?: string\n required?: boolean\n}\n\nexport interface StringField extends BaseField {\n type: 'string'\n default?: string\n format?: 'email' | 'url' | 'password'\n /** Render as `<input type=\"password\">`. Implied when `format === 'password'`. */\n sensitive?: boolean\n placeholder?: string\n minLength?: number\n maxLength?: number\n}\n\nexport interface NumberField extends BaseField {\n type: 'number'\n default?: number\n min?: number\n max?: number\n step?: number\n}\n\nexport interface BooleanField extends BaseField {\n type: 'boolean'\n default?: boolean\n}\n\nexport interface SelectField extends BaseField {\n type: 'select'\n default?: string\n /** Either `['us','eu']` shorthand or `[{ value, label }]` for distinct display strings. */\n options: readonly string[] | readonly { value: string; label: string }[]\n}\n\nexport type ConfigSchemaField = StringField | NumberField | BooleanField | SelectField\n\nexport type ConfigSchema = Record<string, ConfigSchemaField>\n\n/** Parsed shape — typed record inferred from the schema. */\nexport type SettingsFor<S extends ConfigSchema> = {\n [K in keyof S]: S[K] extends StringField\n ? string\n : S[K] extends NumberField\n ? number\n : S[K] extends BooleanField\n ? boolean\n : S[K] extends SelectField\n ? string\n : never\n}\n\n// ── Parse ────────────────────────────────────────────────────────────────────\n\nexport interface ParsedField {\n key: string\n field: ConfigSchemaField\n}\n\n/** Stable, ordered field list (preserves declaration order). */\nexport function parseConfigSchema(schema: ConfigSchema): ParsedField[] {\n return Object.entries(schema).map(([key, field]) => ({ key, field }))\n}\n\n// ── Render ───────────────────────────────────────────────────────────────────\n\n/**\n * Render all fields as HTML controls. Output is a sequence of `<div class=\"field\">…</div>`\n * blocks designed to drop into the admin form template (no surrounding `<form>` or\n * submit button — those belong to the page that calls this).\n */\nexport function renderSchemaFields(\n schema: ConfigSchema,\n currentValues: Record<string, unknown> = {}\n): string {\n return parseConfigSchema(schema)\n .map(({ key, field }) => {\n const value = key in currentValues ? currentValues[key] : (field as { default?: unknown }).default\n return renderField(key, field, value)\n })\n .join('\\n')\n}\n\nfunction renderField(key: string, field: ConfigSchemaField, value: unknown): string {\n const id = `field-${key}`\n const requiredAttr = field.required ? ' required' : ''\n const labelHtml = `${escapeHtml(field.label)}${field.required ? ' *' : ''}`\n const helpHtml = field.description ? `<p class=\"help text-sm text-gray-400 mt-1\">${escapeHtml(field.description)}</p>` : ''\n\n switch (field.type) {\n case 'string': {\n const isPassword = field.sensitive === true || field.format === 'password'\n const inputType = isPassword ? 'password' : field.format === 'email' ? 'email' : field.format === 'url' ? 'url' : 'text'\n const placeholder = field.placeholder ? ` placeholder=\"${escapeHtml(field.placeholder)}\"` : ''\n const min = field.minLength != null ? ` minlength=\"${field.minLength}\"` : ''\n const max = field.maxLength != null ? ` maxlength=\"${field.maxLength}\"` : ''\n return `\n<div class=\"field mb-4\">\n <label for=\"${id}\" class=\"block text-sm font-medium mb-1\">${labelHtml}</label>\n <input id=\"${id}\" name=\"${escapeHtml(key)}\" type=\"${inputType}\"\n class=\"w-full rounded border border-gray-700 bg-gray-800 px-3 py-2 text-sm\"\n value=\"${escapeHtml(String(value ?? ''))}\"${placeholder}${min}${max}${requiredAttr} />\n ${helpHtml}\n</div>`.trim()\n }\n case 'number': {\n const min = field.min != null ? ` min=\"${field.min}\"` : ''\n const max = field.max != null ? ` max=\"${field.max}\"` : ''\n const step = field.step != null ? ` step=\"${field.step}\"` : ''\n return `\n<div class=\"field mb-4\">\n <label for=\"${id}\" class=\"block text-sm font-medium mb-1\">${labelHtml}</label>\n <input id=\"${id}\" name=\"${escapeHtml(key)}\" type=\"number\"\n class=\"w-full rounded border border-gray-700 bg-gray-800 px-3 py-2 text-sm\"\n value=\"${value == null ? '' : escapeHtml(String(value))}\"${min}${max}${step}${requiredAttr} />\n ${helpHtml}\n</div>`.trim()\n }\n case 'boolean': {\n const checked = value === true ? ' checked' : ''\n return `\n<div class=\"field mb-4\">\n <label class=\"flex items-center gap-2 text-sm font-medium\">\n <input name=\"${escapeHtml(key)}\" type=\"checkbox\" class=\"rounded\"${checked} />\n ${labelHtml}\n </label>\n ${helpHtml}\n</div>`.trim()\n }\n case 'select': {\n const optionsHtml = field.options\n .map((o) => {\n const opt = typeof o === 'string' ? { value: o, label: o } : o\n const selected = opt.value === value ? ' selected' : ''\n return `<option value=\"${escapeHtml(opt.value)}\"${selected}>${escapeHtml(opt.label)}</option>`\n })\n .join('')\n return `\n<div class=\"field mb-4\">\n <label for=\"${id}\" class=\"block text-sm font-medium mb-1\">${labelHtml}</label>\n <select id=\"${id}\" name=\"${escapeHtml(key)}\"\n class=\"w-full rounded border border-gray-700 bg-gray-800 px-3 py-2 text-sm\"${requiredAttr}>\n ${optionsHtml}\n </select>\n ${helpHtml}\n</div>`.trim()\n }\n }\n}\n\n// ── FormData → settings ──────────────────────────────────────────────────────\n\n/**\n * Coerce FormData entries into typed settings per the schema. Notably:\n * - Unchecked checkboxes are omitted by the browser; we coalesce to `false`.\n * - Numbers parse via `Number()` and fall back to the field's default if invalid.\n * - Strings preserve empty string (NOT default) so an admin can intentionally clear.\n */\nexport function parseFormDataToSettings(schema: ConfigSchema, form: FormData): Record<string, unknown> {\n const result: Record<string, unknown> = {}\n for (const { key, field } of parseConfigSchema(schema)) {\n switch (field.type) {\n case 'string': {\n const raw = form.get(key)\n result[key] = raw == null ? field.default ?? '' : String(raw)\n break\n }\n case 'number': {\n const raw = form.get(key)\n if (raw == null || raw === '') {\n result[key] = field.default\n } else {\n const n = Number(raw)\n result[key] = Number.isFinite(n) ? n : field.default\n }\n break\n }\n case 'boolean': {\n // Unchecked checkbox → not present in FormData → false.\n result[key] = form.get(key) != null\n break\n }\n case 'select': {\n const raw = form.get(key)\n result[key] = raw == null ? field.default ?? '' : String(raw)\n break\n }\n }\n }\n return result\n}\n\n// ── Defaults ─────────────────────────────────────────────────────────────────\n\n/** Fill missing keys with field defaults. Existing keys (incl. `false`/`0`/'') win. */\nexport function applySchemaDefaults<S extends ConfigSchema>(\n schema: S,\n stored: Record<string, unknown>\n): Record<string, unknown> {\n const result: Record<string, unknown> = { ...stored }\n for (const { key, field } of parseConfigSchema(schema)) {\n if (result[key] === undefined) {\n const def = (field as { default?: unknown }).default\n if (def !== undefined) result[key] = def\n }\n }\n return result\n}\n","/**\n * In-memory registry of registered plugin definitions, indexed by id.\n *\n * Populated by `registerPlugins()` at app construction. The admin settings\n * route uses it to look up a plugin's `configSchema` so the schema-driven\n * settings form can be auto-rendered without per-plugin glue code.\n *\n * Read by the admin layer; written ONLY by registerPlugins.\n */\n\nimport type { RegisterablePlugin } from '../plugins/sdk/register-plugins'\n\nlet registry: ReadonlyMap<string, RegisterablePlugin> = new Map()\n\nexport function setPluginDefinitions(plugins: ReadonlyArray<RegisterablePlugin>): void {\n const next = new Map<string, RegisterablePlugin>()\n for (const p of plugins) next.set(p.id, p)\n registry = next\n}\n\nexport function getPluginDefinition(id: string): RegisterablePlugin | undefined {\n return registry.get(id)\n}\n\nexport function getAllPluginDefinitions(): ReadonlyArray<RegisterablePlugin> {\n return Array.from(registry.values())\n}\n\nexport function resetPluginDefinitions(): void {\n registry = new Map()\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/plugins/singletons/service-singleton.ts","../src/plugins/capabilities.ts","../src/plugins/sdk/define-plugin.ts","../src/plugins/sdk/config-schema.ts","../src/services/plugin-definition-registry.ts"],"names":[],"mappings":"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","file":"chunk-E2LLKPFQ.js","sourcesContent":["/**\n * Generic service-singleton factory\n *\n * Generalizes the hook-system-singleton pattern: a process-wide slot for a\n * service that code outside the HTTP request context — most importantly cron /\n * `scheduled()` handlers, which have no per-request `c.env` — can reach without\n * threading it through every call.\n *\n * Contract (same as the hook-system singleton):\n * - `get()` throws if read before `set()` (throw-before-get) so wiring-order\n * bugs surface loudly rather than silently no-oping.\n * - `set()` is idempotent (last write wins) so constructing multiple apps in one\n * process (e.g. across tests) never throws.\n * - `reset()` clears the slot for test isolation.\n */\n\nexport interface ServiceSingleton<T> {\n /** Set the process-wide instance. Last write wins. */\n set(instance: T): void\n /** Get the instance; throws if not yet set. */\n get(): T\n /** True if an instance has been set. */\n has(): boolean\n /** Clear the slot (test isolation). */\n reset(): void\n}\n\n/**\n * Create a service singleton.\n *\n * @param label Human-readable name used in the throw-before-get error message\n * (e.g. `'EmailService'`).\n */\nexport function createServiceSingleton<T>(label: string): ServiceSingleton<T> {\n let current: T | undefined\n return {\n set(instance: T) {\n current = instance\n },\n get(): T {\n if (current === undefined) {\n throw new Error(\n `${label} has not been initialized. Its setter must be called (the app factory does this at construction) before reading it.`\n )\n }\n return current\n },\n has(): boolean {\n return current !== undefined\n },\n reset() {\n current = undefined\n },\n }\n}\n","/**\n * Plugin capabilities\n *\n * A plugin declares the capabilities it needs (`capabilities: ['email:send']`).\n * The host then hands it a context whose powerful accessors are *gated* by those\n * declarations: reaching `ctx.email` without having declared `email:send` throws\n * `SonicCapabilityError` immediately, instead of failing deep inside a send.\n *\n * This is the isolation boundary that Strapi (namespacing only) and Payload (full\n * config access) don't have: capabilities make a plugin's blast radius explicit\n * and enforceable, and double as documentation of what a plugin can touch.\n *\n * Phase 1 vocabulary. Payment/queue/scheduled-fetch capabilities are intentionally\n * deferred to Phase 2 (see the overhaul plan §8.4 / open question 2).\n */\n\n// Type-only import (no runtime coupling) so a const-narrowed `ctx.cap.email`\n// resolves to the real EmailService type instead of `unknown`.\nimport type { EmailService } from '../services/email/email-service'\nimport type { HookEventName } from './hooks/catalog'\n\n/**\n * Fixed capability names. `db:<table>` is parameterized (a plugin owns specific\n * tables), so it is matched by pattern rather than listed here.\n */\nexport const FIXED_CAPABILITIES = [\n 'email:send',\n 'cache:read',\n 'cache:write',\n 'media:read',\n 'media:write',\n 'http:fetch',\n 'cron:register',\n 'admin:menu',\n 'hooks.auth:subscribe',\n 'hooks.content:subscribe',\n // Reserved: gates subscription to the email event family once those events are\n // dispatched. Declared now so the canonical vocabulary is stable and the\n // Infowall rename target resolves.\n 'hooks.email:subscribe',\n] as const\n\nexport type FixedCapability = (typeof FIXED_CAPABILITIES)[number]\n\n/** A scoped database capability, e.g. `db:email_log`. */\nexport type DbCapability = `db:${string}`\n\n/** Any declarable capability. */\nexport type Capability = FixedCapability | DbCapability\n\nconst DB_CAPABILITY_RE = /^db:[a-zA-Z_][a-zA-Z0-9_]*$/\n\n/** True if `name` is a recognized capability (fixed name or a valid `db:<table>`). */\nexport function isKnownCapability(name: string): name is Capability {\n return (FIXED_CAPABILITIES as readonly string[]).includes(name) || DB_CAPABILITY_RE.test(name)\n}\n\n/**\n * Thrown when a plugin uses a capability it did not declare.\n */\nexport class SonicCapabilityError extends Error {\n readonly capability: string\n readonly plugin?: string\n /** The API surface the plugin tried to access (e.g. 'ctx.cap.email'). Optional. */\n readonly accessedApi?: string\n constructor(capability: string, plugin?: string, accessedApi?: string) {\n super(\n `${plugin ? `Plugin \"${plugin}\"` : 'Plugin'} used capability \"${capability}\" without declaring it. ` +\n `Add \"${capability}\" to the plugin's capabilities.`\n )\n this.name = 'SonicCapabilityError'\n this.capability = capability\n this.plugin = plugin\n this.accessedApi = accessedApi\n }\n}\n\n/** True if `capability` is in the granted set. */\nexport function hasCapability(granted: readonly string[], capability: string): boolean {\n return granted.includes(capability)\n}\n\n/**\n * Assert a capability is granted, throwing {@link SonicCapabilityError} otherwise.\n */\nexport function assertCapability(granted: readonly string[], capability: string, plugin?: string): void {\n if (!hasCapability(granted, capability)) {\n throw new SonicCapabilityError(capability, plugin)\n }\n}\n\n/**\n * Validate a plugin's declared capability list. Returns the unknown entries (empty\n * array = all valid). Callers decide whether to warn or hard-fail.\n *\n * Apply {@link normalizeCapabilities} first if the input may contain deprecated\n * spellings (e.g. from an older SDK or a sibling fork's manifest).\n */\nexport function validateCapabilities(declared: readonly string[]): string[] {\n return declared.filter((c) => !isKnownCapability(c))\n}\n\n// ── Capability rename / normalization (cross-version & cross-fork portability) ─\n//\n// Lets a plugin authored against a different/older SDK spelling load against the\n// canonical vocabulary without code changes. The map is deprecated→canonical; it\n// is applied before the known-capability check. Seeded with the sibling fork's\n// (Infowall) spellings so plugins built there are portable here.\n\nexport const CAPABILITY_RENAMES = {\n // storage:* → media:* (this fork scopes the media library as `media`)\n 'storage:read': 'media:read',\n 'storage:write': 'media:write',\n // cron is a direct registration, not a hook subscription, here\n 'hooks.cron:register': 'cron:register',\n // `:register` → `:subscribe` verb; content read/write granularity lives in the\n // event name (before/after), so both collapse to one subscription capability\n 'hooks.auth:register': 'hooks.auth:subscribe',\n 'hooks.content-read:register': 'hooks.content:subscribe',\n 'hooks.content-write:register': 'hooks.content:subscribe',\n 'hooks.email-events:register': 'hooks.email:subscribe',\n // NOTE: Infowall's `request:intercept` has no canonical target — there is no\n // middleware-insertion surface to gate yet, so it is intentionally absent\n // (a plugin declaring it will surface as unknown rather than silently no-op).\n} as const satisfies Record<string, Capability>\n\n/**\n * Resolve a (possibly deprecated) capability string to its canonical form, or\n * `null` if it is unknown after rename resolution. Renames apply first, then the\n * result is checked against the known vocabulary.\n */\nexport function normalizeCapability(input: string): Capability | null {\n const renamed: string = (CAPABILITY_RENAMES as Record<string, Capability>)[input] ?? input\n return isKnownCapability(renamed) ? (renamed as Capability) : null\n}\n\n/**\n * Normalize a list of capability strings. Returns the canonical capabilities plus\n * the inputs that remained unknown after rename resolution, so the caller can warn\n * (production) or reject (strict).\n */\nexport function normalizeCapabilities(declared: readonly string[]): {\n capabilities: Capability[]\n unknown: string[]\n} {\n const capabilities: Capability[] = []\n const unknown: string[] = []\n for (const raw of declared) {\n const canonical = normalizeCapability(raw)\n if (canonical) {\n if (!capabilities.includes(canonical)) capabilities.push(canonical)\n } else {\n unknown.push(raw)\n }\n }\n return { capabilities, unknown }\n}\n\n// ── Capability-gated context ─────────────────────────────────────────────────\n\n/** Provider factories for capability-backed accessors. Each is called lazily. */\nexport interface CapabilityProviders {\n email?: () => EmailService\n cache?: () => unknown\n http?: () => typeof fetch\n}\n\n// ── Type-level capability narrowing ──────────────────────────────────────────\ndeclare const CAP_NOT_DECLARED: unique symbol\n/**\n * The type of a capability accessor the plugin did NOT declare. Deliberately a\n * branded type (not `never`, which is assignable to everything): using it where a\n * service is expected is a compile error, so `ctx.cap.email` without `email:send`\n * fails to type-check instead of silently passing.\n */\nexport type CapabilityNotDeclared<C extends string = string> = {\n readonly [CAP_NOT_DECLARED]: C\n}\n\n// `T` if the declared tuple `Caps` contains `C`, else the branded not-declared type.\ntype WhenGranted<Caps extends readonly Capability[], C extends string, T> =\n C extends Caps[number] ? T : CapabilityNotDeclared<C>\n// `T` if `Caps` contains ANY of the union `C`, else the branded not-declared type.\ntype WhenGrantedAny<Caps extends readonly Capability[], C extends string, T> =\n Extract<Caps[number], C> extends never ? CapabilityNotDeclared<C> : T\n\n/**\n * The gated context handed to a plugin. Accessors throw at runtime unless the\n * backing capability was declared; with a const-narrowed `Caps` tuple they are\n * also *typed* to the service (or `never`) at compile time, so `ctx.cap.email`\n * is `EmailService` only when `'email:send'` was declared.\n */\nexport interface CapabilityContext<Caps extends readonly Capability[] = readonly Capability[]> {\n /** The capabilities granted to this plugin. */\n readonly capabilities: readonly string[]\n /** True if the plugin declared `capability`. */\n has(capability: string): boolean\n /** Throw {@link SonicCapabilityError} unless `capability` was declared. */\n require(capability: string): void\n /** Email service. `EmailService` when `email:send` is declared, else `never`. */\n readonly email: WhenGranted<Caps, 'email:send', EmailService>\n /** Cache service. Present when `cache:read` or `cache:write` is declared. */\n readonly cache: WhenGrantedAny<Caps, 'cache:read' | 'cache:write', unknown>\n /** Outbound fetch. Present when `http:fetch` is declared. */\n readonly http: WhenGranted<Caps, 'http:fetch', typeof fetch>\n}\n\n/** The un-narrowed gated context (every accessor typed as its service). */\nexport type PluginCapabilityContext = CapabilityContext</** all */ readonly Capability[]>\n\n\n/**\n * Build a capability-gated context.\n *\n * Accessors are lazy getters: they check the grant (and that a provider was\n * supplied) at access time, so merely constructing the context is cheap and\n * holding a reference to a capability you never use costs nothing.\n *\n * @param granted Capabilities the plugin declared.\n * @param providers Backing service factories (only the granted ones get called).\n * @param plugin Plugin name, for clearer errors.\n */\nexport function createCapabilityContext<const Caps extends readonly Capability[]>(\n granted: Caps,\n providers: CapabilityProviders = {},\n plugin?: string\n): CapabilityContext<Caps> {\n // `any` so the lazy getters satisfy the narrowed accessor types (the provider\n // returns the real service at runtime; gating is enforced dynamically below).\n const gate = (capability: string, anyOf: string[], provider: (() => unknown) | undefined): any => {\n const ok = anyOf.some((c) => hasCapability(granted, c))\n if (!ok) throw new SonicCapabilityError(capability, plugin)\n if (!provider) {\n throw new Error(\n `Capability \"${capability}\" is declared by ${plugin ?? 'the plugin'} but no provider was supplied by the host.`\n )\n }\n return provider()\n }\n\n const ctx: CapabilityContext<Caps> = {\n capabilities: [...granted],\n has: (capability) => hasCapability(granted, capability),\n require: (capability) => assertCapability(granted, capability, plugin),\n get email() {\n return gate('email:send', ['email:send'], providers.email)\n },\n get cache() {\n return gate('cache:read', ['cache:read', 'cache:write'], providers.cache)\n },\n get http() {\n return gate('http:fetch', ['http:fetch'], providers.http)\n },\n }\n return ctx\n}\n\n// ── Hook-subscription capability map ────────────────────────────────────────\n//\n// Maps each catalog event to the capability a plugin must declare in order to\n// subscribe to it. Used by the wire phase (Phase A) to gate declarative hook\n// registrations. Plugins that don't declare the required capability have the\n// offending hook skipped (warn in prod, error in strict).\n\nexport const HOOK_CAPABILITY_MAP: Record<HookEventName, Capability> = {\n 'content:read': 'hooks.content:subscribe',\n 'content:before:create': 'hooks.content:subscribe',\n 'content:before:update': 'hooks.content:subscribe',\n 'content:before:delete': 'hooks.content:subscribe',\n 'content:after:create': 'hooks.content:subscribe',\n 'content:after:update': 'hooks.content:subscribe',\n 'content:after:delete': 'hooks.content:subscribe',\n 'content:after:publish': 'hooks.content:subscribe',\n 'auth:registration:completed': 'hooks.auth:subscribe',\n 'auth:password-reset:requested': 'hooks.auth:subscribe',\n 'auth:password-reset:completed': 'hooks.auth:subscribe',\n 'auth:magic-link:consumed': 'hooks.auth:subscribe',\n 'auth:otp:verified': 'hooks.auth:subscribe',\n}\n","/**\n * definePlugin() — the v3 plugin authoring entry point\n *\n * A plugin is authored as a single typed declaration and consumed, unchanged, by\n * every part of the runtime:\n *\n * export const emailPlugin = definePlugin({\n * id: 'email',\n * version: '3.0.0',\n * capabilities: ['email:send', 'hooks.auth:subscribe', 'cron:register'],\n * register(app) { app.route('/admin/plugins/email', emailRoutes) }, // SYNC\n * async onBoot(ctx) { // ASYNC\n * ctx.hooks.on('auth:registration:completed', (p) => { ... }) // typed\n * ctx.cap.email // gated\n * },\n * crons: [{ schedule: '*\\/15 * * * *', hookFamily: 'email-reconciliation' }],\n * async onCronTick(event, ctx) { ... },\n * })\n *\n * The object it returns satisfies the structural contracts the runtime already\n * uses — `MountablePlugin` (mount.ts), `WirablePlugin` (wire.ts), `CronablePlugin`\n * (cron.ts) — plus the legacy `Plugin` metadata fields the admin/registry read.\n * No adapters: a defined plugin drops straight into `plugins.register` or the core\n * plugin list.\n *\n * The value definePlugin adds over a hand-written object is the enriched context:\n * inside `onBoot`/`onCronTick` the author gets a *typed* hook facade (`ctx.hooks`)\n * and the *capability-gated* service context (`ctx.cap`), instead of the raw\n * string-keyed hook system. See the two-phase boot contract: `register` is\n * synchronous (routes only); everything env-dependent lives in `onBoot`.\n */\n\nimport type { Hono } from 'hono'\nimport type { Capability } from '../capabilities'\nimport {\n createCapabilityContext,\n normalizeCapabilities,\n type CapabilityProviders,\n type CapabilityContext,\n} from '../capabilities'\nimport { createTypedHooks, type TypedHooks, type TypedHookHandler } from '../hooks/typed-hooks'\nimport type { HookEventName } from '../hooks/catalog'\nimport type { PluginBootContext, WirableHook } from '../wire'\nimport type { CronContext, CronDeclaration, CronTickEvent } from '../cron'\nimport type { MountableRoute } from '../mount'\nimport { getCoreVersion } from '../../utils/version'\nimport type { ConfigSchema } from './config-schema'\nimport type { PluginMenuEntry } from '../../services/plugin-menu-singleton'\n\n// ── Minimal semver helpers (no external dep — Workers are bundle-size constrained) ─\n\n/** True if `v` is a valid semver string (X.Y.Z with optional pre-release). */\nfunction isSemver(v: string): boolean {\n return /^\\d+\\.\\d+\\.\\d+(-[\\w.]+)?(\\+[\\w.]+)?$/.test(v.trim())\n}\n\n/**\n * Very lightweight semver range satisfier. Handles the most common range forms:\n * exact (`1.2.3`), caret (`^1.2.3` = compatible major), tilde (`~1.2.3` = compatible\n * minor), comparators (`>=1.0.0`, `>1`, `<2.0.0`), and space-separated AND chains.\n * Not a full semver implementation — use the `semver` npm package if you need\n * full range syntax in a non-Workers environment.\n */\nfunction semverSatisfies(version: string, range: string): boolean {\n try {\n const [major, minor, patch] = version.trim().split('-')[0]!.split('.').map(Number)\n const v = major! * 1_000_000 + (minor ?? 0) * 1_000 + (patch ?? 0)\n\n const toInt = (s: string) => {\n const [a, b, c] = s.split('.').map(Number)\n return a! * 1_000_000 + (b ?? 0) * 1_000 + (c ?? 0)\n }\n\n // AND chain: all clauses must pass.\n return range\n .trim()\n .split(/\\s+(?=[><=^~])|\\s+(?=\\d)/)\n .filter(Boolean)\n .every((clause) => {\n const c = clause.trim()\n if (c.startsWith('^')) {\n const base = toInt(c.slice(1))\n const nextMajor = Math.floor(base / 1_000_000 + 1) * 1_000_000\n return v >= base && v < nextMajor\n }\n if (c.startsWith('~')) {\n const base = toInt(c.slice(1))\n const nextMinor = Math.floor(base / 1_000 + 1) * 1_000\n return v >= base && v < nextMinor\n }\n if (c.startsWith('>=')) return v >= toInt(c.slice(2))\n if (c.startsWith('<=')) return v <= toInt(c.slice(2))\n if (c.startsWith('>')) return v > toInt(c.slice(1))\n if (c.startsWith('<')) return v < toInt(c.slice(1))\n return v === toInt(c) // exact\n })\n } catch {\n return true // fail open — don't block a plugin on a parse error\n }\n}\n\n/**\n * Declarative typed hook subscriptions: a map of canonical event name → handler,\n * each narrowed to that event's payload. Flattened into the plugin's `hooks[]`\n * and subscribed during the wire phase. Use `onBoot`'s `ctx.hooks.on()` instead\n * for dynamic/conditional subscriptions.\n */\nexport type DeclarativeHooks = {\n [E in HookEventName]?: TypedHookHandler<E>\n}\n\n/**\n * Context handed to a defined plugin's `onBoot` / `onCronTick`.\n *\n * Enriches the raw boot/cron context with a typed hook facade and the gated\n * capability context, while keeping `raw` and `env` available as an escape hatch.\n */\nexport interface DefinedPluginContext<Caps extends readonly Capability[] = readonly Capability[]> {\n /** Typed hook facade — `ctx.hooks.on('auth:registration:completed', …)`. */\n hooks: TypedHooks\n /**\n * Capability-gated services. With a const-narrowed `Caps`, `ctx.cap.email` is\n * typed `EmailService` only when `'email:send'` was declared (else `never`),\n * and throws `SonicCapabilityError` at runtime if accessed undeclared.\n */\n cap: CapabilityContext<Caps>\n /** Runtime bindings, when available (absent during construction). */\n env?: Record<string, unknown>\n /** The unwrapped context the runtime passed. */\n raw: PluginBootContext | CronContext\n}\n\n/** Input to {@link definePlugin}. */\nexport interface DefinePluginInput<Caps extends readonly Capability[] = readonly []> {\n /** Unique, stable plugin id (kebab-case). Becomes the plugin `name`. */\n id: string\n /** Human-readable display name. Defaults to `id`. */\n name?: string\n /**\n * Semantic version of this plugin (e.g. `'1.2.3'`). Must be a valid semver\n * string — invalid values emit a console.warn at definition time.\n */\n version: string\n /**\n * A semver range expressing which SonicJS core versions this plugin supports\n * (e.g. `'^3.0.0'` or `'>=3.1.0 <4.0.0'`). Checked against the running\n * core version at registration; a mismatch logs a compatibility warning but\n * does not block activation (plugins remain resilient by default).\n */\n sonicjsVersionRange?: string\n description?: string\n author?: { name: string; email?: string; url?: string }\n /** Other plugin ids this one needs (load-order / activation). */\n dependencies?: string[]\n /**\n * Capabilities this plugin declares. The gated `ctx.cap` accessors throw for\n * anything not listed here. Pass as a literal (`['email:send'] as const` is not\n * needed — the `const` type param infers the tuple) to get `ctx.cap` narrowed.\n * Unknown/deprecated names are normalized then warned about at definition.\n */\n capabilities?: Caps\n\n // ── Synchronous registration (routes only) ──\n /** Declarative routes (mounted before the /admin catch-all). */\n routes?: MountableRoute[]\n /**\n * Imperative route registration. MUST be synchronous (Hono's router locks after\n * the first request). Async work belongs in `onBoot`.\n */\n register?: (app: Hono) => void\n\n // ── Asynchronous wiring ──\n /**\n * Declarative typed hook subscriptions (`{ 'content:after:create': (p) => … }`).\n * Subscribed during the wire phase; each handler is narrowed to its event payload.\n */\n hooks?: DeclarativeHooks\n /**\n * Run once on first request, after every plugin has registered. The place for\n * dynamic hook subscriptions (`ctx.hooks.on(...)`) and env-dependent setup.\n */\n onBoot?: (context: DefinedPluginContext<Caps>) => void | Promise<void>\n\n // ── Cron ──\n /** Scheduled-work declarations (also list the expressions in wrangler.toml). */\n crons?: CronDeclaration[]\n /** Handler for a fired cron; branch on `event.hookFamily`. */\n onCronTick?: (event: CronTickEvent, context: DefinedPluginContext<Caps>) => void | Promise<void>\n\n // ── Lifecycle (DB/schema only — never touches routes) ──\n install?: (context: unknown) => void | Promise<void>\n uninstall?: (context: unknown) => void | Promise<void>\n activate?: (context: unknown) => void | Promise<void>\n deactivate?: (context: unknown) => void | Promise<void>\n\n // ── Declarative admin surface ──\n /**\n * Declarative admin-sidebar entries collected by registerPlugins. The catalyst\n * sidebar renders them automatically; no per-plugin `addMenuItem(...)` call\n * required.\n */\n menu?: PluginMenuEntry[]\n /**\n * Schema-driven settings. Declaring this auto-renders the admin form at\n * `/admin/settings/plugins/:id`, parses FormData back into typed values, and\n * persists them via the plugin-service. Authors no longer hand-roll settings\n * routes/templates.\n */\n configSchema?: ConfigSchema\n}\n\n/**\n * The runtime shape produced by {@link definePlugin}. Carries the legacy metadata\n * fields plus the v3 surfaces; structurally satisfies `MountablePlugin`,\n * `WirablePlugin`, and `CronablePlugin`.\n */\nexport interface DefinedPlugin {\n id: string\n name: string\n version: string\n /** The semver range for SonicJS core compatibility declared by the author. */\n sonicjsVersionRange?: string\n description?: string\n author?: { name: string; email?: string; url?: string }\n dependencies?: string[]\n capabilities: Capability[]\n routes?: MountableRoute[]\n register?: (app: Hono) => void\n /** Declarative hook subscriptions, flattened for the wire phase. */\n hooks?: WirableHook[]\n /** Wrapped onBoot accepting the runtime's raw boot context. */\n onBoot?: (context: PluginBootContext) => void | Promise<void>\n crons?: CronDeclaration[]\n /** Wrapped onCronTick accepting the runtime's raw cron context. */\n onCronTick?: (event: CronTickEvent, context: CronContext) => void | Promise<void>\n install?: (context: unknown) => void | Promise<void>\n uninstall?: (context: unknown) => void | Promise<void>\n activate?: (context: unknown) => void | Promise<void>\n deactivate?: (context: unknown) => void | Promise<void>\n /** Declarative admin sidebar entries. registerPlugins collects + sets the menu singleton. */\n menu?: PluginMenuEntry[]\n /** Schema-driven settings. Renders the admin settings form for this plugin. */\n configSchema?: ConfigSchema\n /** Marker so tooling/tests can detect a v3-defined plugin. */\n // eslint-disable-next-line @typescript-eslint/naming-convention -- intentional internal marker\n readonly __sonicV3: true\n}\n\n/**\n * Build the enriched context from whatever raw context the runtime passed.\n *\n * Capability providers ride on the raw context (`raw.providers`) — the host\n * supplies real `email`/`cache`/`http` factories there. When none are supplied, a\n * declared-but-used capability throws \"no provider supplied by host\", which is the\n * correct signal during early bring-up.\n */\nfunction enrich<Caps extends readonly Capability[]>(\n raw: PluginBootContext | CronContext,\n runtimeCaps: readonly Capability[],\n pluginName: string\n): DefinedPluginContext<Caps> {\n const providers = (raw as { providers?: CapabilityProviders }).providers ?? {}\n return {\n hooks: createTypedHooks(raw.hooks),\n // Runtime gating uses the normalized capability set; the context TYPE reflects\n // the declared `Caps` tuple (the narrowing the author sees).\n cap: createCapabilityContext(runtimeCaps as unknown as Caps, providers, pluginName),\n env: raw.env,\n raw,\n }\n}\n\n/**\n * Define a v3 plugin. Validates declared capabilities (warns on unknown), then\n * returns a runtime-ready plugin whose `onBoot`/`onCronTick` receive the enriched,\n * typed, capability-gated context. The `const Caps` type parameter captures the\n * declared capability tuple so `ctx.cap` is narrowed at the author's call site.\n */\nexport function definePlugin<const Caps extends readonly Capability[] = readonly []>(\n input: DefinePluginInput<Caps>\n): DefinedPlugin {\n if (!input.id) throw new Error('definePlugin: `id` is required')\n if (!input.version) throw new Error(`definePlugin: \\`version\\` is required (plugin \"${input.id}\")`)\n\n // Semver validation: warn if the plugin's own version is not a valid semver string.\n if (!isSemver(input.version)) {\n // eslint-disable-next-line no-console\n console.warn(\n `[plugins] Plugin \"${input.id}\" has an invalid version: \"${input.version}\". ` +\n `Use a valid semver string (e.g. \"1.0.0\") to participate in version-range checks.`\n )\n }\n\n // SonicJS core compatibility range check.\n if (input.sonicjsVersionRange) {\n const coreVersion = getCoreVersion()\n if (!semverSatisfies(coreVersion, input.sonicjsVersionRange)) {\n // eslint-disable-next-line no-console\n console.warn(\n `[plugins] Plugin \"${input.id}\" declares sonicjsVersionRange \"${input.sonicjsVersionRange}\" ` +\n `but running core version is \"${coreVersion}\". ` +\n `The plugin may not work correctly. Consider updating the plugin or the version range.`\n )\n }\n }\n\n // Normalize declared capabilities to canonical names first (resolves deprecated\n // / cross-fork spellings like `storage:write` → `media:write`), then warn on any\n // that remain unknown. Strict-reject at registration is layered in Phase 5d.\n const { capabilities, unknown } = normalizeCapabilities(input.capabilities ?? [])\n if (unknown.length > 0) {\n // eslint-disable-next-line no-console\n console.warn(\n `[plugins] Plugin \"${input.id}\" declares unknown capabilities: ${unknown.join(', ')}. ` +\n `These will gate nothing. Check for typos or update the capability vocabulary.`\n )\n }\n\n const name = input.id\n\n const onBoot = input.onBoot\n ? (raw: PluginBootContext) => input.onBoot!(enrich(raw, capabilities, name))\n : undefined\n\n const onCronTick = input.onCronTick\n ? (event: CronTickEvent, raw: CronContext) => input.onCronTick!(event, enrich(raw, capabilities, name))\n : undefined\n\n // Flatten the declarative typed `hooks` map into the wirable `hooks[]` array.\n // Each handler is wrapped to the raw (data, context) shape, coalescing a void\n // return back to the incoming payload (matching createTypedHooks().on()).\n const hooks: WirableHook[] | undefined = input.hooks\n ? Object.entries(input.hooks)\n .filter(([, h]) => typeof h === 'function')\n .map(([eventName, h]) => ({\n name: eventName,\n handler: async (data: any, context: any) => {\n const result = await (h as TypedHookHandler<HookEventName>)(data, context ?? {})\n return result === undefined ? data : result\n },\n }))\n : undefined\n\n return {\n id: input.id,\n name,\n version: input.version,\n sonicjsVersionRange: input.sonicjsVersionRange,\n description: input.description,\n author: input.author,\n dependencies: input.dependencies,\n capabilities,\n routes: input.routes,\n register: input.register,\n hooks,\n onBoot,\n crons: input.crons,\n onCronTick,\n install: input.install,\n uninstall: input.uninstall,\n activate: input.activate,\n deactivate: input.deactivate,\n menu: input.menu,\n configSchema: input.configSchema,\n // eslint-disable-next-line @typescript-eslint/naming-convention -- intentional internal marker\n __sonicV3: true,\n }\n}\n\n/** True if `plugin` was produced by {@link definePlugin}. */\nexport function isDefinedPlugin(plugin: unknown): plugin is DefinedPlugin {\n // eslint-disable-next-line @typescript-eslint/naming-convention -- intentional internal marker\n return !!plugin && typeof plugin === 'object' && (plugin as { __sonicV3?: unknown }).__sonicV3 === true\n}\n","/**\n * Schema-driven plugin settings.\n *\n * Plugins declare `configSchema: { key: ConfigSchemaField }` on definePlugin.\n * The host renders the admin settings UI from the schema, parses FormData back\n * into typed values, and exposes the resulting record via `ctx.settings.load()`.\n *\n * Field kinds: 'string' | 'number' | 'boolean' | 'select'. New kinds get added\n * here once and every consumer picks them up.\n *\n * Phase 1 — settings UI only. The renderer emits plain HTML strings designed to\n * compose into the existing admin layout (no client-side JS). FormData parsing\n * coalesces unchecked-checkbox omission into `false` (the only browser quirk\n * the renderer must account for).\n */\n\nimport { escapeHtml } from '../../utils/sanitize'\n\n// ── Field model ──────────────────────────────────────────────────────────────\n\ninterface BaseField {\n label: string\n description?: string\n required?: boolean\n}\n\nexport interface StringField extends BaseField {\n type: 'string'\n default?: string\n format?: 'email' | 'url' | 'password'\n /** Render as `<input type=\"password\">`. Implied when `format === 'password'`. */\n sensitive?: boolean\n placeholder?: string\n minLength?: number\n maxLength?: number\n}\n\nexport interface NumberField extends BaseField {\n type: 'number'\n default?: number\n min?: number\n max?: number\n step?: number\n}\n\nexport interface BooleanField extends BaseField {\n type: 'boolean'\n default?: boolean\n}\n\nexport interface SelectField extends BaseField {\n type: 'select'\n default?: string\n /** Either `['us','eu']` shorthand or `[{ value, label }]` for distinct display strings. */\n options: readonly string[] | readonly { value: string; label: string }[]\n}\n\nexport type ConfigSchemaField = StringField | NumberField | BooleanField | SelectField\n\nexport type ConfigSchema = Record<string, ConfigSchemaField>\n\n/** Parsed shape — typed record inferred from the schema. */\nexport type SettingsFor<S extends ConfigSchema> = {\n [K in keyof S]: S[K] extends StringField\n ? string\n : S[K] extends NumberField\n ? number\n : S[K] extends BooleanField\n ? boolean\n : S[K] extends SelectField\n ? string\n : never\n}\n\n// ── Parse ────────────────────────────────────────────────────────────────────\n\nexport interface ParsedField {\n key: string\n field: ConfigSchemaField\n}\n\n/** Stable, ordered field list (preserves declaration order). */\nexport function parseConfigSchema(schema: ConfigSchema): ParsedField[] {\n return Object.entries(schema).map(([key, field]) => ({ key, field }))\n}\n\n// ── Render ───────────────────────────────────────────────────────────────────\n\n/**\n * Render all fields as HTML controls. Output is a sequence of `<div class=\"field\">…</div>`\n * blocks designed to drop into the admin form template (no surrounding `<form>` or\n * submit button — those belong to the page that calls this).\n */\nexport function renderSchemaFields(\n schema: ConfigSchema,\n currentValues: Record<string, unknown> = {}\n): string {\n return parseConfigSchema(schema)\n .map(({ key, field }) => {\n const value = key in currentValues ? currentValues[key] : (field as { default?: unknown }).default\n return renderField(key, field, value)\n })\n .join('\\n')\n}\n\nfunction renderField(key: string, field: ConfigSchemaField, value: unknown): string {\n const id = `field-${key}`\n const requiredAttr = field.required ? ' required' : ''\n const labelHtml = `${escapeHtml(field.label)}${field.required ? ' *' : ''}`\n const helpHtml = field.description ? `<p class=\"help text-sm text-gray-400 mt-1\">${escapeHtml(field.description)}</p>` : ''\n\n switch (field.type) {\n case 'string': {\n const isPassword = field.sensitive === true || field.format === 'password'\n const inputType = isPassword ? 'password' : field.format === 'email' ? 'email' : field.format === 'url' ? 'url' : 'text'\n const placeholder = field.placeholder ? ` placeholder=\"${escapeHtml(field.placeholder)}\"` : ''\n const min = field.minLength != null ? ` minlength=\"${field.minLength}\"` : ''\n const max = field.maxLength != null ? ` maxlength=\"${field.maxLength}\"` : ''\n return `\n<div class=\"field mb-4\">\n <label for=\"${id}\" class=\"block text-sm font-medium mb-1\">${labelHtml}</label>\n <input id=\"${id}\" name=\"${escapeHtml(key)}\" type=\"${inputType}\"\n class=\"w-full rounded border border-gray-700 bg-gray-800 px-3 py-2 text-sm\"\n value=\"${escapeHtml(String(value ?? ''))}\"${placeholder}${min}${max}${requiredAttr} />\n ${helpHtml}\n</div>`.trim()\n }\n case 'number': {\n const min = field.min != null ? ` min=\"${field.min}\"` : ''\n const max = field.max != null ? ` max=\"${field.max}\"` : ''\n const step = field.step != null ? ` step=\"${field.step}\"` : ''\n return `\n<div class=\"field mb-4\">\n <label for=\"${id}\" class=\"block text-sm font-medium mb-1\">${labelHtml}</label>\n <input id=\"${id}\" name=\"${escapeHtml(key)}\" type=\"number\"\n class=\"w-full rounded border border-gray-700 bg-gray-800 px-3 py-2 text-sm\"\n value=\"${value == null ? '' : escapeHtml(String(value))}\"${min}${max}${step}${requiredAttr} />\n ${helpHtml}\n</div>`.trim()\n }\n case 'boolean': {\n const checked = value === true ? ' checked' : ''\n return `\n<div class=\"field mb-4\">\n <label class=\"flex items-center gap-2 text-sm font-medium\">\n <input name=\"${escapeHtml(key)}\" type=\"checkbox\" class=\"rounded\"${checked} />\n ${labelHtml}\n </label>\n ${helpHtml}\n</div>`.trim()\n }\n case 'select': {\n const optionsHtml = field.options\n .map((o) => {\n const opt = typeof o === 'string' ? { value: o, label: o } : o\n const selected = opt.value === value ? ' selected' : ''\n return `<option value=\"${escapeHtml(opt.value)}\"${selected}>${escapeHtml(opt.label)}</option>`\n })\n .join('')\n return `\n<div class=\"field mb-4\">\n <label for=\"${id}\" class=\"block text-sm font-medium mb-1\">${labelHtml}</label>\n <select id=\"${id}\" name=\"${escapeHtml(key)}\"\n class=\"w-full rounded border border-gray-700 bg-gray-800 px-3 py-2 text-sm\"${requiredAttr}>\n ${optionsHtml}\n </select>\n ${helpHtml}\n</div>`.trim()\n }\n }\n}\n\n// ── FormData → settings ──────────────────────────────────────────────────────\n\n/**\n * Coerce FormData entries into typed settings per the schema. Notably:\n * - Unchecked checkboxes are omitted by the browser; we coalesce to `false`.\n * - Numbers parse via `Number()` and fall back to the field's default if invalid.\n * - Strings preserve empty string (NOT default) so an admin can intentionally clear.\n */\nexport function parseFormDataToSettings(schema: ConfigSchema, form: FormData): Record<string, unknown> {\n const result: Record<string, unknown> = {}\n for (const { key, field } of parseConfigSchema(schema)) {\n switch (field.type) {\n case 'string': {\n const raw = form.get(key)\n result[key] = raw == null ? field.default ?? '' : String(raw)\n break\n }\n case 'number': {\n const raw = form.get(key)\n if (raw == null || raw === '') {\n result[key] = field.default\n } else {\n const n = Number(raw)\n result[key] = Number.isFinite(n) ? n : field.default\n }\n break\n }\n case 'boolean': {\n // Unchecked checkbox → not present in FormData → false.\n result[key] = form.get(key) != null\n break\n }\n case 'select': {\n const raw = form.get(key)\n result[key] = raw == null ? field.default ?? '' : String(raw)\n break\n }\n }\n }\n return result\n}\n\n// ── Defaults ─────────────────────────────────────────────────────────────────\n\n/** Fill missing keys with field defaults. Existing keys (incl. `false`/`0`/'') win. */\nexport function applySchemaDefaults<S extends ConfigSchema>(\n schema: S,\n stored: Record<string, unknown>\n): Record<string, unknown> {\n const result: Record<string, unknown> = { ...stored }\n for (const { key, field } of parseConfigSchema(schema)) {\n if (result[key] === undefined) {\n const def = (field as { default?: unknown }).default\n if (def !== undefined) result[key] = def\n }\n }\n return result\n}\n","/**\n * In-memory registry of registered plugin definitions, indexed by id.\n *\n * Populated by `registerPlugins()` at app construction. The admin settings\n * route uses it to look up a plugin's `configSchema` so the schema-driven\n * settings form can be auto-rendered without per-plugin glue code.\n *\n * Read by the admin layer; written ONLY by registerPlugins.\n */\n\nimport type { RegisterablePlugin } from '../plugins/sdk/register-plugins'\n\nlet registry: ReadonlyMap<string, RegisterablePlugin> = new Map()\n\nexport function setPluginDefinitions(plugins: ReadonlyArray<RegisterablePlugin>): void {\n const next = new Map<string, RegisterablePlugin>()\n for (const p of plugins) next.set(p.id, p)\n registry = next\n}\n\nexport function getPluginDefinition(id: string): RegisterablePlugin | undefined {\n return registry.get(id)\n}\n\nexport function getAllPluginDefinitions(): ReadonlyArray<RegisterablePlugin> {\n return Array.from(registry.values())\n}\n\nexport function resetPluginDefinitions(): void {\n registry = new Map()\n}\n"]}
|