@objectstack/service-settings 11.0.0 → 11.2.0

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/crypto-adapter.ts","../src/settings-service.types.ts","../src/visibility-eval.ts","../src/settings-service.ts","../src/local-crypto-provider.ts","../src/settings-routes.ts","../src/manifest.ts","../src/manifests/auth.manifest.ts","../src/manifests/mail.manifest.ts","../src/manifests/branding.manifest.ts","../src/manifests/feature-flags.manifest.ts","../src/manifests/storage.manifest.ts","../src/manifests/ai.manifest.ts","../src/manifests/knowledge.manifest.ts","../src/manifests/localization.manifest.ts","../src/manifests/company.manifest.ts","../src/manifests/index.ts","../src/translations/en.ts","../src/translations/zh-CN.ts","../src/translations/ja-JP.ts","../src/translations/es-ES.ts","../src/translations/index.ts","../src/settings-service-plugin.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Public entrypoint for `@objectstack/service-settings`.\n * See ADR-0007 and `README.md`.\n */\n\nexport { SettingsService } from './settings-service.js';\nexport {\n type CryptoAdapter,\n NoopCryptoAdapter,\n} from './crypto-adapter.js';\n// Default, KMS-free ICryptoProvider. AES-256-GCM keyed off `OS_SECRET_KEY`\n// (production) or a persisted dev key; fails loud in production rather than\n// silently minting an ephemeral key. Hosts swap in a KMS/Vault provider for\n// managed custody. Exported so other subsystems (e.g. the runtime-UI\n// datasource secret binder) can reuse the same wrapping. `InMemoryCryptoProvider`\n// remains a deprecated alias for backward compatibility.\nexport {\n LocalCryptoProvider,\n InMemoryCryptoProvider,\n type LocalCryptoProviderOptions,\n type CryptoMode,\n type KeySource,\n} from './local-crypto-provider.js';\nexport {\n type SettingsActionHandler,\n type SettingsAuditSink,\n type SettingsContext,\n type SettingsEngine,\n type SettingsRow,\n type SettingsServiceOptions,\n envKeyOf,\n SettingsLockedError,\n SettingsValidationError,\n UnknownKeyError,\n UnknownNamespaceError,\n} from './settings-service.types.js';\nexport {\n evaluateVisibility,\n referencedKeys,\n VisibilityParseError,\n} from './visibility-eval.js';\nexport {\n SettingsServicePlugin,\n type SettingsServicePluginOptions,\n} from './settings-service-plugin.js';\nexport {\n registerSettingsRoutes,\n type SettingsRoutesOptions,\n} from './settings-routes.js';\nexport {\n settingsObjects,\n settingsPluginManifestHeader,\n SETTINGS_PLUGIN_ID,\n SETTINGS_PLUGIN_VERSION,\n} from './manifest.js';\n\n// Reference manifests (mail / branding / feature flags) and the\n// convenience aggregate. Hosts can pass `builtinSettingsManifests`\n// directly to `new SettingsServicePlugin({ manifests })`.\nexport {\n builtinSettingsManifests,\n brandingSettingsManifest,\n featureFlagsSettingsManifest,\n mailSettingsManifest,\n mailTestActionHandler,\n storageSettingsManifest,\n storageTestActionHandler,\n} from './manifests/index.js';\n\n// Re-export the spec types for convenience so plugin authors only need\n// one import.\nexport type {\n SettingsManifest,\n ResolvedSettingValue,\n SettingsNamespacePayload,\n SettingsActionResult,\n SpecifierScope,\n} from '@objectstack/spec/system';\n\n// Built-in translations (en / zh-CN / ja-JP) for the reference manifests.\n// Hosts merge `settingsBuiltinTranslations` into their i18next resource tree\n// so SettingsView resolves labels via `<ns>.settings.<namespace>.…`.\nexport {\n settingsBuiltinTranslations,\n en as settingsTranslationsEn,\n zhCN as settingsTranslationsZhCN,\n jaJP as settingsTranslationsJaJP,\n} from './translations/index.js';\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Pluggable adapter for at-rest encryption of `Specifier.encrypted: true`\n * values. The default {@link NoopCryptoAdapter} provides a transparent\n * base64 wrapping suitable for development and tests; production\n * deployments MUST inject a real KMS-backed adapter.\n *\n * encrypt/decrypt are async to leave room for KMS round-trips.\n */\nexport interface CryptoAdapter {\n /** Returns the ciphertext blob to store in `sys_setting.value_enc`. */\n encrypt(plaintext: string, ctx: { namespace: string; key: string }): Promise<string>;\n /** Returns the plaintext used by the resolver. */\n decrypt(ciphertext: string, ctx: { namespace: string; key: string }): Promise<string>;\n /**\n * Stable, short, non-reversible digest used for audit-log entries so\n * operators can correlate value changes without leaking secrets.\n */\n digest(plaintext: string): string;\n}\n\n/**\n * Development / test default. Base64-wraps the plaintext so the column\n * isn't a literal mirror but provides no real confidentiality.\n *\n * Operators are expected to override this via\n * `SettingsServicePluginOptions.crypto`.\n */\nexport class NoopCryptoAdapter implements CryptoAdapter {\n async encrypt(plaintext: string): Promise<string> {\n return 'b64:' + Buffer.from(plaintext, 'utf8').toString('base64');\n }\n async decrypt(ciphertext: string): Promise<string> {\n if (!ciphertext.startsWith('b64:')) {\n // Tolerate legacy plaintext rows during the dev rollout.\n return ciphertext;\n }\n return Buffer.from(ciphertext.slice(4), 'base64').toString('utf8');\n }\n digest(plaintext: string): string {\n // FNV-1a 32-bit — short, stable, non-cryptographic. Audit-only.\n let h = 0x811c9dc5;\n for (let i = 0; i < plaintext.length; i++) {\n h ^= plaintext.charCodeAt(i);\n h = (h + ((h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24))) >>> 0;\n }\n return 'fnv32:' + h.toString(16).padStart(8, '0');\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * SettingsService — the runtime implementation of ADR-0007.\n *\n * Responsibilities:\n * - Maintain an in-memory registry of `SettingsManifest` instances.\n * - Read/write values from the shared `sys_setting` K/V table via the\n * `objectql` data engine, with an in-memory fallback so the service\n * is usable before a real persistence layer is wired up (e.g. unit\n * tests, bootstrap, control-plane mock).\n * - Resolve effective values with `OS_* env > Tenant > User > Default`\n * precedence and tag every value with provenance.\n * - Encrypt-at-rest for `encrypted: true` specifiers using a pluggable\n * {@link CryptoAdapter}.\n * - Emit `sys_audit_log` rows for every successful write (encrypted\n * values are masked).\n * - Dispatch `runAction` for `action_button` specifiers — used by\n * \"Test connection\" / \"Send test email\" etc.\n *\n * The service is intentionally framework-agnostic: it doesn't import\n * the HTTP server, the plugin context, or the audit object schema. The\n * plugin wires those pieces up.\n */\n\nimport type { SettingsActionResult, SpecifierScope } from '@objectstack/spec/system';\nimport { type CryptoAdapter } from './crypto-adapter.js';\n\n/** Caller identity used by the resolver and audit log. */\nexport interface SettingsContext {\n /** Calling user id, when known. Required for `scope: 'user'` reads. */\n userId?: string;\n /** Tenant / project id. Reserved for multi-tenant deployments. */\n tenantId?: string;\n /** Permissions held by the caller (used by REST authz). */\n permissions?: string[];\n /** Source IP / request id for audit correlation. */\n requestId?: string;\n}\n\n/** Storage row shape used by both the engine and the in-memory store. */\nexport interface SettingsRow {\n namespace: string;\n key: string;\n scope: SpecifierScope;\n user_id: string | null;\n value: unknown | null;\n value_enc: string | null;\n encrypted: boolean;\n /**\n * When true, lower-scope rows for the same (namespace, key) are\n * read-only — the resolver still returns this row's value and the\n * mutation API throws `SettingsLockedError`. Only meaningful on\n * upper-scope rows (`global`, `tenant`). (Phase 2)\n */\n locked?: boolean;\n /** Human-readable reason the lock was applied (UI tooltip). */\n locked_reason?: string | null;\n updated_at?: string;\n updated_by?: string | null;\n}\n\n/**\n * Minimal data-engine surface used by the SettingsService. Mirrors the\n * methods we actually call so we can stub it cleanly in tests without\n * pulling the whole `IDataEngine`.\n */\nexport interface SettingsEngine {\n find(\n objectName: string,\n opts: { where?: Record<string, unknown>; limit?: number; bypassTenantAudit?: boolean },\n ): Promise<any[]>;\n insert(\n objectName: string,\n data: Record<string, unknown>,\n opts?: { bypassTenantAudit?: boolean },\n ): Promise<any>;\n update(\n objectName: string,\n opts: {\n where: Record<string, unknown>;\n data: Record<string, unknown>;\n bypassTenantAudit?: boolean;\n },\n ): Promise<any>;\n delete?(objectName: string, opts: { where: Record<string, unknown> }): Promise<any>;\n}\n\n/** Optional audit hook — service-settings won't crash if absent. */\nexport interface SettingsAuditSink {\n record(entry: {\n namespace: string;\n key: string;\n scope: SpecifierScope;\n userId?: string;\n actor?: string;\n action: 'set' | 'reset';\n valueDigest: string;\n encrypted: boolean;\n requestId?: string;\n }): Promise<void> | void;\n}\n\n/**\n * Persistence hook for the `sys_secret` object — used by the secret\n * split introduced in Phase 3. When provided, `SettingsService` writes\n * encrypted specifier values via `ICryptoProvider` into `sys_secret`\n * and stores only the handle id in `sys_setting.value_enc`. When\n * absent, the legacy inline `crypto.encrypt → value_enc` path is used.\n */\nexport interface SettingsSecretStore {\n /** Insert a new secret row; returns the row id (handle id). */\n insert(row: {\n id: string;\n namespace: string;\n key: string;\n kms_key_id: string;\n alg: string;\n version: number;\n ciphertext: string;\n }): Promise<{ id: string }>;\n /** Look up the latest ciphertext for a handle id; null when missing. */\n get(id: string): Promise<{\n id: string;\n namespace: string;\n key: string;\n kms_key_id: string;\n alg: string;\n version: number;\n ciphertext: string;\n } | null>;\n /** Replace an existing secret row (used by rotateKey). */\n update(id: string, patch: {\n kms_key_id?: string;\n alg?: string;\n version?: number;\n ciphertext?: string;\n }): Promise<void>;\n}\n\n/**\n * Append-only writer for the `sys_setting_audit` object — Phase 3\n * audit trail. Distinct from `SettingsAuditSink` (which still writes\n * to the generic `sys_audit_log`) so audit consumers can subscribe\n * to settings activity without scanning the firehose.\n */\nexport interface SettingsAuditWriter {\n write(entry: {\n namespace: string;\n key: string;\n scope: SpecifierScope;\n action: 'set' | 'reset' | 'lock' | 'unlock' | 'rotate';\n source?: 'ui' | 'api' | 'migration' | 'import' | 'system';\n actorId?: string;\n oldHash?: string | null;\n newHash?: string | null;\n encrypted: boolean;\n requestId?: string;\n reason?: string;\n }): Promise<void> | void;\n}\n\n/** Action handler signature for `Specifier.type === 'action_button'`. */\nexport type SettingsActionHandler = (input: {\n namespace: string;\n actionId: string;\n values: Record<string, unknown>;\n payload?: unknown;\n ctx: SettingsContext;\n}) => Promise<SettingsActionResult> | SettingsActionResult;\n\nexport interface SettingsServiceOptions {\n /** Persistence engine. When undefined, an in-memory store is used. */\n engine?: SettingsEngine;\n /** Crypto adapter for `encrypted` values. Defaults to NoopCryptoAdapter. */\n crypto?: CryptoAdapter;\n /**\n * Phase 3 ICryptoProvider used together with `secretStore`. When both\n * are wired, encrypted writes flow to `sys_secret` and `value_enc`\n * holds the handle id. When omitted, the legacy inline `crypto`\n * adapter path remains in effect (back-compat).\n */\n cryptoProvider?: import('@objectstack/spec/contracts').ICryptoProvider;\n /** Phase 3 secret store backing the `sys_secret` object. */\n secretStore?: SettingsSecretStore;\n /** Audit sink. When undefined, writes still succeed but are not logged. */\n audit?: SettingsAuditSink;\n /** Phase 3 dedicated writer for `sys_setting_audit`. */\n auditWriter?: SettingsAuditWriter;\n /**\n * `process.env`-like map. Defaults to `process.env`. Injected so\n * unit tests can simulate locked values without polluting the host\n * environment.\n */\n env?: Record<string, string | undefined>;\n /** Object name backing the K/V store. Defaults to 'sys_setting'. */\n objectName?: string;\n}\n\n/**\n * Convert `(namespace, key)` to the ObjectStack-owned env var convention:\n * `OS_` prefix, uppercase, dots → underscores, hyphens → underscores.\n */\nexport function envKeyOf(namespace: string, key: string): string {\n const slug = `${namespace}_${key}`.replace(/[.-]/g, '_').toUpperCase();\n return `OS_${slug}`;\n}\n\n/** Thrown when a caller tries to write a value pinned by env. */\nexport class SettingsLockedError extends Error {\n readonly code = 'SETTINGS_LOCKED' as const;\n constructor(\n readonly namespace: string,\n readonly key: string,\n readonly reason = 'locked-by-env',\n ) {\n super(`Setting '${namespace}.${key}' is locked (${reason}).`);\n }\n}\n\n/** Thrown when the requested namespace has no registered manifest. */\nexport class UnknownNamespaceError extends Error {\n readonly code = 'SETTINGS_UNKNOWN_NAMESPACE' as const;\n constructor(readonly namespace: string) {\n super(`No settings manifest registered for namespace '${namespace}'.`);\n }\n}\n\n/** Thrown when a key isn't declared by the namespace's manifest. */\nexport class UnknownKeyError extends Error {\n readonly code = 'SETTINGS_UNKNOWN_KEY' as const;\n constructor(readonly namespace: string, readonly key: string) {\n super(`Key '${key}' is not declared in manifest '${namespace}'.`);\n }\n}\n\n/**\n * Thrown when a write would leave the namespace in an invalid state —\n * a `required` field that is visible under the post-write values is\n * empty (e.g. provider=cloudflare saved without an API key). The whole\n * batch is rejected; `fields` maps each offending key to a message the\n * UI can render inline.\n */\nexport class SettingsValidationError extends Error {\n readonly code = 'SETTINGS_VALIDATION' as const;\n constructor(\n readonly namespace: string,\n readonly fields: Record<string, string>,\n ) {\n super(\n `Settings for '${namespace}' are incomplete: ` +\n Object.entries(fields).map(([k, msg]) => `${k} — ${msg}`).join('; '),\n );\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Evaluator for the restricted visibility expressions used by settings\n * manifests, e.g. `\"${data.provider === 'cloudflare'}\"` or\n * `\"${data.embedder_provider && data.embedder_provider !== 'none'}\"`.\n *\n * The server needs these at save time so `setMany` can enforce `required`\n * only on fields that are actually visible for the current provider —\n * a half-filled Cloudflare form must be rejected, while OpenAI fields\n * stay irrelevant. The console UI evaluates the same strings client-side;\n * this is deliberately NOT a general JS evaluator, just the tiny grammar\n * the manifests use:\n *\n * orExpr := andExpr ('||' andExpr)*\n * andExpr := unary ('&&' unary)*\n * unary := '!' unary | comparison\n * compare := primary (('===' | '!==' | '==' | '!=') primary)?\n * primary := '(' orExpr ')' | string | number | true | false | null | data.<ident>\n *\n * Anything outside the grammar throws `VisibilityParseError`; callers\n * should treat that as \"cannot determine visibility\" and skip validation\n * for the field (lenient) rather than block the save.\n */\n\nexport class VisibilityParseError extends Error {\n constructor(expr: string, detail: string) {\n super(`Cannot parse visibility expression \"${expr}\": ${detail}`);\n this.name = 'VisibilityParseError';\n }\n}\n\ntype Token =\n | { kind: 'punct'; value: '(' | ')' | '!' | '&&' | '||' | '===' | '!==' | '==' | '!=' }\n | { kind: 'string'; value: string }\n | { kind: 'number'; value: number }\n | { kind: 'keyword'; value: boolean | null }\n | { kind: 'ref'; value: string };\n\n/**\n * Unwrap the manifest forms a `visible` field can take: a bare string,\n * a `${…}` template string, or a `{ dialect, source }` envelope.\n */\nexport function visibilitySource(visible: unknown): string | undefined {\n let src: string | undefined;\n if (typeof visible === 'string') src = visible;\n else if (visible && typeof visible === 'object' && typeof (visible as { source?: unknown }).source === 'string') {\n src = (visible as { source: string }).source;\n }\n if (src === undefined) return undefined;\n const trimmed = src.trim();\n if (trimmed.startsWith('${') && trimmed.endsWith('}')) return trimmed.slice(2, -1).trim();\n return trimmed;\n}\n\n/** `data.*` keys referenced by a visibility expression (regex-level scan). */\nexport function referencedKeys(visible: unknown): string[] {\n const src = visibilitySource(visible);\n if (!src) return [];\n return [...src.matchAll(/data\\.([A-Za-z_][A-Za-z0-9_]*)/g)].map((m) => m[1]);\n}\n\nfunction tokenize(expr: string): Token[] {\n const tokens: Token[] = [];\n let i = 0;\n while (i < expr.length) {\n const ch = expr[i];\n if (/\\s/.test(ch)) { i++; continue; }\n if (ch === '(' || ch === ')') { tokens.push({ kind: 'punct', value: ch }); i++; continue; }\n let matchedOp = false;\n for (const op of ['===', '!==', '==', '!=', '&&', '||'] as const) {\n if (expr.startsWith(op, i)) {\n tokens.push({ kind: 'punct', value: op });\n i += op.length;\n matchedOp = true;\n break;\n }\n }\n if (matchedOp) continue;\n if (ch === '!') { tokens.push({ kind: 'punct', value: '!' }); i++; continue; }\n if (ch === \"'\" || ch === '\"') {\n const quote = ch;\n let j = i + 1;\n let out = '';\n while (j < expr.length && expr[j] !== quote) {\n if (expr[j] === '\\\\' && j + 1 < expr.length) { out += expr[j + 1]; j += 2; }\n else { out += expr[j]; j++; }\n }\n if (j >= expr.length) throw new VisibilityParseError(expr, 'unterminated string');\n tokens.push({ kind: 'string', value: out });\n i = j + 1;\n continue;\n }\n if (/[0-9]/.test(ch)) {\n const m = /^[0-9]+(\\.[0-9]+)?/.exec(expr.slice(i))!;\n tokens.push({ kind: 'number', value: Number(m[0]) });\n i += m[0].length;\n continue;\n }\n if (/[A-Za-z_]/.test(ch)) {\n const m = /^[A-Za-z_][A-Za-z0-9_.]*/.exec(expr.slice(i))!;\n const word = m[0];\n if (word === 'true') tokens.push({ kind: 'keyword', value: true });\n else if (word === 'false') tokens.push({ kind: 'keyword', value: false });\n else if (word === 'null') tokens.push({ kind: 'keyword', value: null });\n else if (word.startsWith('data.')) {\n const key = word.slice('data.'.length);\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) throw new VisibilityParseError(expr, `unsupported reference \"${word}\"`);\n tokens.push({ kind: 'ref', value: key });\n } else throw new VisibilityParseError(expr, `unsupported identifier \"${word}\"`);\n i += word.length;\n continue;\n }\n throw new VisibilityParseError(expr, `unexpected character \"${ch}\"`);\n }\n return tokens;\n}\n\n/**\n * Evaluate a visibility expression against the merged form data.\n * Throws {@link VisibilityParseError} for anything outside the grammar.\n */\nexport function evaluateVisibility(visible: unknown, data: Record<string, unknown>): boolean {\n const src = visibilitySource(visible);\n if (!src) return true;\n const tokens = tokenize(src);\n let pos = 0;\n\n const peek = (): Token | undefined => tokens[pos];\n const eat = (value: string): boolean => {\n const t = tokens[pos];\n if (t?.kind === 'punct' && t.value === value) { pos++; return true; }\n return false;\n };\n\n function primary(): unknown {\n const t = peek();\n if (!t) throw new VisibilityParseError(src!, 'unexpected end of expression');\n if (t.kind === 'punct' && t.value === '(') {\n pos++;\n const v = orExpr();\n if (!eat(')')) throw new VisibilityParseError(src!, 'missing closing parenthesis');\n return v;\n }\n if (t.kind === 'string' || t.kind === 'number' || t.kind === 'keyword') { pos++; return t.value; }\n if (t.kind === 'ref') { pos++; return data[t.value]; }\n throw new VisibilityParseError(src!, `unexpected token`);\n }\n\n function comparison(): unknown {\n const left = primary();\n const t = peek();\n if (t?.kind === 'punct' && ['===', '!==', '==', '!='].includes(t.value)) {\n pos++;\n const right = primary();\n // Loose == / != are treated as strict — manifest values are\n // primitives written by hand; the distinction never matters here.\n return t.value === '===' || t.value === '==' ? left === right : left !== right;\n }\n return left;\n }\n\n function unary(): unknown {\n if (eat('!')) return !unary();\n return comparison();\n }\n\n function andExpr(): unknown {\n let v = unary();\n while (eat('&&')) {\n const r = unary();\n v = v && r;\n }\n return v;\n }\n\n function orExpr(): unknown {\n let v = andExpr();\n while (eat('||')) {\n const r = andExpr();\n v = v || r;\n }\n return v;\n }\n\n const result = orExpr();\n if (pos !== tokens.length) throw new VisibilityParseError(src, 'trailing tokens');\n return Boolean(result);\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type {\n SettingsManifest,\n ResolvedSettingValue,\n SettingsNamespacePayload,\n SettingsActionResult,\n SpecifierScope,\n SettingsChangeEvent,\n SettingsChangeHandler,\n SettingsUnsubscribe,\n} from '@objectstack/spec/system';\nimport {\n type CryptoAdapter,\n NoopCryptoAdapter,\n} from './crypto-adapter.js';\nimport {\n type SettingsActionHandler,\n type SettingsAuditSink,\n type SettingsContext,\n type SettingsEngine,\n type SettingsRow,\n type SettingsServiceOptions,\n envKeyOf,\n SettingsLockedError,\n SettingsValidationError,\n UnknownKeyError,\n UnknownNamespaceError,\n} from './settings-service.types.js';\nimport { evaluateVisibility, referencedKeys } from './visibility-eval.js';\n\nconst DEFAULT_OBJECT = 'sys_setting';\n\n/**\n * Value-bearing specifier types — drives which entries we expect to\n * find in the K/V store. Keeps the resolver in sync with the spec\n * without importing the (large) Zod enum at runtime.\n */\nconst LAYOUT_ONLY_TYPES = new Set([\n 'group',\n 'info_banner',\n 'child_pane',\n 'title_value',\n 'action_button',\n]);\n\ninterface RegisteredManifest {\n manifest: SettingsManifest;\n /** Resolved specifier scopes for fast lookup. */\n scopes: Map<string, SpecifierScope>;\n /** Specifiers marked encrypted (or implicit for `password`). */\n encryptedKeys: Set<string>;\n /** Default values from the manifest, keyed by specifier key. */\n defaults: Map<string, unknown>;\n /** Action handlers registered alongside this manifest. */\n actions: Map<string, SettingsActionHandler>;\n}\n\n/**\n * Concrete SettingsService. See `src/settings-service.types.ts` for\n * the supporting types and `README.md` for the high-level contract.\n */\nexport class SettingsService {\n private engine?: SettingsEngine;\n private readonly crypto: CryptoAdapter;\n private cryptoProvider?: import('@objectstack/spec/contracts').ICryptoProvider;\n private secretStore?: import('./settings-service.types.js').SettingsSecretStore;\n private audit?: SettingsAuditSink;\n private auditWriter?: import('./settings-service.types.js').SettingsAuditWriter;\n private readonly env: Record<string, string | undefined>;\n private readonly objectName: string;\n private readonly registry = new Map<string, RegisteredManifest>();\n /** In-memory fallback when no engine is wired. */\n private readonly memory: SettingsRow[] = [];\n /** Change subscribers, optionally scoped to a namespace. */\n private readonly subscribers = new Set<{\n ns?: string;\n handler: SettingsChangeHandler;\n }>();\n\n constructor(opts: SettingsServiceOptions = {}) {\n this.engine = opts.engine;\n this.crypto = opts.crypto ?? new NoopCryptoAdapter();\n this.cryptoProvider = opts.cryptoProvider;\n this.secretStore = opts.secretStore;\n this.audit = opts.audit;\n this.auditWriter = opts.auditWriter;\n this.env = opts.env ?? (typeof process !== 'undefined' ? process.env : {});\n this.objectName = opts.objectName ?? DEFAULT_OBJECT;\n }\n\n /**\n * Late-bind a data engine and (optionally) an audit sink. Plugins\n * call this from `kernel:ready` once `objectql` is wired so the\n * SettingsService swaps from its in-memory fallback to the real\n * `sys_setting` table without re-registering the service.\n */\n bindEngine(\n engine: SettingsEngine,\n audit?: SettingsAuditSink,\n extras?: {\n secretStore?: import('./settings-service.types.js').SettingsSecretStore;\n auditWriter?: import('./settings-service.types.js').SettingsAuditWriter;\n cryptoProvider?: import('@objectstack/spec/contracts').ICryptoProvider;\n },\n ): void {\n this.engine = engine;\n if (audit) this.audit = audit;\n if (extras?.secretStore) this.secretStore = extras.secretStore;\n if (extras?.auditWriter) this.auditWriter = extras.auditWriter;\n if (extras?.cryptoProvider) this.cryptoProvider = extras.cryptoProvider;\n\n // Notify subscribers that the persistent store is now available so\n // late-binders (e.g. AIServicePlugin's adapter rebuild on saved\n // provider settings) can re-fetch with real DB-backed values rather\n // than only the in-memory defaults that were visible at\n // `kernel:ready` ordering before the engine was wired.\n for (const ns of this.registry.keys()) {\n this.emitChange({\n namespace: ns,\n key: '*',\n scope: 'global',\n action: 'set',\n at: new Date().toISOString(),\n });\n }\n }\n\n /**\n * Cascade priority ranks for lock comparisons (lower = higher\n * precedence). env<global<tenant<user<default. A locked row at a\n * lower rank blocks writes at all higher ranks.\n */\n private scopeRank(scope: SpecifierScope | 'env' | 'default'): number {\n switch (scope) {\n case 'global': return 1;\n case 'tenant': return 2;\n case 'user': return 3;\n default: return 99;\n }\n }\n\n // ---------------------------------------------------------------------\n // Change events (Phase 1)\n // ---------------------------------------------------------------------\n\n /**\n * Subscribe to `settings:changed` events. When `namespace` is set the\n * handler only fires for that namespace, otherwise it fires for every\n * mutation across the service.\n *\n * Returns an idempotent unsubscribe handle — call it from the\n * consumer's shutdown hook to avoid leaks.\n */\n subscribe(\n namespace: string | undefined,\n handler: SettingsChangeHandler,\n ): SettingsUnsubscribe {\n const entry = { ns: namespace, handler };\n this.subscribers.add(entry);\n return () => {\n this.subscribers.delete(entry);\n };\n }\n\n /**\n * Dispatch a change event to all matching subscribers. Errors thrown\n * by a handler are swallowed to keep the bus crash-safe — handlers\n * are expected to enqueue async work themselves.\n */\n private emitChange(event: SettingsChangeEvent): void {\n if (this.subscribers.size === 0) return;\n for (const sub of this.subscribers) {\n if (sub.ns && sub.ns !== event.namespace) continue;\n try {\n sub.handler(event);\n } catch {\n // Swallow — never break the writer because a listener misbehaves.\n }\n }\n }\n\n // ---------------------------------------------------------------------\n // Manifest registry\n // ---------------------------------------------------------------------\n\n /** Register (or replace) a manifest. Idempotent. */\n registerManifest(manifest: SettingsManifest): void {\n const scopes = new Map<string, SpecifierScope>();\n const encryptedKeys = new Set<string>();\n const defaults = new Map<string, unknown>();\n const defaultScope = manifest.scope ?? 'tenant';\n for (const spec of manifest.specifiers) {\n if (!spec.key || LAYOUT_ONLY_TYPES.has(spec.type)) continue;\n scopes.set(spec.key, spec.scope ?? defaultScope);\n if (spec.encrypted || spec.type === 'password') encryptedKeys.add(spec.key);\n if (typeof spec.default !== 'undefined') defaults.set(spec.key, spec.default);\n }\n const prev = this.registry.get(manifest.namespace);\n const actions = prev?.actions ?? new Map<string, SettingsActionHandler>();\n this.registry.set(manifest.namespace, { manifest, scopes, encryptedKeys, defaults, actions });\n }\n\n /** Look up a manifest, or throw `UnknownNamespaceError`. */\n getManifest(namespace: string): SettingsManifest {\n const reg = this.registry.get(namespace);\n if (!reg) throw new UnknownNamespaceError(namespace);\n return reg.manifest;\n }\n\n /** List all registered manifests, optionally filtered by permission. */\n listManifests(ctx: SettingsContext = {}): SettingsManifest[] {\n const perms = new Set(ctx.permissions ?? []);\n const all = Array.from(this.registry.values()).map((r) => r.manifest);\n // Empty permissions ⇒ pass-through (server-side trust, e.g. boot tests).\n if (perms.size === 0) return all;\n return all.filter((m) => perms.has(m.readPermission ?? 'setup.access'));\n }\n\n /** Register a handler for an `action_button` declared in a manifest. */\n registerAction(namespace: string, actionId: string, handler: SettingsActionHandler): void {\n const reg = this.registry.get(namespace);\n if (!reg) throw new UnknownNamespaceError(namespace);\n reg.actions.set(actionId, handler);\n }\n\n // ---------------------------------------------------------------------\n // Resolver\n // ---------------------------------------------------------------------\n\n /** Resolve a single key. */\n async get<T = unknown>(\n namespace: string,\n key: string,\n ctx: SettingsContext = {},\n ): Promise<ResolvedSettingValue<T>> {\n const reg = this.registry.get(namespace);\n if (!reg) throw new UnknownNamespaceError(namespace);\n if (!reg.scopes.has(key)) throw new UnknownKeyError(namespace, key);\n\n // 1. OS_* env\n const envName = envKeyOf(namespace, key);\n const envRaw = this.env[envName];\n if (typeof envRaw === 'string') {\n const def = reg.defaults.get(key);\n const value = coerceEnvValue(envRaw, def);\n return {\n value: value as T,\n source: 'env',\n locked: true,\n lockedReason: `Set via env: ${envName}`,\n cascadeChain: [\n { scope: 'env', value, locked: true, lockedReason: `Set via env: ${envName}`, effective: true },\n ],\n };\n }\n\n const scope = reg.scopes.get(key)!;\n // For 'user' scope we pre-filter by user_id; for 'tenant' and 'global'\n // we load everything for the namespace and pick the right row below.\n const rows = await this.loadRows(namespace, scope === 'user' ? ctx.userId ?? null : null);\n\n // 2. cascade walk — OS_* env (handled above) > global > tenant > user > default\n //\n // Build the full chain in declared order so the UI can render\n // \"Inherited from Global / Locked by Global / Overrides tenant\"\n // badges. The first non-null entry wins as `source`.\n const chain: NonNullable<ResolvedSettingValue['cascadeChain']> = [];\n\n const globalRow = rows.find((r) => r.key === key && r.scope === 'global');\n if (globalRow) {\n const value = await this.materialiseRow(globalRow);\n chain.push({\n scope: 'global',\n value,\n locked: !!globalRow.locked,\n lockedReason: globalRow.locked_reason ?? undefined,\n });\n }\n\n if (scope === 'tenant' || scope === 'user') {\n const tenantRow = rows.find((r) => r.key === key && r.scope === 'tenant');\n if (tenantRow) {\n chain.push({\n scope: 'tenant',\n value: await this.materialiseRow(tenantRow),\n locked: !!tenantRow.locked,\n lockedReason: tenantRow.locked_reason ?? undefined,\n });\n }\n }\n\n if (scope === 'user') {\n const userRow = rows.find((r) => r.key === key && r.scope === 'user');\n if (userRow) {\n chain.push({\n scope: 'user',\n value: await this.materialiseRow(userRow),\n });\n }\n }\n\n const def = reg.defaults.get(key);\n chain.push({ scope: 'default', value: def ?? null });\n\n // Effective row: highest priority entry. Lock anywhere up the chain\n // locks the effective value (lower scopes can't shadow it).\n const lockedEntry = chain.find((e) => e.locked === true);\n const effective = chain.find((e) => e.value !== null && e.value !== undefined) ?? chain[chain.length - 1];\n effective.effective = true;\n\n return {\n value: effective.value as T,\n source: effective.scope as ResolvedSettingValue['source'],\n locked: !!lockedEntry,\n lockedReason: lockedEntry?.lockedReason,\n cascadeChain: chain,\n };\n }\n\n /** Resolve every value in a namespace + return the manifest. */\n async getNamespace(\n namespace: string,\n ctx: SettingsContext = {},\n ): Promise<SettingsNamespacePayload> {\n const reg = this.registry.get(namespace);\n if (!reg) throw new UnknownNamespaceError(namespace);\n\n const values: Record<string, ResolvedSettingValue> = {};\n for (const [key] of reg.scopes) {\n values[key] = await this.get(namespace, key, ctx);\n }\n return { manifest: reg.manifest, values };\n }\n\n // ---------------------------------------------------------------------\n // Reactive client (Phase 1)\n // ---------------------------------------------------------------------\n\n /**\n * Build a reactive `ISettingsClient` for a namespace.\n *\n * The client maintains an internal snapshot of the resolved values,\n * refreshing on every `settings:changed` event for the namespace.\n * Consumers call `current` / `get(key)` for synchronous reads and\n * register handlers via `onChange()`.\n *\n * `schema` is optional. When supplied, the snapshot is parsed (and\n * defaulted) through the Zod schema on each refresh — this gives\n * plugins strong types and runtime validation in one call. When\n * absent, raw resolved values flow through unchanged (used by the\n * dynamic console UI which validates per-field).\n */\n async createClient<T extends Record<string, unknown> = Record<string, unknown>>(\n namespace: string,\n opts: {\n ctx?: SettingsContext;\n parse?: (raw: Record<string, unknown>) => T;\n } = {},\n ): Promise<{\n readonly namespace: string;\n readonly current: T;\n get<K extends keyof T>(key: K): T[K];\n onChange(handler: SettingsChangeHandler): SettingsUnsubscribe;\n refresh(): Promise<void>;\n dispose(): void;\n }> {\n const ctx = opts.ctx ?? {};\n let snapshot: T = await this.snapshotOf<T>(namespace, ctx, opts.parse);\n\n const off = this.subscribe(namespace, () => {\n // Fire-and-forget refresh; new readers see the latest snapshot.\n void this.snapshotOf<T>(namespace, ctx, opts.parse).then((next) => {\n snapshot = next;\n });\n });\n\n return {\n namespace,\n get current() {\n return snapshot;\n },\n get<K extends keyof T>(key: K): T[K] {\n return snapshot[key];\n },\n onChange: (handler) => this.subscribe(namespace, handler),\n refresh: async () => {\n snapshot = await this.snapshotOf<T>(namespace, ctx, opts.parse);\n },\n dispose: off,\n };\n }\n\n private async snapshotOf<T>(\n namespace: string,\n ctx: SettingsContext,\n parse?: (raw: Record<string, unknown>) => T,\n ): Promise<T> {\n const payload = await this.getNamespace(namespace, ctx);\n const raw: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(payload.values)) raw[k] = v.value;\n return parse ? parse(raw) : (raw as T);\n }\n\n // ---------------------------------------------------------------------\n // Mutations\n // ---------------------------------------------------------------------\n\n /** Persist a single key. Throws SettingsLockedError when env-locked. */\n async set(\n namespace: string,\n key: string,\n value: unknown,\n ctx: SettingsContext = {},\n ): Promise<ResolvedSettingValue> {\n return (await this.setMany(namespace, { [key]: value }, ctx))[key];\n }\n\n /** Persist multiple keys atomically (best-effort). */\n async setMany(\n namespace: string,\n patch: Record<string, unknown>,\n ctx: SettingsContext = {},\n ): Promise<Record<string, ResolvedSettingValue>> {\n const reg = this.registry.get(namespace);\n if (!reg) throw new UnknownNamespaceError(namespace);\n\n // Pre-flight: reject the whole batch if any key is locked or unknown.\n for (const key of Object.keys(patch)) {\n if (!reg.scopes.has(key)) throw new UnknownKeyError(namespace, key);\n const envRaw = this.env[envKeyOf(namespace, key)];\n if (typeof envRaw === 'string') throw new SettingsLockedError(namespace, key);\n\n // Phase 2 lock: a row at an upper scope marked locked=true\n // refuses writes at this (lower) scope. Writing AT the same\n // scope as the lock is still permitted (i.e. a platform admin\n // can edit a globally-locked value; a tenant admin cannot).\n const scope = reg.scopes.get(key)!;\n const rows = await this.loadRows(namespace, scope === 'user' ? ctx.userId ?? null : null);\n const upper = rows.find(\n (r) =>\n r.key === key &&\n r.locked === true &&\n this.scopeRank(r.scope) < this.scopeRank(scope),\n );\n if (upper) {\n throw new SettingsLockedError(namespace, key, `locked-by-${upper.scope}`);\n }\n }\n\n // Reject writes that would leave the namespace in a known-broken\n // state (visible required field empty / pattern mismatch). See\n // validatePatch for the exact semantics.\n await this.validatePatch(namespace, patch, ctx);\n\n for (const [key, rawValue] of Object.entries(patch)) {\n const scope = reg.scopes.get(key)!;\n // global rows are platform-wide (tenant_id=null, user_id=null);\n // user rows pin to ctx.userId; tenant rows leave user_id null and\n // let the engine's tenant scoping fill in tenant_id from ctx.\n const userId = scope === 'user' ? ctx.userId ?? null : null;\n const isEncrypted = reg.encryptedKeys.has(key);\n const isNull = rawValue === null || typeof rawValue === 'undefined';\n\n let storedValue: unknown | null = null;\n let storedEnc: string | null = null;\n let digest = '';\n\n if (!isNull) {\n if (isEncrypted) {\n const plain = typeof rawValue === 'string' ? rawValue : JSON.stringify(rawValue);\n // Phase 3 split: when a sys_secret store + ICryptoProvider are\n // wired, persist the ciphertext in sys_secret and keep the\n // handle id in sys_setting.value_enc. Otherwise fall back to\n // the legacy inline crypto adapter path for back-compat.\n if (this.cryptoProvider && this.secretStore) {\n const handle = await this.cryptoProvider.encrypt(plain, {\n namespace,\n key,\n tenantId: ctx.tenantId,\n });\n await this.secretStore.insert({\n id: handle.id,\n namespace,\n key,\n kms_key_id: handle.kmsKeyId,\n alg: handle.alg,\n version: handle.version,\n ciphertext: handle.ciphertext,\n });\n storedEnc = handle.id;\n digest = this.cryptoProvider.digest(plain);\n } else {\n storedEnc = await this.crypto.encrypt(plain, { namespace, key });\n digest = this.crypto.digest(plain);\n }\n } else {\n storedValue = rawValue;\n digest = this.crypto.digest(stableStringify(rawValue));\n }\n }\n\n await this.upsertRow({\n namespace,\n key,\n scope,\n user_id: userId,\n value: storedValue,\n value_enc: storedEnc,\n encrypted: isEncrypted,\n updated_at: new Date().toISOString(),\n updated_by: ctx.userId ?? null,\n });\n\n if (this.audit) {\n await this.audit.record({\n namespace,\n key,\n scope,\n userId: ctx.userId,\n action: isNull ? 'reset' : 'set',\n valueDigest: isEncrypted ? '<encrypted:' + digest + '>' : digest,\n encrypted: isEncrypted,\n requestId: ctx.requestId,\n });\n }\n\n if (this.auditWriter) {\n try {\n await this.auditWriter.write({\n namespace,\n key,\n scope,\n action: isNull ? 'reset' : 'set',\n source: 'api',\n actorId: ctx.userId,\n oldHash: null,\n newHash: isNull ? null : digest,\n encrypted: isEncrypted,\n requestId: ctx.requestId,\n });\n } catch {\n // never fail a write because the audit table is unhappy.\n }\n }\n\n this.emitChange({\n namespace,\n key,\n scope,\n action: isNull ? 'reset' : 'set',\n at: new Date().toISOString(),\n });\n }\n\n // Re-resolve so callers see the post-write effective values.\n const out: Record<string, ResolvedSettingValue> = {};\n for (const key of Object.keys(patch)) {\n out[key] = await this.get(namespace, key, ctx);\n }\n return out;\n }\n\n /**\n * Save-time validation for `setMany`, fulfilling the spec promise that\n * `required` is enforced server-side and hidden specifiers are not\n * validated. Semantics, tuned to reject broken configs without\n * breaking unrelated single-key writes:\n *\n * - The post-write value map is computed (current values overlaid\n * with the patch; `null` patch entries fall back to the default).\n * - A specifier is checked only when the patch TOUCHES it — its own\n * key is in the patch, or a key its `visible` expression references\n * is (switching provider must validate that provider's fields).\n * - `required` + visible + empty → rejected.\n * - `pattern` (text fields) + non-empty value that mismatches → rejected.\n * - All-null patches (namespace reset) and unparseable visibility\n * expressions skip validation rather than block the write.\n */\n private async validatePatch(\n namespace: string,\n patch: Record<string, unknown>,\n ctx: SettingsContext,\n ): Promise<void> {\n const reg = this.registry.get(namespace);\n if (!reg) return;\n const entries = Object.entries(patch);\n if (entries.length === 0) return;\n // An all-null patch is a reset — clearing values is never blocked.\n if (entries.every(([, v]) => v === null || typeof v === 'undefined')) return;\n\n // Post-write value map: resolved values overlaid with the patch.\n const data: Record<string, unknown> = {};\n for (const [key] of reg.scopes) {\n data[key] = (await this.get(namespace, key, ctx)).value;\n }\n for (const [key, value] of entries) {\n data[key] = value === null || typeof value === 'undefined'\n ? reg.defaults.get(key) ?? null\n : value;\n }\n\n const patchKeys = new Set(Object.keys(patch));\n const errors: Record<string, string> = {};\n\n for (const spec of (reg.manifest.specifiers ?? []) as Array<Record<string, unknown>>) {\n const key = spec.key as string | undefined;\n const type = String(spec.type ?? '');\n if (!key || LAYOUT_ONLY_TYPES.has(type)) continue;\n\n let visible = true;\n let deps: string[] = [];\n if (typeof spec.visible !== 'undefined') {\n try {\n visible = evaluateVisibility(spec.visible, data);\n deps = referencedKeys(spec.visible);\n } catch {\n continue; // can't determine visibility — stay lenient\n }\n }\n if (!visible) continue;\n if (!patchKeys.has(key) && !deps.some((d) => patchKeys.has(d))) continue;\n\n const value = data[key];\n const label = typeof spec.label === 'string' ? spec.label : key;\n const empty =\n value === null || typeof value === 'undefined' ||\n (typeof value === 'string' && value.trim() === '');\n\n if (spec.required === true && empty) {\n errors[key] = `${label} is required for this configuration.`;\n continue;\n }\n if (!empty && typeof spec.pattern === 'string' && typeof value === 'string') {\n let re: RegExp | undefined;\n try {\n re = new RegExp(spec.pattern);\n } catch {\n re = undefined; // invalid manifest pattern — don't block writes\n }\n if (re && !re.test(value)) {\n const hint = typeof spec.description === 'string' ? ` ${spec.description}` : '';\n errors[key] = `${label} does not match the expected format.${hint}`;\n }\n }\n }\n\n if (Object.keys(errors).length > 0) {\n throw new SettingsValidationError(namespace, errors);\n }\n }\n\n /**\n * Clear every persisted row in a namespace so values fall back to\n * env/defaults. Env-locked keys are untouched (env wins over rows\n * anyway and refuses writes). Persisted rows are nulled rather than\n * deleted so the audit trail records the reset per key.\n *\n * Returns the number of cleared keys.\n */\n async resetNamespace(namespace: string, ctx: SettingsContext = {}): Promise<number> {\n const payload = await this.getNamespace(namespace, ctx);\n const patch: Record<string, null> = {};\n for (const [key, v] of Object.entries(payload.values)) {\n if (v.source === 'global' || v.source === 'tenant' || v.source === 'user') {\n patch[key] = null;\n }\n }\n const keys = Object.keys(patch);\n if (keys.length > 0) await this.setMany(namespace, patch, ctx);\n return keys.length;\n }\n\n /** Invoke a declared action (test connection, rotate, …). */\n async runAction(\n namespace: string,\n actionId: string,\n payload: unknown,\n ctx: SettingsContext = {},\n ): Promise<SettingsActionResult> {\n const reg = this.registry.get(namespace);\n if (!reg) throw new UnknownNamespaceError(namespace);\n const handler = reg.actions.get(actionId);\n if (!handler) {\n // Built-in fallback: every namespace gets a `reset` action that\n // clears persisted rows (back to env/defaults). Plugins may\n // override it via registerAction for richer behaviour (e.g. the\n // AI plugin re-runs env adapter detection after the clear).\n if (actionId === 'reset') {\n const cleared = await this.resetNamespace(namespace, ctx);\n return {\n ok: true,\n severity: 'info',\n message: cleared > 0\n ? `Cleared ${cleared} saved value(s); environment/default configuration is back in effect.`\n : 'No saved values to clear — already using environment/default configuration.',\n };\n }\n return {\n ok: false,\n severity: 'error',\n message: `No handler registered for action '${actionId}' in '${namespace}'.`,\n };\n }\n const values: Record<string, unknown> = {};\n for (const [key] of reg.scopes) {\n values[key] = (await this.get(namespace, key, ctx)).value;\n }\n try {\n return await handler({ namespace, actionId, values, payload, ctx });\n } catch (err: any) {\n return {\n ok: false,\n severity: 'error',\n message: err?.message ?? 'Action handler threw.',\n };\n }\n }\n\n // ---------------------------------------------------------------------\n // Persistence helpers (engine or in-memory)\n // ---------------------------------------------------------------------\n\n private async loadRows(namespace: string, userId: string | null): Promise<SettingsRow[]> {\n if (this.engine) {\n const where: Record<string, unknown> = { namespace };\n if (userId !== null) where.user_id = userId;\n // Settings rows include platform-wide (`global` scope, tenant_id=null)\n // entries; bypass the tenant-scoping audit warning so loads work\n // uniformly across global/tenant/user without log noise. Per-tenant\n // isolation for `tenant`-scope rows is still enforced by the engine\n // once an ExecutionContext.tenantId is plumbed through (Phase 2+).\n const rows = await this.engine.find(this.objectName, {\n where,\n bypassTenantAudit: true,\n } as any);\n return rows.map((r) => ({\n namespace: r.namespace,\n key: r.key,\n scope: r.scope as SpecifierScope,\n user_id: r.user_id ?? null,\n value: r.value ?? null,\n value_enc: r.value_enc ?? null,\n encrypted: Boolean(r.encrypted),\n locked: Boolean(r.locked),\n locked_reason: r.locked_reason ?? null,\n updated_at: r.updated_at,\n updated_by: r.updated_by ?? null,\n }));\n }\n return this.memory.filter(\n (r) =>\n r.namespace === namespace &&\n (userId === null || r.user_id === userId || r.scope === 'tenant' || r.scope === 'global'),\n );\n }\n\n private async upsertRow(row: SettingsRow): Promise<void> {\n if (this.engine) {\n const where: Record<string, unknown> = {\n namespace: row.namespace,\n key: row.key,\n scope: row.scope,\n user_id: row.user_id ?? null,\n };\n // global rows are platform-wide — bypass the tenant audit warning\n // (we intentionally write tenant_id=null). tenant/user rows still\n // benefit from the warning when ctx.tenantId is missing.\n const bypass = row.scope === 'global' ? { bypassTenantAudit: true } : {};\n const existing = await this.engine.find(this.objectName, {\n where,\n limit: 1,\n ...bypass,\n } as any);\n if (existing[0]) {\n await this.engine.update(this.objectName, {\n where,\n data: { ...row },\n ...bypass,\n } as any);\n } else {\n await this.engine.insert(this.objectName, { ...row }, bypass as any);\n }\n return;\n }\n const idx = this.memory.findIndex(\n (r) =>\n r.namespace === row.namespace &&\n r.key === row.key &&\n r.scope === row.scope &&\n (r.user_id ?? null) === (row.user_id ?? null),\n );\n if (idx >= 0) this.memory[idx] = row;\n else this.memory.push(row);\n }\n\n private async materialiseRow(row: SettingsRow): Promise<unknown> {\n if (row.encrypted) {\n if (!row.value_enc) return null;\n let plain: string;\n try {\n // Phase 3: when the value_enc looks like a sys_secret handle and\n // both the secretStore + cryptoProvider are wired, dereference\n // through sys_secret. Otherwise (legacy rows or in-memory tests)\n // fall back to inline crypto-adapter decryption.\n if (\n this.cryptoProvider &&\n this.secretStore &&\n typeof row.value_enc === 'string' &&\n row.value_enc.startsWith('sec_')\n ) {\n const secret = await this.secretStore.get(row.value_enc);\n if (!secret) return null;\n plain = await this.cryptoProvider.decrypt(\n {\n id: secret.id,\n kmsKeyId: secret.kms_key_id,\n alg: secret.alg,\n version: secret.version,\n ciphertext: secret.ciphertext,\n },\n { namespace: row.namespace, key: row.key },\n );\n } else {\n plain = await this.crypto.decrypt(row.value_enc, {\n namespace: row.namespace,\n key: row.key,\n });\n }\n } catch (err) {\n // Decrypt failures are almost always operational: the crypto\n // provider's data key changed (e.g. InMemoryCryptoProvider\n // generated a fresh ephemeral key after a restart) and the\n // stored AES-GCM auth tag no longer verifies. Bubbling the\n // raw Node error would 500 the entire `getNamespace` request\n // and lock the operator out of the settings UI — including\n // the very inputs they'd use to re-enter the secret. Instead,\n // log once and surface `null` so the field renders as empty\n // and remains editable.\n console.warn(\n `[SettingsService] failed to decrypt ${row.namespace}.${row.key}: ${(err as Error)?.message ?? err}. ` +\n `Returning null so the namespace remains readable; re-save the field to repair.`,\n );\n return null;\n }\n // Try JSON parse so non-string secrets round-trip.\n try {\n return JSON.parse(plain);\n } catch {\n return plain;\n }\n }\n return row.value ?? null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Local helpers\n// ---------------------------------------------------------------------------\n\n/** Stable stringify so the audit digest is order-independent. */\nfunction stableStringify(input: unknown): string {\n if (input === null || typeof input !== 'object') return JSON.stringify(input);\n if (Array.isArray(input)) return '[' + input.map(stableStringify).join(',') + ']';\n const obj = input as Record<string, unknown>;\n const keys = Object.keys(obj).sort();\n return '{' + keys.map((k) => JSON.stringify(k) + ':' + stableStringify(obj[k])).join(',') + '}';\n}\n\n/** Re-typed env coercer (the canonical one lives in settings-service.types). */\nfunction coerceEnvValue(raw: string, hint: unknown): unknown {\n if (typeof hint === 'boolean') return raw === 'true' || raw === '1' || raw === 'yes';\n if (typeof hint === 'number') {\n const n = Number(raw);\n return Number.isFinite(n) ? n : raw;\n }\n if (Array.isArray(hint) || (hint && typeof hint === 'object')) {\n try {\n return JSON.parse(raw);\n } catch {\n return raw;\n }\n }\n return raw;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type {\n CryptoContext,\n CryptoHandle,\n ICryptoProvider,\n} from '@objectstack/spec/contracts';\nimport { createHash, randomBytes, createCipheriv, createDecipheriv } from 'node:crypto';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\n\n/**\n * LocalCryptoProvider — the default, KMS-free `ICryptoProvider`. It is an\n * AES-256-GCM provider keyed off a single 32-byte data key, suitable for\n * single-operator / self-host deployments where a managed KMS or Vault is\n * overkill. KMS / Vault providers (per-tenant keys, automatic rotation,\n * managed custody) plug in behind the same `ICryptoProvider` seam.\n *\n * Key resolution (first match wins):\n *\n * 1. `opts.key` — explicit Buffer (tests / embedders).\n * 2. `OS_SECRET_KEY` — canonical production master key\n * (32-byte hex or base64).\n * 3. `OS_DEV_CRYPTO_KEY` — dev convenience key (legacy\n * (legacy `OBJECTSTACK_DEV_CRYPTO_KEY`) `OBJECTSTACK_DEV_CRYPTO_KEY`\n * still honoured).\n * 4. Persisted file — `~/.objectstack/dev-crypto-key`\n * (mode 0600). In development it is\n * auto-created; in production it is\n * only *read* unless `OS_CRYPTO_AUTOKEY`\n * opts the single-node self-host case\n * into minting + persisting it too.\n * 5. Ephemeral random key — development/test only.\n *\n * ## Fail-loud guarantee (the reason this class exists)\n *\n * The original provider would *silently* fall back to a fresh per-process\n * `randomBytes(32)` key whenever no env key and no readable file were\n * available — or auto-mint a new on-disk key on every boot. In an\n * ephemeral-FS container or a multi-node cluster that means each\n * restart / each node encrypts under a different key, and **every**\n * previously-written `sys_secret` value (encrypted settings, `secret`\n * fields, datasource credentials) becomes undecryptable. The failure was\n * invisible at encrypt and boot time and only surfaced later as\n * \"all my saved passwords/API keys/DB creds fail to decrypt\".\n *\n * To turn that silent data-loss into a config error at boot, the provider\n * REFUSES to mint a key in production: when `mode === 'production'` and no\n * stable key source (env var or pre-existing key file) is available, the\n * constructor throws an actionable error instead of generating one. The one\n * exception is the `OS_CRYPTO_AUTOKEY` opt-in: a single-node self-host\n * (`os start` on a durable filesystem) may mint + *persist* a key so the\n * zero-config quickstart boots — but even then the ephemeral fallback stays\n * forbidden, so a non-writable / ephemeral FS still fails loud rather than\n * running under a key that won't survive a restart. Development and test keep\n * the ergonomic fallback so local loops and unit tests stay frictionless.\n *\n * `mode` is auto-detected from `NODE_ENV` (`production` → strict;\n * `test`/`VITEST` → ephemeral, no disk; otherwise `development`) and can be\n * overridden via `opts.mode` for embedders that manage their own lifecycle.\n *\n * ## Handle format\n * id — `sec_` + 32 hex chars (122 bits of entropy)\n * kmsKeyId — `local:v<version>`\n * alg — `aes-256-gcm`\n * version — bumps on rotateKey()\n * ciphertext— base64(iv (12) || authTag (16) || cipher)\n *\n * ## AAD binding\n * The CryptoContext (namespace + key) is folded into AES-GCM AAD so a\n * ciphertext rewrapped from a different (ns, key) tuple fails decryption —\n * guards against operators accidentally copying rows between namespaces.\n *\n * ## WebContainer (StackBlitz) note\n * `node:crypto.createCipheriv('aes-256-gcm', …)` is not implemented in\n * WebContainer. When we detect that runtime, we swap to a pure-JS AES-GCM\n * from `@noble/ciphers/aes.js`, producing the same `iv || tag || ciphertext`\n * byte layout so the handle shape is unchanged. The swap is best-effort: if\n * the dependency is missing, we fall back to the Node implementation and let\n * it throw, surfacing the configuration problem clearly.\n */\nconst SECRET_KEY_ENV = 'OS_SECRET_KEY';\nconst DEV_KEY_ENV = 'OS_DEV_CRYPTO_KEY';\nconst DEV_KEY_LEGACY_ENV = 'OBJECTSTACK_DEV_CRYPTO_KEY';\n/**\n * Opt-in that lets the strict production path mint + PERSIST a key (but never\n * fall back to an ephemeral one). Set by `os start` for the single-node\n * self-host quickstart so the documented zero-config boot works out of the\n * box, while a real cluster deploy (which must provision `OS_SECRET_KEY`)\n * leaves it unset and keeps the fail-loud guarantee. See `commands/start.ts`.\n */\nconst AUTOKEY_ENV = 'OS_CRYPTO_AUTOKEY';\n\ntype EnvMap = Record<string, string | undefined>;\n\n/** Where the provider resolved its data key from (for diagnostics). */\nexport type KeySource =\n | 'explicit'\n | 'env:OS_SECRET_KEY'\n | 'env:OS_DEV_CRYPTO_KEY'\n | 'file'\n | 'generated-file'\n | 'ephemeral';\n\nexport type CryptoMode = 'production' | 'development' | 'test';\n\nexport interface LocalCryptoProviderOptions {\n /** Explicit 32-byte data key. Overrides all env / file resolution. */\n key?: Buffer;\n /**\n * Env source. Defaults to `process.env`. Injectable so embedders and\n * tests can drive key resolution deterministically.\n */\n env?: EnvMap;\n /**\n * Deployment mode. Controls whether an ephemeral / auto-generated key is\n * tolerated. Defaults to auto-detection from `NODE_ENV`:\n * - `production` → a stable key (env var or pre-existing file) is\n * REQUIRED; construction throws otherwise (fail loud).\n * - `development` → persists an auto-generated key to disk so restarts\n * reuse it; falls back to an ephemeral key (loud warning) if disk is\n * unwritable.\n * - `test` → never touches disk; uses an ephemeral key silently.\n */\n mode?: CryptoMode;\n}\n\nconst processEnv = (): EnvMap =>\n ((globalThis as { process?: { env?: EnvMap } }).process?.env ?? {}) as EnvMap;\n\nconst detectMode = (env: EnvMap): CryptoMode => {\n if (env.VITEST || env.NODE_ENV === 'test') return 'test';\n if (env.NODE_ENV === 'production') return 'production';\n return 'development';\n};\n\n/**\n * Per-user persistent key location. Honours `OS_HOME`\n * (legacy `OBJECTSTACK_HOME`) for projects that pin a non-default config dir.\n */\nconst keyFilePath = (env: EnvMap): string => {\n const home =\n env.OS_HOME ||\n env.OBJECTSTACK_HOME ||\n (env.HOME ? join(env.HOME, '.objectstack') : undefined) ||\n join(homedir(), '.objectstack');\n return join(home, 'dev-crypto-key');\n};\n\n/**\n * Parse an env key value (hex or base64) into a 32-byte Buffer. Returns\n * `undefined` when the value is unusable so the caller can decide whether to\n * fall through (dev) or throw (production / explicit master key).\n */\nconst parseKey = (raw: string | undefined): Buffer | undefined => {\n if (!raw) return undefined;\n const trimmed = raw.trim();\n if (!trimmed) return undefined;\n // hex: 64 chars of [0-9a-f]\n if (/^[0-9a-fA-F]{64}$/.test(trimmed)) return Buffer.from(trimmed, 'hex');\n // base64 (standard or url-safe): decode and check length\n try {\n const normalised = trimmed.replace(/-/g, '+').replace(/_/g, '/');\n const buf = Buffer.from(normalised, 'base64');\n if (buf.length === 32) return buf;\n } catch {\n /* fall through */\n }\n return undefined;\n};\n\n/** Truthy env flag: `1` / `true` / `yes` (case-insensitive). */\nconst parseBool = (raw: string | undefined): boolean => {\n const v = raw?.trim().toLowerCase();\n return v === '1' || v === 'true' || v === 'yes';\n};\n\n/** Read an existing key file (no creation). Returns `undefined` on miss / IO error. */\nconst loadExistingKey = (path: string): Buffer | undefined => {\n try {\n if (!existsSync(path)) return undefined;\n return parseKey(readFileSync(path, 'utf8').trim());\n } catch {\n return undefined;\n }\n};\n\n/**\n * Load (or generate-then-persist) the key file. Returns `undefined` on any\n * I/O error so the caller can degrade to an ephemeral key without breaking\n * boot. Only used in development.\n */\nconst loadOrCreateKey = (path: string): { key: Buffer; generated: boolean } | undefined => {\n try {\n const existing = loadExistingKey(path);\n if (existing) return { key: existing, generated: false };\n const key = randomBytes(32);\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, key.toString('base64'), { mode: 0o600 });\n return { key, generated: true };\n } catch {\n return undefined;\n }\n};\n\nconst INVALID_KEY_MSG = (name: string): string =>\n `[LocalCryptoProvider] ${name} is set but is not a 32-byte key (expected 64 hex chars or base64 of 32 bytes). ` +\n `Generate one with \\`openssl rand -hex 32\\`.`;\n\nconst MISSING_PROD_KEY_MSG = (path: string): string =>\n `[LocalCryptoProvider] Refusing to start in production without a stable encryption key.\\n` +\n ` No ${SECRET_KEY_ENV} (or ${DEV_KEY_ENV}) is set and no persisted key file was found at:\\n` +\n ` ${path}\\n` +\n ` Minting a key here would make every sys_secret value (encrypted settings, secret\\n` +\n ` fields, datasource credentials) undecryptable after the next restart or on another node.\\n` +\n ` Fix: generate a 32-byte key and set it in the environment (identical across every\\n` +\n ` restart and every node), e.g.\\n` +\n ` ${SECRET_KEY_ENV}=$(openssl rand -hex 32)`;\n\ninterface ResolvedKey {\n key: Buffer;\n source: KeySource;\n}\n\nconst warn = (msg: string): void => {\n try {\n (globalThis as { console?: { warn?: (m: string) => void } }).console?.warn?.(msg);\n } catch {\n /* exotic runtime without console — ignore */\n }\n};\n\nconst legacyDeprecationWarned = { value: false };\n\nfunction resolveDataKey(opts: LocalCryptoProviderOptions): ResolvedKey {\n if (opts.key) return { key: opts.key, source: 'explicit' };\n\n const env = opts.env ?? processEnv();\n const mode = opts.mode ?? detectMode(env);\n\n // 1) Canonical production master key.\n if (env[SECRET_KEY_ENV] !== undefined) {\n const parsed = parseKey(env[SECRET_KEY_ENV]);\n if (parsed) return { key: parsed, source: 'env:OS_SECRET_KEY' };\n // Present-but-invalid is an explicit operator error — never silently\n // fall through to a different key (that would be silent data divergence).\n throw new Error(INVALID_KEY_MSG(SECRET_KEY_ENV));\n }\n\n // 2) Dev convenience key (legacy alias honoured with a deprecation note).\n let devRaw = env[DEV_KEY_ENV];\n if (devRaw === undefined && env[DEV_KEY_LEGACY_ENV] !== undefined) {\n devRaw = env[DEV_KEY_LEGACY_ENV];\n if (!legacyDeprecationWarned.value) {\n legacyDeprecationWarned.value = true;\n warn(\n `[ObjectStack] Env var \\`${DEV_KEY_LEGACY_ENV}\\` is deprecated; rename it to \\`${DEV_KEY_ENV}\\`.`,\n );\n }\n }\n if (devRaw !== undefined) {\n const parsed = parseKey(devRaw);\n if (parsed) return { key: parsed, source: 'env:OS_DEV_CRYPTO_KEY' };\n if (mode === 'production') throw new Error(INVALID_KEY_MSG(DEV_KEY_ENV));\n warn(`${INVALID_KEY_MSG(DEV_KEY_ENV)} Ignoring and generating a local key.`);\n }\n\n // 3) No usable env key — behaviour depends on mode.\n if (mode === 'test') {\n // Tests never touch disk; an ephemeral key round-trips within the process.\n return { key: randomBytes(32), source: 'ephemeral' };\n }\n\n const path = keyFilePath(env);\n\n if (mode === 'production') {\n // Honour a pre-existing, operator-provisioned key file first.\n const existing = loadExistingKey(path);\n if (existing) {\n warn(\n `[LocalCryptoProvider] No ${SECRET_KEY_ENV} set — using the persisted key at ${path}. ` +\n `For containers / multi-node, prefer setting ${SECRET_KEY_ENV} so every node shares one key.`,\n );\n return { key: existing, source: 'file' };\n }\n\n // Single-node self-host opt-in (`os start` on a durable filesystem): mint\n // a key AND persist it so the zero-config quickstart boots. We still\n // REFUSE the ephemeral fallback below — if the key cannot be written\n // (read-only / ephemeral FS), running anyway would silently lose every\n // sys_secret on the next restart, the exact footgun this guard prevents.\n // Multi-node deploys must NOT opt in (each node would mint a divergent\n // key); `os start` only sets the flag when no cluster driver is set.\n if (parseBool(env[AUTOKEY_ENV])) {\n const persisted = loadOrCreateKey(path);\n if (persisted) {\n if (persisted.generated) {\n warn(\n `[LocalCryptoProvider] No ${SECRET_KEY_ENV} set — minted a new AES-256-GCM key and ` +\n `persisted it to ${path} (mode 0600). Restarts on this host reuse it automatically. ` +\n `For containers, CI, or multi-node, set ${SECRET_KEY_ENV} so every node shares one key.`,\n );\n }\n return { key: persisted.key, source: persisted.generated ? 'generated-file' : 'file' };\n }\n // Persist failed → fall through to the hard error. Never run ephemeral\n // in production, even with the opt-in.\n }\n\n throw new Error(MISSING_PROD_KEY_MSG(path));\n }\n\n // development: persist an auto-generated key so restarts reuse it.\n const persisted = loadOrCreateKey(path);\n if (persisted) {\n if (persisted.generated) {\n warn(\n `[LocalCryptoProvider] No ${SECRET_KEY_ENV}/${DEV_KEY_ENV} set — generated a new AES-256-GCM key ` +\n `and persisted it to ${path} (mode 0600). Restarts on this host reuse it automatically. ` +\n `For containers, CI, or multi-node, set ${SECRET_KEY_ENV} explicitly so the key survives.`,\n );\n }\n return { key: persisted.key, source: persisted.generated ? 'generated-file' : 'file' };\n }\n\n // Last-resort ephemeral key (e.g. $HOME unwritable). Loud warning: this is\n // the dangerous tier — secrets will NOT survive a restart.\n const key = randomBytes(32);\n warn(\n `[LocalCryptoProvider] No ${SECRET_KEY_ENV} set and could not persist a fallback key at ${path} — ` +\n `generated an EPHEMERAL key. Existing encrypted settings/secrets will fail to decrypt after restart. ` +\n `Set ${SECRET_KEY_ENV} to a stable 32-byte key:\\n ${SECRET_KEY_ENV}=${key.toString('base64')}`,\n );\n return { key, source: 'ephemeral' };\n}\n\nconst isWebContainerRuntime = (): boolean => {\n const g = globalThis as any;\n return (\n typeof g !== 'undefined' &&\n (Boolean(g.process?.versions?.webcontainer) ||\n Boolean(g.process?.env?.SHELL?.includes?.('jsh')) ||\n Boolean(g.process?.env?.STACKBLITZ))\n );\n};\n\ntype GcmFactory = (key: Uint8Array, nonce: Uint8Array, aad?: Uint8Array) => {\n encrypt: (plain: Uint8Array) => Uint8Array;\n decrypt: (cipher: Uint8Array) => Uint8Array;\n};\n\nlet nobleGcmPromise: Promise<GcmFactory | undefined> | undefined;\nconst loadNobleGcm = (): Promise<GcmFactory | undefined> => {\n if (!nobleGcmPromise) {\n nobleGcmPromise = (async () => {\n try {\n const mod = await import('@noble/ciphers/aes.js');\n return mod.gcm as unknown as GcmFactory;\n } catch (err: any) {\n warn(\n `[LocalCryptoProvider] WebContainer detected but @noble/ciphers not installed: ${err?.message ?? err}. Falling back to node:crypto (will throw).`,\n );\n return undefined;\n }\n })();\n }\n return nobleGcmPromise;\n};\n\nexport class LocalCryptoProvider implements ICryptoProvider {\n private readonly key: Buffer;\n private readonly useNoble: boolean;\n /** Where the active data key came from. Exposed for diagnostics/tests. */\n readonly keySource: KeySource;\n\n constructor(opts: LocalCryptoProviderOptions = {}) {\n const resolved = resolveDataKey(opts);\n this.key = resolved.key;\n this.keySource = resolved.source;\n this.useNoble = isWebContainerRuntime();\n }\n\n async encrypt(plain: string, ctx: CryptoContext): Promise<CryptoHandle> {\n const iv = randomBytes(12);\n const aad = Buffer.from(this.aadOf(ctx), 'utf8');\n const plainBytes = Buffer.from(plain, 'utf8');\n\n let blob: string;\n if (this.useNoble) {\n const gcm = await loadNobleGcm();\n if (gcm) {\n const cipher = gcm(this.key, iv, aad);\n const ctWithTag = cipher.encrypt(plainBytes); // ciphertext || tag(16)\n const ct = ctWithTag.subarray(0, ctWithTag.length - 16);\n const tag = ctWithTag.subarray(ctWithTag.length - 16);\n blob = Buffer.concat([iv, Buffer.from(tag), Buffer.from(ct)]).toString('base64');\n } else {\n blob = this.encryptNode(plainBytes, iv, aad);\n }\n } else {\n blob = this.encryptNode(plainBytes, iv, aad);\n }\n\n return {\n id: 'sec_' + randomBytes(16).toString('hex'),\n kmsKeyId: 'local:v1',\n alg: 'aes-256-gcm',\n version: 1,\n ciphertext: blob,\n };\n }\n\n async decrypt(handle: CryptoHandle, ctx: CryptoContext): Promise<string> {\n const buf = Buffer.from(handle.ciphertext, 'base64');\n const iv = buf.subarray(0, 12);\n const tag = buf.subarray(12, 28);\n const data = buf.subarray(28);\n const aad = Buffer.from(this.aadOf(ctx), 'utf8');\n\n if (this.useNoble) {\n const gcm = await loadNobleGcm();\n if (gcm) {\n const cipher = gcm(this.key, iv, aad);\n const ctWithTag = Buffer.concat([data, tag]); // noble expects ciphertext || tag\n const out = cipher.decrypt(ctWithTag);\n return Buffer.from(out).toString('utf8');\n }\n }\n const decipher = createDecipheriv('aes-256-gcm', this.key, iv);\n decipher.setAAD(aad);\n decipher.setAuthTag(tag);\n return Buffer.concat([decipher.update(data), decipher.final()]).toString('utf8');\n }\n\n async rotateKey(handle: CryptoHandle, ctx: CryptoContext): Promise<CryptoHandle> {\n const plain = await this.decrypt(handle, ctx);\n const next = await this.encrypt(plain, ctx);\n return {\n ...next,\n id: handle.id,\n kmsKeyId: `local:v${handle.version + 1}`,\n version: handle.version + 1,\n };\n }\n\n digest(plain: string): string {\n return 'sha256:' + createHash('sha256').update(plain, 'utf8').digest('hex');\n }\n\n private encryptNode(plainBytes: Buffer, iv: Buffer, aad: Buffer): string {\n const cipher = createCipheriv('aes-256-gcm', this.key, iv);\n cipher.setAAD(aad);\n const enc = Buffer.concat([cipher.update(plainBytes), cipher.final()]);\n const tag = cipher.getAuthTag();\n return Buffer.concat([iv, tag, enc]).toString('base64');\n }\n\n private aadOf(ctx: CryptoContext): string {\n // Bind ciphertext to (namespace,key) so a row cannot be moved across\n // specifiers. Tenant binding is intentionally omitted because the\n // handle is dereferenced from a `sys_setting` row already scoped to\n // its tenant — adding tenant here would force the decrypt path to\n // re-read that scope.\n return [ctx.namespace, ctx.key].join('|');\n }\n}\n\n/**\n * @deprecated Renamed to {@link LocalCryptoProvider}. The old name implied an\n * \"in-memory / ephemeral\" key when the provider in fact persists its key\n * (env var or on-disk file). Kept as an alias for backward compatibility.\n */\nexport const InMemoryCryptoProvider = LocalCryptoProvider;\n/** @deprecated Use {@link LocalCryptoProviderOptions}. */\nexport type InMemoryCryptoProviderOptions = LocalCryptoProviderOptions;\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * REST surface for the SettingsService — see ADR-0007 §REST.\n *\n * GET /api/settings → visible manifests\n * GET /api/settings/:namespace → { manifest, values }\n * PUT /api/settings/:namespace → batch upsert\n * POST /api/settings/:namespace/:actionId → invoke declared action\n *\n * The route layer is a thin wrapper that maps thrown service errors\n * into proper HTTP status codes; all business logic lives in\n * `SettingsService`.\n */\n\nimport type { IHttpServer, IHttpRequest, IHttpResponse, RouteHandler } from '@objectstack/spec/contracts';\nimport { SettingsService } from './settings-service.js';\nimport {\n SettingsLockedError,\n SettingsValidationError,\n UnknownKeyError,\n UnknownNamespaceError,\n type SettingsContext,\n} from './settings-service.types.js';\n\nexport interface SettingsRoutesOptions {\n /** Base path. Default `/api/settings`. */\n basePath?: string;\n /**\n * Extract caller identity from the request. The default reads\n * `x-user-id` / `x-tenant-id` headers and parses\n * `x-permissions` as a comma-separated list — fine for dev and\n * straightforward to override in production wiring.\n */\n contextFromRequest?: (req: IHttpRequest) => SettingsContext;\n}\n\nconst defaultContext = (req: IHttpRequest): SettingsContext => {\n const header = (name: string): string | undefined => {\n const v = req.headers?.[name];\n return Array.isArray(v) ? v[0] : v;\n };\n const perms = header('x-permissions');\n return {\n userId: header('x-user-id'),\n tenantId: header('x-tenant-id'),\n permissions: perms ? perms.split(',').map((s) => s.trim()).filter(Boolean) : undefined,\n requestId: header('x-request-id'),\n };\n};\n\nfunction sendError(res: IHttpResponse, status: number, code: string, message: string, extra?: Record<string, unknown>) {\n res.status(status).json({ error: { code, message, ...extra } });\n}\n\nexport function registerSettingsRoutes(\n http: IHttpServer,\n service: SettingsService,\n opts: SettingsRoutesOptions = {},\n): void {\n const base = opts.basePath ?? '/api/settings';\n const ctxOf = opts.contextFromRequest ?? defaultContext;\n\n http.get(base, (async (req, res) => {\n try {\n const ctx = ctxOf(req);\n const manifests = service.listManifests(ctx);\n await res.json({ manifests });\n } catch (err: any) {\n sendError(res, 500, 'INTERNAL', err?.message ?? 'Failed to list manifests');\n }\n }) satisfies RouteHandler);\n\n http.get(`${base}/:namespace`, (async (req, res) => {\n const ns = req.params.namespace;\n try {\n const ctx = ctxOf(req);\n const payload = await service.getNamespace(ns, ctx);\n await res.json(payload);\n } catch (err: any) {\n if (err instanceof UnknownNamespaceError) {\n sendError(res, 404, 'UNKNOWN_NAMESPACE', err.message);\n } else {\n sendError(res, 500, 'INTERNAL', err?.message ?? 'Failed to read namespace');\n }\n }\n }) satisfies RouteHandler);\n\n http.put(`${base}/:namespace`, (async (req, res) => {\n const ns = req.params.namespace;\n let body = (req.body ?? {}) as Record<string, unknown>;\n // DX symmetry: GET returns `{ values: { key: { value, source, … } } }`.\n // Accept that same envelope on PUT (sole top-level `values` object) so a\n // caller can write back exactly what it read instead of tripping a\n // confusing UNKNOWN_KEY('values'). Per-key, unwrap the read-shape\n // `{ value, … }` wrapper to the bare value; flat `{ key: value }` bodies\n // (and a manifest that genuinely declares a `values` key alongside others)\n // are untouched.\n if (\n Object.keys(body).length === 1 &&\n body.values && typeof body.values === 'object' && !Array.isArray(body.values)\n ) {\n const inner = body.values as Record<string, unknown>;\n body = Object.fromEntries(\n Object.entries(inner).map(([k, v]) =>\n v && typeof v === 'object' && !Array.isArray(v) && 'value' in (v as object)\n ? [k, (v as { value: unknown }).value]\n : [k, v],\n ),\n );\n }\n try {\n const ctx = ctxOf(req);\n const result = await service.setMany(ns, body, ctx);\n await res.json({ values: result });\n } catch (err: any) {\n if (err instanceof SettingsLockedError) {\n sendError(res, 409, 'SETTINGS_LOCKED', err.message, {\n namespace: err.namespace,\n key: err.key,\n reason: err.reason,\n });\n } else if (err instanceof UnknownNamespaceError) {\n sendError(res, 404, 'UNKNOWN_NAMESPACE', err.message);\n } else if (err instanceof UnknownKeyError) {\n sendError(res, 400, 'UNKNOWN_KEY', err.message, { namespace: err.namespace, key: err.key });\n } else if (err instanceof SettingsValidationError) {\n sendError(res, 400, 'SETTINGS_VALIDATION', err.message, {\n namespace: err.namespace,\n fields: err.fields,\n });\n } else {\n sendError(res, 500, 'INTERNAL', err?.message ?? 'Failed to write namespace');\n }\n }\n }) satisfies RouteHandler);\n\n http.post(`${base}/:namespace/:actionId`, (async (req, res) => {\n const { namespace, actionId } = req.params;\n try {\n const ctx = ctxOf(req);\n const result = await service.runAction(namespace, actionId, req.body, ctx);\n const status = result.ok ? 200 : 400;\n await res.status(status).json(result);\n } catch (err: any) {\n if (err instanceof UnknownNamespaceError) {\n sendError(res, 404, 'UNKNOWN_NAMESPACE', err.message);\n } else {\n sendError(res, 500, 'INTERNAL', err?.message ?? 'Action failed');\n }\n }\n }) satisfies RouteHandler);\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { SysSetting, SysSecret, SysSettingAudit } from '@objectstack/platform-objects/system';\n\nexport const SETTINGS_PLUGIN_ID = 'com.objectstack.service.settings';\nexport const SETTINGS_PLUGIN_VERSION = '0.1.0';\n\n/** Objects owned by service-settings. Currently just the K/V store. */\nexport const settingsObjects: any[] = [SysSetting, SysSecret, SysSettingAudit];\n\n/** Manifest header shared by compile-time config and runtime registration. */\nexport const settingsPluginManifestHeader = {\n id: SETTINGS_PLUGIN_ID,\n namespace: 'sys',\n version: SETTINGS_PLUGIN_VERSION,\n type: 'plugin' as const,\n scope: 'system' as const,\n name: 'Settings Service',\n description:\n 'Generic settings registry + K/V resolver with OS_* env > Tenant > User > Default precedence. ADR-0007.',\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { SettingsManifest } from '@objectstack/spec/system';\n\n// Open-source auth settings intentionally stay small: platform-wide auth\n// policy toggles plus the baseline Google social-login provider.\nconst manifest = {\n namespace: 'auth',\n version: 1,\n label: 'Authentication',\n icon: 'LockKeyhole',\n description: 'Sign-in, registration, and built-in auth feature controls.',\n scope: 'global',\n readPermission: 'manage_platform_settings',\n writePermission: 'manage_platform_settings',\n category: 'Security',\n order: 15,\n specifiers: [\n {\n type: 'group',\n id: 'email_password',\n label: 'Email and password',\n required: false,\n description: 'Control local email/password sign-in and self-service registration.',\n },\n {\n type: 'toggle',\n key: 'email_password_enabled',\n label: 'Enable email/password login',\n required: false,\n default: true,\n },\n {\n type: 'toggle',\n key: 'signup_enabled',\n label: 'Allow self-service registration',\n required: false,\n default: true,\n visible: \"${data.email_password_enabled !== false}\",\n },\n {\n type: 'toggle',\n key: 'require_email_verification',\n label: 'Require email verification',\n required: false,\n default: false,\n visible: \"${data.email_password_enabled !== false}\",\n },\n\n {\n type: 'group',\n id: 'password_policy',\n label: 'Password policy',\n required: false,\n description: 'Length bounds enforced by the auth provider on sign-up and password reset.',\n },\n {\n type: 'number',\n key: 'password_min_length',\n label: 'Minimum password length',\n required: false,\n default: 8,\n min: 6,\n max: 64,\n visible: \"${data.email_password_enabled !== false}\",\n },\n {\n type: 'number',\n key: 'password_max_length',\n label: 'Maximum password length',\n required: false,\n default: 128,\n min: 16,\n max: 256,\n description: 'Upper bound guards against denial-of-service via very long password hashing.',\n visible: \"${data.email_password_enabled !== false}\",\n },\n {\n type: 'toggle',\n key: 'password_reject_breached',\n label: 'Reject breached passwords',\n required: false,\n default: false,\n description:\n 'Block passwords found in public breach corpora via Have I Been Pwned (k-anonymity range check; the password is never sent in full).',\n visible: \"${data.email_password_enabled !== false}\",\n },\n {\n type: 'toggle',\n key: 'password_require_complexity',\n label: 'Require complex passwords',\n required: false,\n default: false,\n description:\n 'Require passwords to mix character classes (uppercase, lowercase, digits, symbols) on sign-up and password change/reset.',\n visible: \"${data.email_password_enabled !== false}\",\n },\n {\n type: 'number',\n key: 'password_min_classes',\n label: 'Minimum character classes',\n required: false,\n default: 3,\n min: 1,\n max: 4,\n description: 'How many of the four classes (upper / lower / digit / symbol) a password must include.',\n visible: \"${data.email_password_enabled !== false && data.password_require_complexity === true}\",\n },\n {\n type: 'number',\n key: 'password_history_count',\n label: 'Password history (no reuse)',\n required: false,\n default: 0,\n min: 0,\n max: 24,\n description: 'Block reusing this many previous passwords on change/reset. 0 disables the check.',\n visible: \"${data.email_password_enabled !== false}\",\n },\n\n {\n type: 'group',\n id: 'anti_abuse',\n label: 'Anti-abuse',\n required: false,\n description:\n 'Brute-force protection: per-identity account lockout and per-IP rate limiting on auth endpoints.',\n },\n {\n type: 'number',\n key: 'lockout_threshold',\n label: 'Account lockout threshold',\n required: false,\n default: 0,\n min: 0,\n max: 20,\n description:\n 'Lock an account after this many consecutive failed sign-ins. 0 disables lockout. While locked, sign-in is rejected even with the correct password.',\n visible: \"${data.email_password_enabled !== false}\",\n },\n {\n type: 'number',\n key: 'lockout_duration_minutes',\n label: 'Lockout duration (minutes)',\n required: false,\n default: 15,\n min: 1,\n max: 1440,\n description: 'How long an account stays locked once the threshold is crossed.',\n visible: \"${data.email_password_enabled !== false && data.lockout_threshold > 0}\",\n },\n {\n type: 'number',\n key: 'rate_limit_max',\n label: 'Auth rate-limit: max requests',\n required: false,\n default: 10,\n min: 1,\n max: 1000,\n description: 'Maximum requests per IP, per window, to the sign-in / sign-up / password-reset endpoints.',\n },\n {\n type: 'number',\n key: 'rate_limit_window_seconds',\n label: 'Auth rate-limit: window (seconds)',\n required: false,\n default: 60,\n min: 1,\n max: 3600,\n description: 'Sliding window over which the request cap above is counted.',\n },\n {\n type: 'group',\n id: 'sessions',\n label: 'Sessions',\n required: false,\n description: 'How long a signed-in session stays valid.',\n },\n {\n type: 'number',\n key: 'session_expiry_days',\n label: 'Session lifetime (days)',\n required: false,\n default: 7,\n min: 1,\n max: 365,\n description: 'A session expires this many days after sign-in.',\n },\n {\n type: 'number',\n key: 'session_refresh_days',\n label: 'Refresh threshold (days)',\n required: false,\n default: 1,\n min: 1,\n max: 90,\n description: 'An active session is extended when it is older than this.',\n },\n\n {\n type: 'group',\n id: 'social',\n label: 'Social sign-in',\n required: false,\n description:\n 'Configure the built-in Google sign-in provider. Deployment env vars still win.',\n },\n {\n type: 'toggle',\n key: 'google_enabled',\n label: 'Enable Google login',\n required: false,\n default: true,\n description:\n 'Requires a Google OAuth client ID and secret from Google Cloud Console.',\n },\n {\n type: 'text',\n key: 'google_client_id',\n label: 'Google client ID',\n required: true,\n description:\n 'OAuth client ID from Google Cloud Console. GOOGLE_CLIENT_ID can also be set on the server.',\n visible: \"${data.google_enabled !== false}\",\n },\n {\n type: 'password',\n key: 'google_client_secret',\n label: 'Google client secret',\n required: true,\n encrypted: true,\n description:\n 'Stored encrypted at rest. GOOGLE_CLIENT_SECRET can also be set on the server.',\n visible: \"${data.google_enabled !== false}\",\n },\n\n ],\n};\n\n/** Authentication - sign-in, registration, and built-in auth controls. */\nexport const authSettingsManifest = manifest as unknown as SettingsManifest;\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { SettingsManifest } from '@objectstack/spec/system';\nimport type { SettingsActionHandler } from '../settings-service.types.js';\n\n// Visibility expressions are written as inline strings here for\n// readability. The spec's ExpressionInputSchema accepts a bare string\n// and normalises it at parse time, but the inferred TypeScript output\n// type expects `{ dialect, source }` objects. Build the manifest as\n// `unknown` first, then cast — keeps the manifest source compact.\nconst manifest = {\n namespace: 'mail',\n version: 1,\n label: 'Mail Delivery',\n icon: 'Mail',\n description: 'SMTP and transactional email provider configuration.',\n scope: 'global',\n readPermission: 'manage_platform_settings',\n writePermission: 'manage_platform_settings',\n category: 'Communication',\n order: 10,\n specifiers: [\n { type: 'group', id: 'provider', label: 'Provider', required: false,\n description: 'Choose how this workspace sends outbound email.' },\n\n { type: 'select', key: 'provider', label: 'Provider', required: true, default: 'smtp',\n options: [\n { value: 'smtp', label: 'SMTP' },\n { value: 'sendgrid', label: 'SendGrid' },\n { value: 'ses', label: 'Amazon SES' },\n { value: 'postmark', label: 'Postmark' },\n ],\n },\n\n { type: 'group', id: 'smtp', label: 'SMTP', required: false, visible: \"${data.provider === 'smtp'}\" },\n { type: 'text', key: 'smtp_host', label: 'Host', required: true,\n description: 'Example: smtp.example.com', visible: \"${data.provider === 'smtp'}\" },\n { type: 'number', key: 'smtp_port', label: 'Port', required: false, default: 587,\n min: 1, max: 65535, visible: \"${data.provider === 'smtp'}\" },\n { type: 'toggle', key: 'smtp_secure', label: 'Use TLS', required: false, default: true,\n visible: \"${data.provider === 'smtp'}\" },\n { type: 'text', key: 'smtp_user', label: 'Username', required: false,\n visible: \"${data.provider === 'smtp'}\" },\n { type: 'password', key: 'smtp_password', label: 'Password', required: false,\n visible: \"${data.provider === 'smtp'}\" },\n\n { type: 'group', id: 'api_key', label: 'API key', required: false, visible: \"${data.provider !== 'smtp'}\" },\n { type: 'password', key: 'api_key', label: 'API key', required: true, encrypted: true,\n visible: \"${data.provider !== 'smtp'}\" },\n\n { type: 'group', id: 'from_address', label: 'From address', required: false },\n { type: 'email', key: 'from_email', label: 'From email', required: true,\n description: 'Example: no-reply@example.com' },\n { type: 'text', key: 'from_name', label: 'From name', required: false, default: 'ObjectStack' },\n\n { type: 'action_button', id: 'test', label: 'Send test email', required: false, icon: 'Send',\n handler: { kind: 'http', method: 'POST', url: '/api/settings/mail/test' } },\n ],\n};\n\n/** Mail Delivery — SMTP / API provider configuration. */\nexport const mailSettingsManifest = manifest as unknown as SettingsManifest;\n\n/** Built-in action handler stub for `mail/test`. */\nexport const mailTestActionHandler: SettingsActionHandler = async ({ values }) => {\n const provider = String(values.provider ?? 'smtp');\n const fromEmail = values.from_email as string | undefined;\n if (!fromEmail) {\n return { ok: false, severity: 'error', message: 'Configure a from address before testing.' };\n }\n if (provider === 'smtp' && !values.smtp_host) {\n return { ok: false, severity: 'error', message: 'SMTP host is required.' };\n }\n if (provider !== 'smtp' && !values.api_key) {\n return { ok: false, severity: 'error', message: 'API key is required.' };\n }\n return {\n ok: true,\n severity: 'info',\n message: `Configuration looks valid (provider=${provider}). Wire @objectstack/plugin-mail for actual delivery.`,\n };\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { SettingsManifest } from '@objectstack/spec/system';\n\n/** Branding — workspace identity (name, logo, theme). */\nexport const brandingSettingsManifest: SettingsManifest = {\n namespace: 'branding',\n version: 1,\n label: 'Branding',\n icon: 'Palette',\n description: 'Workspace name, logo, and accent colour.',\n scope: 'tenant',\n readPermission: 'setup.access',\n writePermission: 'setup.write',\n category: 'Workspace',\n order: 5,\n specifiers: [\n { type: 'group', id: 'identity', label: 'Identity', required: false },\n { type: 'text', key: 'workspace_name', label: 'Workspace name', required: true,\n default: 'ObjectStack', minLength: 1, maxLength: 60 },\n { type: 'email', key: 'support_email', label: 'Support email', required: false,\n description: 'Example: support@example.com' },\n\n { type: 'group', id: 'appearance', label: 'Appearance', required: false },\n { type: 'select', key: 'theme_mode', label: 'Default theme', required: false, default: 'system',\n options: [\n { value: 'light', label: 'Light' },\n { value: 'dark', label: 'Dark' },\n { value: 'system', label: 'Match system' },\n ],\n },\n { type: 'color', key: 'accent_color', label: 'Accent colour', required: false, default: '#6366f1' },\n { type: 'url', key: 'logo_url', label: 'Logo URL', required: false,\n description: 'Example: https://…/logo.svg' },\n ],\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { SettingsManifest } from '@objectstack/spec/system';\n\n/** Feature Flags — opt into experimental capabilities. */\nexport const featureFlagsSettingsManifest: SettingsManifest = {\n namespace: 'feature_flags',\n version: 1,\n label: 'Feature Flags',\n icon: 'FlaskConical',\n description: 'Toggle experimental and beta features for this workspace.',\n scope: 'tenant',\n readPermission: 'setup.access',\n writePermission: 'setup.write',\n category: 'Beta',\n order: 100,\n beta: true,\n specifiers: [\n { type: 'info_banner', id: 'beta_notice', label: 'Heads up', required: false,\n bannerText:\n 'Beta features may change without notice. Pin via env vars (e.g. `OS_FEATURE_FLAGS_AI_ENABLED=true`) to lock for the whole deployment.',\n bannerSeverity: 'warning' },\n\n { type: 'group', id: 'productivity', label: 'Productivity', required: false },\n { type: 'toggle', key: 'ai_enabled', label: 'AI Assistant', required: false, default: false,\n description: 'Enables the in-app AI assistant panel.' },\n { type: 'toggle', key: 'kanban_swimlanes', label: 'Kanban swimlanes', required: false, default: false },\n\n { type: 'group', id: 'collaboration', label: 'Collaboration', required: false },\n { type: 'toggle', key: 'realtime_cursors', label: 'Realtime cursors', required: false, default: false },\n { type: 'toggle', key: 'inline_comments', label: 'Inline comments', required: false, default: true },\n ],\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { SettingsManifest } from '@objectstack/spec/system';\nimport type { SettingsActionHandler } from '../settings-service.types.js';\n\n// Mirrors the shape of `mail.manifest.ts`. The actual adapter rebuild\n// + `storage/test` probe live in `@objectstack/service-storage`; this\n// manifest only declares the form + acts as a safe fallback when the\n// storage plugin is not present.\nconst manifest = {\n namespace: 'storage',\n version: 1,\n label: 'File Storage',\n icon: 'HardDrive',\n description:\n 'Backend used for attachments, exports, and user uploads. ' +\n '⚠ Switching adapter does not migrate existing files — files ' +\n 'uploaded under the previous adapter become unreachable through ' +\n 'the new one.',\n scope: 'global',\n readPermission: 'manage_platform_settings',\n writePermission: 'manage_platform_settings',\n category: 'Infrastructure',\n order: 20,\n specifiers: [\n { type: 'group', id: 'adapter', label: 'Backend', required: false,\n description: 'Choose where uploaded files are stored.' },\n { type: 'select', key: 'adapter', label: 'Adapter', required: true, default: 'local',\n options: [\n { value: 'local', label: 'Local filesystem' },\n { value: 's3', label: 'S3 / S3-compatible' },\n ],\n },\n\n { type: 'group', id: 'local', label: 'Local', required: false,\n visible: \"${data.adapter === 'local'}\" },\n { type: 'text', key: 'local_root', label: 'Root directory', required: false,\n default: './.objectstack/data/uploads',\n description: 'Filesystem path under which files are stored. Relative paths resolve from the server CWD.',\n visible: \"${data.adapter === 'local'}\" },\n\n { type: 'group', id: 's3', label: 'S3', required: false,\n visible: \"${data.adapter === 's3'}\" },\n { type: 'text', key: 's3_bucket', label: 'Bucket', required: true,\n description: 'Shared host bucket. Per-environment files are namespaced via the projects/<environmentId>/ prefix.',\n visible: \"${data.adapter === 's3'}\" },\n { type: 'text', key: 's3_region', label: 'Region', required: true,\n description: 'Example: us-east-1',\n visible: \"${data.adapter === 's3'}\" },\n { type: 'text', key: 's3_endpoint', label: 'Endpoint', required: false,\n description: 'Custom endpoint for S3-compatible providers (R2, MinIO, Wasabi). Leave blank for AWS S3.',\n visible: \"${data.adapter === 's3'}\" },\n { type: 'text', key: 's3_access_key_id', label: 'Access key ID', required: true,\n visible: \"${data.adapter === 's3'}\" },\n { type: 'password', key: 's3_secret_access_key', label: 'Secret access key',\n required: true, encrypted: true,\n visible: \"${data.adapter === 's3'}\" },\n { type: 'toggle', key: 's3_force_path_style', label: 'Force path-style URLs',\n required: false, default: false,\n description: 'Enable for MinIO and most S3-compatible providers; disable for AWS S3.',\n visible: \"${data.adapter === 's3'}\" },\n\n { type: 'group', id: 'limits', label: 'Limits', required: false },\n { type: 'number', key: 'presigned_ttl', label: 'Presigned URL TTL (seconds)',\n required: false, default: 3600, min: 60, max: 604800 },\n { type: 'number', key: 'session_ttl', label: 'Upload session TTL (seconds)',\n required: false, default: 86400, min: 300, max: 604800,\n description: 'How long a chunked-upload session stays resumable.' },\n { type: 'number', key: 'max_upload_mb', label: 'Max upload size (MB)',\n required: false, default: 100, min: 1, max: 10240 },\n\n { type: 'action_button', id: 'test', label: 'Test connection',\n required: false, icon: 'Plug',\n handler: { kind: 'http', method: 'POST', url: '/api/settings/storage/test' } },\n ],\n};\n\n/** File Storage — local FS / S3-compatible backend configuration. */\nexport const storageSettingsManifest = manifest as unknown as SettingsManifest;\n\n/**\n * Built-in fallback action handler for `storage/test`. The real\n * implementation lives in `@objectstack/service-storage` and is\n * registered by `StorageServicePlugin` on `kernel:ready` (it overrides\n * this stub via `registerAction`). This fallback only validates the\n * form so the button is still useful when the storage plugin is\n * absent (e.g. in a unit-test kernel that mounts settings only).\n */\nexport const storageTestActionHandler: SettingsActionHandler = async ({ values }) => {\n const adapter = String(values.adapter ?? 'local');\n if (adapter === 'local') {\n const root = values.local_root as string | undefined;\n if (!root) {\n return { ok: false, severity: 'error', message: 'Configure a root directory before testing.' };\n }\n return {\n ok: true,\n severity: 'info',\n message: `Local adapter configured (root=${root}). Mount @objectstack/service-storage to exercise live I/O.`,\n };\n }\n if (adapter === 's3') {\n const missing: string[] = [];\n if (!values.s3_bucket) missing.push('s3_bucket');\n if (!values.s3_region) missing.push('s3_region');\n if (!values.s3_access_key_id) missing.push('s3_access_key_id');\n if (!values.s3_secret_access_key) missing.push('s3_secret_access_key');\n if (missing.length) {\n return { ok: false, severity: 'error', message: `Missing required field${missing.length > 1 ? 's' : ''}: ${missing.join(', ')}` };\n }\n return {\n ok: true,\n severity: 'info',\n message: `S3 adapter configured (bucket=${values.s3_bucket}, region=${values.s3_region}). Mount @objectstack/service-storage to exercise live I/O.`,\n };\n }\n return { ok: false, severity: 'error', message: `Unknown adapter: ${adapter}` };\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { SettingsManifest } from '@objectstack/spec/system';\nimport type { SettingsActionHandler } from '../settings-service.types.js';\n\n// Visibility expressions are written as inline strings here for\n// readability. The spec's ExpressionInputSchema accepts a bare string\n// and normalises it at parse time, but the inferred TypeScript output\n// type expects `{ dialect, source }` objects. Build the manifest as\n// `unknown` first, then cast — keeps the manifest source compact.\n//\n// The actual LLM adapter selection still happens in\n// `@objectstack/service-ai`'s plugin (env-var driven by default).\n// This manifest gives operators a UI to inspect and override those\n// env-derived defaults without redeploying. AIServicePlugin binds to this\n// namespace once the kernel is ready; env-locked settings values use the\n// OS_AI_* convention and win over UI-stored values.\nconst manifest = {\n namespace: 'ai',\n version: 1,\n label: 'AI',\n icon: 'Sparkles',\n description:\n 'LLM provider, model, credentials, and embedder configuration used by ' +\n 'the platform AI and knowledge services. Provider SDK packages (e.g. ' +\n '@ai-sdk/openai for chat, @objectstack/embedder-openai for embeddings) ' +\n 'must be installed on the host for the chosen provider to be loadable at runtime.',\n scope: 'global',\n readPermission: 'manage_platform_settings',\n writePermission: 'manage_platform_settings',\n category: 'Infrastructure',\n order: 30,\n specifiers: [\n // ── Provider selection ────────────────────────────────────────\n { type: 'group', id: 'provider', label: 'Provider', required: false,\n description: 'Choose the LLM backend. Memory mode echoes input — useful for tests but never for production.' },\n { type: 'select', key: 'provider', label: 'Provider', required: true, default: 'memory',\n options: [\n { value: 'memory', label: 'Memory (echo — testing only)' },\n { value: 'gateway', label: 'Vercel AI Gateway' },\n { value: 'openai', label: 'OpenAI' },\n { value: 'anthropic', label: 'Anthropic' },\n { value: 'google', label: 'Google Generative AI' },\n // Below: providers expose an OpenAI-compatible Chat Completions API,\n // so they reuse the @ai-sdk/openai SDK with a preset base_url. The\n // plugin's buildAdapterFromValues maps these onto provider=\"openai\"\n // + an auto-filled openai_base_url at runtime.\n { value: 'deepseek', label: 'DeepSeek (OpenAI-compatible)' },\n { value: 'dashscope', label: '阿里通义 DashScope (OpenAI-compatible)' },\n { value: 'cloudflare', label: 'Cloudflare AI Gateway (OpenAI-compatible)' },\n { value: 'siliconflow', label: '硅基流动 SiliconFlow (OpenAI-compatible)' },\n { value: 'openrouter', label: 'OpenRouter (OpenAI-compatible)' },\n ],\n },\n\n // ── Vercel AI Gateway ─────────────────────────────────────────\n { type: 'group', id: 'gateway', label: 'Vercel AI Gateway', required: false,\n visible: \"${data.provider === 'gateway'}\",\n description: 'Multi-provider router. The model spec follows `provider/model`, e.g. `openai/gpt-4o`.' },\n { type: 'text', key: 'gateway_model', label: 'Gateway model', required: true,\n description: 'Forwarded as AI_GATEWAY_MODEL. Format: provider/model, e.g. openai/gpt-4o or anthropic/claude-sonnet-4.6.',\n pattern: '^[A-Za-z0-9_-]+\\\\/[A-Za-z0-9._:-]+$',\n visible: \"${data.provider === 'gateway'}\" },\n { type: 'password', key: 'gateway_api_key', label: 'Gateway API key',\n required: false, encrypted: true,\n description: 'Optional — required only if the gateway enforces auth.',\n visible: \"${data.provider === 'gateway'}\" },\n\n // ── OpenAI ───────────────────────────────────────────────────\n { type: 'group', id: 'openai', label: 'OpenAI', required: false,\n visible: \"${data.provider === 'openai'}\" },\n { type: 'password', key: 'openai_api_key', label: 'OpenAI API key',\n required: true, encrypted: true,\n description: 'Forwarded as OPENAI_API_KEY. Stored encrypted at rest.',\n visible: \"${data.provider === 'openai'}\" },\n { type: 'text', key: 'openai_model', label: 'Model', required: false, default: 'gpt-4o',\n description: 'Default model id. Per-agent overrides take precedence.',\n visible: \"${data.provider === 'openai'}\" },\n { type: 'text', key: 'openai_base_url', label: 'Base URL', required: false,\n description: 'Override for Azure OpenAI or self-hosted gateways. Leave blank for api.openai.com.',\n visible: \"${data.provider === 'openai'}\" },\n\n // ── Anthropic ────────────────────────────────────────────────\n { type: 'group', id: 'anthropic', label: 'Anthropic', required: false,\n visible: \"${data.provider === 'anthropic'}\" },\n { type: 'password', key: 'anthropic_api_key', label: 'Anthropic API key',\n required: true, encrypted: true,\n description: 'Forwarded as ANTHROPIC_API_KEY. Stored encrypted at rest.',\n visible: \"${data.provider === 'anthropic'}\" },\n { type: 'text', key: 'anthropic_model', label: 'Model', required: false,\n default: 'claude-sonnet-4-20250514',\n visible: \"${data.provider === 'anthropic'}\" },\n\n // ── Google Generative AI ─────────────────────────────────────\n { type: 'group', id: 'google', label: 'Google', required: false,\n visible: \"${data.provider === 'google'}\" },\n { type: 'password', key: 'google_api_key', label: 'Google API key',\n required: true, encrypted: true,\n description: 'Forwarded as GOOGLE_GENERATIVE_AI_API_KEY. Stored encrypted at rest.',\n visible: \"${data.provider === 'google'}\" },\n { type: 'text', key: 'google_model', label: 'Model', required: false,\n default: 'gemini-2.0-flash',\n visible: \"${data.provider === 'google'}\" },\n\n // ── OpenAI-compatible presets (DeepSeek / DashScope / Cloudflare / …) ──\n //\n // These providers all expose `/v1/chat/completions` in OpenAI shape, so\n // we reuse the `@ai-sdk/openai` SDK with a preset base URL. The plugin\n // normalises `provider=deepseek` (etc.) to `provider=openai` at adapter\n // construction time, injecting the right base URL and a sensible default\n // model id. Users only fill in API key + (optionally) model — the URL\n // is preset, eliminating the #1 onboarding mistake.\n { type: 'group', id: 'deepseek', label: 'DeepSeek', required: false,\n visible: \"${data.provider === 'deepseek'}\",\n description: 'OpenAI-compatible API at https://api.deepseek.com. Base URL is auto-filled.' },\n { type: 'password', key: 'deepseek_api_key', label: 'DeepSeek API key',\n required: true, encrypted: true,\n description: 'sk-... — issued at platform.deepseek.com.',\n visible: \"${data.provider === 'deepseek'}\" },\n { type: 'text', key: 'deepseek_model', label: 'Model', required: false,\n default: 'deepseek-chat',\n description: 'Examples: deepseek-chat (V3), deepseek-reasoner (R1 thinking).',\n visible: \"${data.provider === 'deepseek'}\" },\n\n { type: 'group', id: 'dashscope', label: '阿里通义 DashScope', required: false,\n visible: \"${data.provider === 'dashscope'}\",\n description: 'OpenAI-compatible endpoint at dashscope.aliyuncs.com/compatible-mode/v1. Base URL is auto-filled.' },\n { type: 'password', key: 'dashscope_api_key', label: 'DashScope API key',\n required: true, encrypted: true,\n description: 'sk-... — issued at dashscope.console.aliyun.com.',\n visible: \"${data.provider === 'dashscope'}\" },\n { type: 'text', key: 'dashscope_model', label: 'Model', required: false,\n default: 'qwen-plus',\n description: 'Examples: qwen-plus, qwen-max, qwen3-max, qwen-turbo.',\n visible: \"${data.provider === 'dashscope'}\" },\n\n { type: 'group', id: 'cloudflare', label: 'Cloudflare AI Gateway', required: false,\n visible: \"${data.provider === 'cloudflare'}\",\n description:\n 'Uses the /compat endpoint so the model id is `provider/model` (e.g. ' +\n '`openai/gpt-4o-mini`, `anthropic/claude-3-5-sonnet`, `deepseek/deepseek-chat`). ' +\n 'Note: alibaba/qwen* is NOT supported by Cloudflare /compat — use the DashScope provider for Qwen.' },\n { type: 'text', key: 'cloudflare_account_id', label: 'Cloudflare account id', required: true,\n description: 'The 32-char hex id from your Cloudflare dashboard URL.',\n visible: \"${data.provider === 'cloudflare'}\" },\n { type: 'text', key: 'cloudflare_gateway_id', label: 'Gateway id', required: false, default: 'default',\n description: 'Gateway name configured in Cloudflare → AI Gateway. Defaults to `default`.',\n visible: \"${data.provider === 'cloudflare'}\" },\n { type: 'password', key: 'cloudflare_api_key', label: 'Cloudflare AI Gateway token',\n required: true, encrypted: true,\n description: 'Issued in AI Gateway → \"API tokens\" tab (cfut_… or sk_…).',\n visible: \"${data.provider === 'cloudflare'}\" },\n { type: 'text', key: 'cloudflare_model', label: 'Model', required: false,\n default: 'openai/gpt-4o-mini',\n pattern: '^[A-Za-z0-9_-]+\\\\/[A-Za-z0-9._:@-]+$',\n description:\n 'Format: provider/model. Allowed providers (per Cloudflare /compat): anthropic, openai, groq, ' +\n 'mistral, cohere, perplexity, workers-ai, google-ai-studio, vertex, grok, deepseek, cerebras, baseten, parallel.',\n visible: \"${data.provider === 'cloudflare'}\" },\n\n { type: 'group', id: 'siliconflow', label: '硅基流动 SiliconFlow', required: false,\n visible: \"${data.provider === 'siliconflow'}\",\n description: 'OpenAI-compatible endpoint at api.siliconflow.cn/v1. Base URL is auto-filled.' },\n { type: 'password', key: 'siliconflow_api_key', label: 'SiliconFlow API key',\n required: true, encrypted: true,\n visible: \"${data.provider === 'siliconflow'}\" },\n { type: 'text', key: 'siliconflow_model', label: 'Model', required: false,\n default: 'Qwen/Qwen2.5-7B-Instruct',\n description: 'Examples: Qwen/Qwen2.5-72B-Instruct, deepseek-ai/DeepSeek-V3, meta-llama/Meta-Llama-3.1-8B-Instruct.',\n visible: \"${data.provider === 'siliconflow'}\" },\n\n { type: 'group', id: 'openrouter', label: 'OpenRouter', required: false,\n visible: \"${data.provider === 'openrouter'}\",\n description: 'Multi-provider router at openrouter.ai/api/v1. Base URL is auto-filled.' },\n { type: 'password', key: 'openrouter_api_key', label: 'OpenRouter API key',\n required: true, encrypted: true,\n description: 'sk-or-...',\n visible: \"${data.provider === 'openrouter'}\" },\n { type: 'text', key: 'openrouter_model', label: 'Model', required: false,\n default: 'openai/gpt-4o-mini',\n description: 'Format: provider/model (e.g. anthropic/claude-3.5-sonnet, deepseek/deepseek-chat).',\n visible: \"${data.provider === 'openrouter'}\" },\n\n // ── Generation defaults ──────────────────────────────────────\n { type: 'group', id: 'defaults', label: 'Generation defaults', required: false,\n description: 'Applied when an agent or chat request does not specify its own value.',\n visible: \"${data.provider !== 'memory'}\" },\n { type: 'slider', key: 'temperature', label: 'Temperature',\n required: false, default: 0.7, min: 0, max: 2, step: 0.1,\n description: '0 = deterministic, 2 = highly creative.',\n visible: \"${data.provider !== 'memory'}\" },\n { type: 'number', key: 'max_tokens', label: 'Max output tokens',\n required: false, default: 4096, min: 1, max: 1048576,\n description: 'Hard cap on tokens generated per response.',\n visible: \"${data.provider !== 'memory'}\" },\n { type: 'number', key: 'request_timeout_ms', label: 'Request timeout (ms)',\n required: false, default: 60000, min: 1000, max: 600000,\n visible: \"${data.provider !== 'memory'}\" },\n\n // ── Conversation titles ──────────────────────────────────────\n // After the first assistant turn lands, service-ai fires a one-shot\n // LLM call that asks the model to produce a ≤16-char title and\n // PATCHes it onto the conversation. Without this every row in the\n // sidebar shows \"New conversation\" + a truncated preview.\n { type: 'group', id: 'titles', label: 'Conversation titles', required: false,\n description: 'Auto-generate a short summary title for new conversations.',\n visible: \"${data.provider !== 'memory'}\" },\n { type: 'toggle', key: 'title_generation_enabled', label: 'Auto-summarize conversation titles',\n required: false, default: true,\n description:\n 'When on, the LLM is asked to produce a short title after the first assistant ' +\n 'reply. Disable to save tokens, or leave the title blank to let users name ' +\n 'conversations manually.',\n visible: \"${data.provider !== 'memory'}\" },\n { type: 'number', key: 'title_max_length', label: 'Title max length (chars)',\n required: false, default: 16, min: 8, max: 80,\n description: 'Hard cap on the generated title. Anything longer is truncated server-side.',\n visible: \"${data.provider !== 'memory' && data.title_generation_enabled !== false}\" },\n\n // ── Observability ────────────────────────────────────────────\n { type: 'group', id: 'observability', label: 'Observability', required: false },\n { type: 'toggle', key: 'trace_enabled', label: 'Record traces',\n required: false, default: true,\n description: 'Persist prompt/response traces to sys_ai_trace for debugging and replay.' },\n { type: 'toggle', key: 'log_prompts', label: 'Log full prompts',\n required: false, default: false,\n description: 'Include rendered prompts (not just metadata) in trace rows. ⚠ May leak PII — disable in regulated environments.' },\n\n // ── Probe ────────────────────────────────────────────────────\n { type: 'action_button', id: 'test', label: 'Test connection',\n required: false, icon: 'Plug',\n handler: { kind: 'http', method: 'POST', url: '/api/settings/ai/test' } },\n // Escape hatch: clears every saved row in this namespace so the\n // runtime falls back to env auto-detection (AI_GATEWAY_MODEL /\n // OPENAI_API_KEY / …). Without it, a broken saved config can only\n // be removed by editing sys_setting by hand.\n { type: 'action_button', id: 'reset', label: 'Reset to environment defaults',\n required: false, icon: 'RotateCcw',\n handler: { kind: 'http', method: 'POST', url: '/api/settings/ai/reset' } },\n\n // ════════════════════════════════════════════════════════════════\n // Embedder — text → vector provider used by knowledge / RAG.\n // Decoupled from the chat provider above so an organisation can\n // mix-and-match (e.g. OpenAI for chat + 阿里通义 for embeddings).\n //\n // The preset list mirrors @objectstack/embedder-openai's\n // OPENAI_COMPATIBLE_PRESETS so a UI dropdown maps 1:1 to a\n // runtime baseUrl. The \"none\" choice is the explicit opt-out\n // for instances that disable knowledge / RAG entirely.\n // ════════════════════════════════════════════════════════════════\n { type: 'group', id: 'embedder', label: 'Embedder', required: false,\n description:\n 'Text → vector provider used by knowledge sources and RAG. ' +\n 'Independent from the chat provider above — mix providers freely ' +\n '(e.g. OpenAI for chat + 阿里通义 for embeddings).' },\n { type: 'select', key: 'embedder_provider', label: 'Provider',\n required: false, default: 'none',\n options: [\n { value: 'none', label: 'Disabled (no embeddings)' },\n { value: 'openai', label: 'OpenAI' },\n { value: 'azure', label: 'Azure OpenAI' },\n { value: 'dashscope', label: '阿里通义 DashScope' },\n { value: 'zhipu', label: '智谱 BigModel' },\n { value: 'siliconflow', label: '硅基流动 SiliconFlow' },\n { value: 'doubao', label: '火山引擎 Doubao' },\n { value: 'minimax', label: 'MiniMax' },\n { value: 'ollama', label: 'Ollama (local)' },\n { value: 'custom', label: 'Custom (OpenAI-compatible)' },\n ],\n },\n { type: 'password', key: 'embedder_api_key', label: 'Embedder API key',\n required: false, encrypted: true,\n description: 'Bearer token sent as Authorization header. For Ollama any non-empty value works.',\n visible: \"${data.embedder_provider && data.embedder_provider !== 'none'}\" },\n { type: 'text', key: 'embedder_model', label: 'Model',\n required: false,\n description:\n 'Examples — OpenAI: text-embedding-3-small · 阿里通义: text-embedding-v3 · ' +\n '智谱: embedding-3 · 硅基流动: BAAI/bge-m3 · Ollama: bge-m3',\n visible: \"${data.embedder_provider && data.embedder_provider !== 'none'}\" },\n { type: 'text', key: 'embedder_base_url', label: 'Base URL',\n required: false,\n description:\n 'Endpoint root (without /embeddings). Auto-filled from preset; ' +\n 'override for proxies or self-hosted gateways.',\n visible: \"${data.embedder_provider === 'custom' || data.embedder_provider === 'azure'}\" },\n { type: 'number', key: 'embedder_dimensions', label: 'Dimensions',\n required: false, min: 1, max: 8192,\n description:\n 'Override output dimensionality (Matryoshka models only — OpenAI v3, 智谱 embedding-3, BGE-m3 dense). ' +\n 'Leave blank to use the model default.',\n visible: \"${data.embedder_provider && data.embedder_provider !== 'none'}\" },\n { type: 'number', key: 'embedder_batch_size', label: 'Batch size',\n required: false, default: 64, min: 1, max: 2048,\n description: 'Chunks per embed() call. Reduce if hitting provider rate / size limits.',\n visible: \"${data.embedder_provider && data.embedder_provider !== 'none'}\" },\n { type: 'action_button', id: 'test_embedder', label: 'Test embedder',\n required: false, icon: 'Plug',\n handler: { kind: 'http', method: 'POST', url: '/api/settings/ai/test_embedder' } },\n ],\n};\n\n/** AI — provider / model / credentials configuration. */\nexport const aiSettingsManifest = manifest as unknown as SettingsManifest;\n\n/**\n * Built-in fallback action handler for `ai/test`. The real\n * implementation that issues a live `chat()` round-trip lives in\n * `@objectstack/service-ai` and overrides this stub via\n * `registerAction` on `kernel:ready` (mirrors the storage pattern).\n *\n * This fallback only validates the form so the button is still useful\n * when the AI plugin is absent (e.g. in a unit-test kernel that mounts\n * settings only).\n */\nexport const aiTestActionHandler: SettingsActionHandler = async ({ values, payload }) => {\n // The Settings UI may POST the current (possibly unsaved) form state\n // either as `{ values: {...} }` (nested) or as a bare `{ key: value }`\n // map (Studio default). Prefer those over the persisted snapshot so\n // operators can validate edits before hitting \"Save\".\n const overrides = extractOverrides(payload);\n const merged: Record<string, unknown> = { ...values, ...overrides };\n const provider = String(merged.provider ?? 'memory');\n values = merged;\n if (provider === 'memory') {\n return {\n ok: true,\n severity: 'warning',\n message: 'Memory provider is an echo stub — no external call to validate. Switch to a real provider for production.',\n };\n }\n if (provider === 'gateway') {\n if (!values.gateway_model) {\n return { ok: false, severity: 'error', message: 'Gateway model is required (e.g. openai/gpt-4o).' };\n }\n return {\n ok: true,\n severity: 'info',\n message: `Vercel AI Gateway configured (model=${values.gateway_model}). Mount @objectstack/service-ai to exercise live calls.`,\n };\n }\n // Cloudflare needs more than just an API key.\n if (provider === 'cloudflare') {\n if (!values.cloudflare_account_id) {\n return { ok: false, severity: 'error', message: 'Cloudflare account id is required.' };\n }\n if (!values.cloudflare_api_key) {\n return { ok: false, severity: 'error', message: 'Cloudflare AI Gateway token is required.' };\n }\n const model = values.cloudflare_model ?? '(default openai/gpt-4o-mini)';\n return {\n ok: true,\n severity: 'info',\n message: `Cloudflare AI Gateway configured (model=${model}). Mount @objectstack/service-ai to exercise live calls.`,\n };\n }\n const keyField = `${provider}_api_key`;\n if (!values[keyField]) {\n return { ok: false, severity: 'error', message: `${provider} API key is required.` };\n }\n const modelField = `${provider}_model`;\n const model = values[modelField] ?? '(default)';\n return {\n ok: true,\n severity: 'info',\n message: `${provider} configured (model=${model}). Mount @objectstack/service-ai to exercise live calls.`,\n };\n};\n\n/**\n * Built-in fallback handler for `ai/test_embedder`. Real implementation\n * with a live `embed()` round-trip lives in `@objectstack/service-ai` or\n * `@objectstack/service-knowledge` and overrides this stub at runtime.\n *\n * This fallback validates form completeness only — no network call —\n * so the button is useful even when no embedder plugin is mounted.\n */\nexport const aiTestEmbedderActionHandler: SettingsActionHandler = async ({ values, payload }) => {\n const overrides = extractOverrides(payload);\n const merged: Record<string, unknown> = { ...values, ...overrides };\n const provider = String(merged.embedder_provider ?? 'none');\n\n if (provider === 'none') {\n return {\n ok: false,\n severity: 'warning',\n message: 'Embedder is disabled. Pick a provider to enable knowledge / RAG.',\n };\n }\n\n // For Ollama, an API key is conventionally `ollama` but not enforced.\n if (provider !== 'ollama' && !merged.embedder_api_key) {\n return {\n ok: false,\n severity: 'error',\n message: `${provider} embedder requires an API key.`,\n };\n }\n\n if ((provider === 'custom' || provider === 'azure') && !merged.embedder_base_url) {\n return {\n ok: false,\n severity: 'error',\n message: `${provider} embedder requires a Base URL.`,\n };\n }\n\n const model = merged.embedder_model ?? '(provider default)';\n return {\n ok: true,\n severity: 'info',\n message:\n `${provider} embedder configured (model=${model}). ` +\n 'Mount @objectstack/embedder-openai + a knowledge adapter to exercise live calls.',\n };\n};\n\nfunction extractOverrides(payload: unknown): Record<string, unknown> {\n if (!payload || typeof payload !== 'object') return {};\n const p = payload as Record<string, unknown>;\n if (p.values && typeof p.values === 'object' && p.values !== null) {\n return p.values as Record<string, unknown>;\n }\n return p;\n}\n","// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { SettingsManifest } from '@objectstack/spec/system';\nimport type { SettingsActionHandler } from '../settings-service.types.js';\n\n/**\n * Knowledge — RAG infrastructure: which adapter stores vectors, and\n * how big chunks are. The embedder itself is configured in the AI\n * namespace (see `ai.manifest.ts`) because it's shared between\n * knowledge sources and any future agent that needs to embed ad-hoc\n * inputs.\n *\n * Adapter list mirrors the plugin packages currently published:\n * - memory @objectstack/knowledge-memory (dev / test reference)\n * - turso @objectstack/knowledge-turso (libSQL native F32_BLOB —\n * works for cloud Turso AND\n * local file mode)\n * - ragflow @objectstack/knowledge-ragflow (external RAGFlow service)\n *\n * As with the AI manifest, the real adapter wiring happens in the\n * knowledge plugins; this manifest is the canonical settings surface\n * for \"what knowledge backend is wired\" and saves operators from\n * grepping defineStack() during onboarding / incident response.\n */\nconst manifest = {\n namespace: 'knowledge',\n version: 1,\n label: 'Knowledge',\n icon: 'BookOpen',\n description:\n 'Vector-store backend for RAG / knowledge sources. ' +\n '⚠ Switching adapter does NOT migrate existing indices — documents ' +\n 'indexed under the previous adapter become unreachable until ' +\n 're-indexed. The embedder is configured separately under AI.',\n scope: 'global',\n readPermission: 'manage_platform_settings',\n writePermission: 'manage_platform_settings',\n category: 'Infrastructure',\n order: 35,\n specifiers: [\n // ── Adapter selection ─────────────────────────────────────────\n { type: 'group', id: 'adapter', label: 'Backend', required: false,\n description: 'Choose where document chunks and their vectors are stored.' },\n { type: 'select', key: 'adapter', label: 'Adapter', required: true, default: 'memory',\n options: [\n { value: 'memory', label: 'In-memory (dev / test only)' },\n { value: 'turso', label: 'Turso / libSQL (cloud or local)' },\n { value: 'ragflow', label: 'RAGFlow (external)' },\n ],\n },\n\n // ── Turso / libSQL ────────────────────────────────────────────\n { type: 'group', id: 'turso', label: 'Turso / libSQL', required: false,\n visible: \"${data.adapter === 'turso'}\",\n description:\n 'Works against managed Turso (libsql://…), local file (file:./knowledge.db), ' +\n 'or in-memory (:memory:). For per-tenant cloud deployments, leave blank to ' +\n 'reuse the tenant\\'s primary libSQL connection.' },\n { type: 'text', key: 'turso_url', label: 'Connection URL', required: false,\n description: 'Examples: libsql://your-tenant.turso.io · file:./.objectstack/knowledge.db · :memory:',\n visible: \"${data.adapter === 'turso'}\" },\n { type: 'password', key: 'turso_auth_token', label: 'Auth token',\n required: false, encrypted: true,\n description: 'Only required for managed Turso URLs. Leave blank for local file / :memory:.',\n visible: \"${data.adapter === 'turso'}\" },\n\n // ── RAGFlow ───────────────────────────────────────────────────\n { type: 'group', id: 'ragflow', label: 'RAGFlow', required: false,\n visible: \"${data.adapter === 'ragflow'}\",\n description: 'External RAGFlow deployment. See https://ragflow.io for self-host instructions.' },\n { type: 'text', key: 'ragflow_base_url', label: 'Base URL', required: true,\n description: 'Example: http://localhost:9380',\n visible: \"${data.adapter === 'ragflow'}\" },\n { type: 'password', key: 'ragflow_api_key', label: 'API key',\n required: true, encrypted: true,\n visible: \"${data.adapter === 'ragflow'}\" },\n { type: 'text', key: 'ragflow_default_dataset', label: 'Default dataset id',\n required: false,\n description: 'Used when a KnowledgeSource does not specify its own RAGFlow dataset.',\n visible: \"${data.adapter === 'ragflow'}\" },\n\n // ── Indexing defaults ─────────────────────────────────────────\n { type: 'group', id: 'indexing', label: 'Indexing defaults', required: false,\n description: 'Per-source values on KnowledgeSource.adapterConfig take precedence.',\n visible: \"${data.adapter !== 'memory'}\" },\n { type: 'number', key: 'chunk_target', label: 'Target chunk size (chars)',\n required: false, default: 800, min: 64, max: 8192,\n description: 'Soft cap on chunk size in characters before token-aware splitting kicks in.',\n visible: \"${data.adapter !== 'memory'}\" },\n { type: 'number', key: 'chunk_overlap', label: 'Chunk overlap (chars)',\n required: false, default: 80, min: 0, max: 2048,\n description: 'Characters retained from the previous chunk so context survives the boundary.',\n visible: \"${data.adapter !== 'memory'}\" },\n { type: 'number', key: 'over_fetch', label: 'Over-fetch multiplier',\n required: false, default: 4, min: 1, max: 20,\n description: 'Internal `topK * overFetch` candidates fetched so JS-side metadata filtering still has rows to return.',\n visible: \"${data.adapter === 'turso'}\" },\n\n // ── Permissions ───────────────────────────────────────────────\n { type: 'group', id: 'permissions', label: 'Permissions', required: false },\n { type: 'toggle', key: 'enforce_rls', label: 'Enforce RLS on search',\n required: false, default: true,\n description:\n 'Re-check every hit against the caller\\'s record-level permissions via IDataEngine. ' +\n '⚠ Disabling skips the platform\\'s unique safeguard against vector-store data leakage — leave on in production.' },\n\n // ── Probe ─────────────────────────────────────────────────────\n { type: 'action_button', id: 'test', label: 'Test connection',\n required: false, icon: 'Plug',\n handler: { kind: 'http', method: 'POST', url: '/api/settings/knowledge/test' } },\n ],\n};\n\n/** Knowledge — RAG vector-store backend configuration. */\nexport const knowledgeSettingsManifest = manifest as unknown as SettingsManifest;\n\n/**\n * Built-in fallback handler for `knowledge/test`. The real probe with\n * a live `healthCheck()` round-trip lives in `@objectstack/service-knowledge`\n * and overrides this stub at runtime (mirrors the AI / storage patterns).\n *\n * This fallback only validates form completeness so the button is\n * usable when no knowledge adapter plugin is mounted.\n */\nexport const knowledgeTestActionHandler: SettingsActionHandler = async ({ values, payload }) => {\n const overrides = extractOverrides(payload);\n const merged: Record<string, unknown> = { ...values, ...overrides };\n const adapter = String(merged.adapter ?? 'memory');\n\n if (adapter === 'memory') {\n return {\n ok: true,\n severity: 'warning',\n message: 'In-memory adapter — no external service to probe. Indices are wiped on restart; do not use in production.',\n };\n }\n\n if (adapter === 'turso') {\n const url = merged.turso_url;\n if (!url) {\n return {\n ok: true,\n severity: 'info',\n message: 'No URL configured — adapter will reuse the tenant\\'s primary libSQL connection at runtime.',\n };\n }\n const u = String(url);\n if (u.startsWith('libsql://') && !merged.turso_auth_token) {\n return {\n ok: false,\n severity: 'error',\n message: 'Managed Turso URL requires an auth token.',\n };\n }\n return {\n ok: true,\n severity: 'info',\n message: `Turso adapter configured (${u}). Mount @objectstack/knowledge-turso to exercise live calls.`,\n };\n }\n\n if (adapter === 'ragflow') {\n if (!merged.ragflow_base_url) {\n return { ok: false, severity: 'error', message: 'RAGFlow requires a Base URL.' };\n }\n if (!merged.ragflow_api_key) {\n return { ok: false, severity: 'error', message: 'RAGFlow requires an API key.' };\n }\n return {\n ok: true,\n severity: 'info',\n message: `RAGFlow adapter configured (${merged.ragflow_base_url}). Mount @objectstack/knowledge-ragflow to exercise live calls.`,\n };\n }\n\n return { ok: false, severity: 'error', message: `Unknown adapter: ${adapter}` };\n};\n\nfunction extractOverrides(payload: unknown): Record<string, unknown> {\n if (!payload || typeof payload !== 'object') return {};\n const p = payload as Record<string, unknown>;\n if (p.values && typeof p.values === 'object' && p.values !== null) {\n return p.values as Record<string, unknown>;\n }\n return p;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { SettingsManifest } from '@objectstack/spec/system';\n\n/**\n * Localization — workspace-wide regional defaults (ADR-0053 Phase 2 follow-up).\n *\n * The single source of truth for the platform's reference timezone, language,\n * currency, and display formats. `resolveExecutionContext` reads `timezone`\n * and `locale` from here (cascade: platform default → global → tenant) onto\n * every `ExecutionContext`, so formulas (`today()`), analytics date bucketing,\n * and rendered `datetime` instants all resolve against the org's region.\n *\n * Scope is `tenant`: one org per physical tenant (ADR-0002) sets its regional\n * defaults; the manifest `default` of each key is the platform built-in, and a\n * `global` row (or `OS_LOCALIZATION_*` env) can pin a deployment-wide value.\n * Per-user overrides are intentionally out of scope for v1.\n */\nexport const localizationSettingsManifest: SettingsManifest = {\n namespace: 'localization',\n version: 1,\n label: 'Localization',\n icon: 'Globe',\n description: 'Default timezone, language, currency, and date/number formats.',\n scope: 'tenant',\n readPermission: 'setup.access',\n writePermission: 'setup.write',\n category: 'Workspace',\n order: 2,\n specifiers: [\n // ── Region ────────────────────────────────────────────────────────────\n { type: 'group', id: 'region', label: 'Region', required: false },\n {\n type: 'select', key: 'timezone', label: 'Default timezone', required: false, default: 'UTC',\n description: 'IANA zone used to resolve today()/daysFromNow, analytics date buckets, and rendered datetimes.',\n options: [\n { value: 'UTC', label: 'UTC' },\n { value: 'America/Los_Angeles', label: '(UTC−08/−07) Los Angeles' },\n { value: 'America/Denver', label: '(UTC−07/−06) Denver' },\n { value: 'America/Chicago', label: '(UTC−06/−05) Chicago' },\n { value: 'America/New_York', label: '(UTC−05/−04) New York' },\n { value: 'America/Sao_Paulo', label: '(UTC−03) São Paulo' },\n { value: 'Europe/London', label: '(UTC±00/+01) London' },\n { value: 'Europe/Paris', label: '(UTC+01/+02) Paris' },\n { value: 'Europe/Berlin', label: '(UTC+01/+02) Berlin' },\n { value: 'Europe/Moscow', label: '(UTC+03) Moscow' },\n { value: 'Asia/Dubai', label: '(UTC+04) Dubai' },\n { value: 'Asia/Kolkata', label: '(UTC+05:30) Kolkata' },\n { value: 'Asia/Singapore', label: '(UTC+08) Singapore' },\n { value: 'Asia/Shanghai', label: '(UTC+08) Shanghai' },\n { value: 'Asia/Tokyo', label: '(UTC+09) Tokyo' },\n { value: 'Australia/Sydney', label: '(UTC+10/+11) Sydney' },\n { value: 'Pacific/Auckland', label: '(UTC+12/+13) Auckland' },\n ],\n },\n {\n type: 'select', key: 'locale', label: 'Default language', required: false, default: 'en-US',\n description: 'BCP-47 locale for message catalogs and number/date formatting.',\n options: [\n { value: 'en-US', label: 'English (US)' },\n { value: 'zh-CN', label: '简体中文' },\n { value: 'ja-JP', label: '日本語' },\n { value: 'es-ES', label: 'Español (España)' },\n ],\n },\n {\n type: 'text', key: 'default_country', label: 'Default country', required: false, default: 'US',\n description: 'ISO 3166-1 alpha-2 code (e.g. US, GB, CN). Used for address and phone defaults.',\n pattern: '^[A-Za-z]{2}$', minLength: 2, maxLength: 2,\n },\n\n // ── Formats ───────────────────────────────────────────────────────────\n { type: 'group', id: 'formats', label: 'Formats', required: false },\n {\n type: 'select', key: 'date_format', label: 'Date format', required: false, default: 'YYYY-MM-DD',\n options: [\n { value: 'YYYY-MM-DD', label: '2026-06-17 (ISO)' },\n { value: 'MM/DD/YYYY', label: '06/17/2026 (US)' },\n { value: 'DD/MM/YYYY', label: '17/06/2026 (EU)' },\n { value: 'DD.MM.YYYY', label: '17.06.2026' },\n { value: 'DD-MMM-YYYY', label: '17-Jun-2026' },\n ],\n },\n {\n type: 'select', key: 'time_format', label: 'Time format', required: false, default: '24h',\n options: [\n { value: '24h', label: '24-hour (14:30)' },\n { value: '12h', label: '12-hour (2:30 PM)' },\n ],\n },\n {\n type: 'select', key: 'number_format', label: 'Number format', required: false, default: '1,234.56',\n description: 'Grouping and decimal separators for displayed numbers.',\n options: [\n { value: '1,234.56', label: '1,234.56 (comma / dot)' },\n { value: '1.234,56', label: '1.234,56 (dot / comma)' },\n { value: '1 234,56', label: '1 234,56 (space / comma)' },\n { value: '1,23,456.78', label: '1,23,456.78 (Indian)' },\n ],\n },\n {\n type: 'select', key: 'first_day_of_week', label: 'First day of week', required: false, default: 'monday',\n description: 'Anchors weekly analytics buckets and calendar grids.',\n options: [\n { value: 'monday', label: 'Monday (ISO)' },\n { value: 'sunday', label: 'Sunday' },\n { value: 'saturday', label: 'Saturday' },\n ],\n },\n\n // ── Finance ───────────────────────────────────────────────────────────\n { type: 'group', id: 'finance', label: 'Finance', required: false },\n {\n type: 'select', key: 'currency', label: 'Default currency', required: false, default: 'USD',\n description: 'ISO 4217 code applied when a currency field omits its own.',\n options: [\n { value: 'USD', label: 'USD — US Dollar' },\n { value: 'EUR', label: 'EUR — Euro' },\n { value: 'GBP', label: 'GBP — British Pound' },\n { value: 'JPY', label: 'JPY — Japanese Yen' },\n { value: 'CNY', label: 'CNY — Chinese Yuan' },\n { value: 'INR', label: 'INR — Indian Rupee' },\n { value: 'AUD', label: 'AUD — Australian Dollar' },\n { value: 'CAD', label: 'CAD — Canadian Dollar' },\n { value: 'BRL', label: 'BRL — Brazilian Real' },\n ],\n },\n {\n type: 'select', key: 'fiscal_year_start', label: 'Fiscal year start', required: false, default: 'january',\n description: 'First month of the fiscal year — drives \"this quarter / fiscal year\" in reports.',\n options: [\n { value: 'january', label: 'January' },\n { value: 'february', label: 'February' },\n { value: 'march', label: 'March' },\n { value: 'april', label: 'April' },\n { value: 'may', label: 'May' },\n { value: 'june', label: 'June' },\n { value: 'july', label: 'July' },\n { value: 'august', label: 'August' },\n { value: 'september', label: 'September' },\n { value: 'october', label: 'October' },\n { value: 'november', label: 'November' },\n { value: 'december', label: 'December' },\n ],\n },\n ],\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { SettingsManifest } from '@objectstack/spec/system';\n\n/**\n * Company — the workspace's legal organization identity.\n *\n * Distinct from `branding` (the public-facing workspace name / logo / theme):\n * this is the **legal entity** — registered name, address, tax IDs, and the\n * primary contact. Downstream consumers are invoices/receipts, email footers\n * (CAN-SPAM requires a physical postal address), contracts, and compliance\n * exports. Benchmarked against Salesforce \"Company Information\" and Stripe's\n * business profile.\n *\n * Scope is `tenant`: one org per physical tenant (ADR-0002).\n */\nexport const companySettingsManifest: SettingsManifest = {\n namespace: 'company',\n version: 1,\n label: 'Company',\n icon: 'Building2',\n description: 'Legal entity identity — registered name, address, tax IDs, and primary contact.',\n scope: 'tenant',\n readPermission: 'setup.access',\n writePermission: 'setup.write',\n category: 'Workspace',\n order: 3,\n specifiers: [\n // ── Identity ──────────────────────────────────────────────────────────\n { type: 'group', id: 'identity', label: 'Identity', required: false },\n {\n type: 'text', key: 'legal_name', label: 'Legal name', required: false,\n description: 'Registered legal name of the organization (may differ from the workspace name).',\n maxLength: 200,\n },\n {\n type: 'text', key: 'registration_number', label: 'Registration number', required: false,\n description: 'Company registration / incorporation number (e.g. EIN, company no.).',\n maxLength: 80,\n },\n {\n type: 'text', key: 'tax_id', label: 'Tax / VAT ID', required: false,\n description: 'Tax identifier shown on invoices (e.g. VAT, GST, ABN).',\n maxLength: 80,\n },\n\n // ── Registered address ────────────────────────────────────────────────\n { type: 'group', id: 'address', label: 'Registered address', required: false },\n { type: 'text', key: 'address_line1', label: 'Address line 1', required: false, maxLength: 200 },\n { type: 'text', key: 'address_line2', label: 'Address line 2', required: false, maxLength: 200 },\n { type: 'text', key: 'city', label: 'City', required: false, maxLength: 120 },\n { type: 'text', key: 'state', label: 'State / Province', required: false, maxLength: 120 },\n { type: 'text', key: 'postal_code', label: 'Postal code', required: false, maxLength: 32 },\n {\n type: 'text', key: 'country', label: 'Country', required: false,\n description: 'ISO 3166-1 alpha-2 code (e.g. US, GB, CN).',\n pattern: '^[A-Za-z]{2}$', minLength: 2, maxLength: 2,\n },\n\n // ── Contact ───────────────────────────────────────────────────────────\n { type: 'group', id: 'contact', label: 'Contact', required: false },\n {\n type: 'text', key: 'phone', label: 'Phone', required: false,\n description: 'Primary business phone (E.164 recommended, e.g. +1 415 555 0100).',\n maxLength: 40,\n },\n {\n type: 'url', key: 'website', label: 'Website', required: false,\n description: 'Example: https://example.com',\n },\n { type: 'text', key: 'primary_contact_name', label: 'Primary contact name', required: false, maxLength: 120 },\n {\n type: 'email', key: 'primary_contact_email', label: 'Primary contact email', required: false,\n description: 'Example: ops@example.com',\n },\n ],\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/** Reference manifests bundled with service-settings. */\nexport { authSettingsManifest } from './auth.manifest.js';\nexport { mailSettingsManifest, mailTestActionHandler } from './mail.manifest.js';\nexport { brandingSettingsManifest } from './branding.manifest.js';\nexport { featureFlagsSettingsManifest } from './feature-flags.manifest.js';\nexport { storageSettingsManifest, storageTestActionHandler } from './storage.manifest.js';\nexport {\n aiSettingsManifest,\n aiTestActionHandler,\n aiTestEmbedderActionHandler,\n} from './ai.manifest.js';\nexport { knowledgeSettingsManifest, knowledgeTestActionHandler } from './knowledge.manifest.js';\nexport { localizationSettingsManifest } from './localization.manifest.js';\nexport { companySettingsManifest } from './company.manifest.js';\n\nimport { authSettingsManifest } from './auth.manifest.js';\nimport { mailSettingsManifest } from './mail.manifest.js';\nimport { brandingSettingsManifest } from './branding.manifest.js';\nimport { featureFlagsSettingsManifest } from './feature-flags.manifest.js';\nimport { storageSettingsManifest } from './storage.manifest.js';\nimport { aiSettingsManifest } from './ai.manifest.js';\nimport { knowledgeSettingsManifest } from './knowledge.manifest.js';\nimport { localizationSettingsManifest } from './localization.manifest.js';\nimport { companySettingsManifest } from './company.manifest.js';\n\n/** Convenience aggregate — pass to `SettingsServicePlugin({ manifests })`. */\nexport const builtinSettingsManifests = [\n brandingSettingsManifest,\n companySettingsManifest,\n localizationSettingsManifest,\n authSettingsManifest,\n mailSettingsManifest,\n storageSettingsManifest,\n aiSettingsManifest,\n knowledgeSettingsManifest,\n featureFlagsSettingsManifest,\n];\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { TranslationData } from '@objectstack/spec/system';\n\n/**\n * English (en) — built-in settings manifest translations.\n *\n * Mirrors literals in `manifests/{mail,branding,feature-flags,storage}.manifest.ts`.\n * Keeping them explicit here lets the resolver chain (locale → fallback → literal)\n * always have at least an English entry to fall back to.\n */\nexport const en: TranslationData = {\n settingsCommon: {\n sourceLabels: {\n env: 'Env',\n global: 'Global',\n tenant: 'Tenant',\n user: 'User',\n default: 'Default',\n },\n },\n settings: {\n mail: {\n title: 'Mail Delivery',\n description: 'SMTP and transactional email provider configuration.',\n groups: {\n provider: { title: 'Provider', description: 'Choose how this workspace sends outbound email.' },\n smtp: { title: 'SMTP' },\n api_key: { title: 'API key' },\n from_address: { title: 'From address' },\n },\n keys: {\n provider: {\n label: 'Provider',\n options: {\n smtp: 'SMTP',\n sendgrid: 'SendGrid',\n ses: 'Amazon SES',\n postmark: 'Postmark',\n },\n },\n smtp_host: { label: 'Host', help: 'Example: smtp.example.com' },\n smtp_port: { label: 'Port' },\n smtp_secure: { label: 'Use TLS' },\n smtp_user: { label: 'Username' },\n smtp_password: { label: 'Password' },\n api_key: { label: 'API key' },\n from_email: { label: 'From email', help: 'Example: no-reply@example.com' },\n from_name: { label: 'From name' },\n },\n actions: {\n test: { label: 'Send test email' },\n },\n },\n\n branding: {\n title: 'Branding',\n description: 'Workspace name, logo, and accent colour.',\n groups: {\n identity: { title: 'Identity' },\n appearance: { title: 'Appearance' },\n },\n keys: {\n workspace_name: { label: 'Workspace name' },\n support_email: { label: 'Support email', help: 'Example: support@example.com' },\n theme_mode: {\n label: 'Default theme',\n options: { light: 'Light', dark: 'Dark', system: 'Match system' },\n },\n accent_color: { label: 'Accent colour' },\n logo_url: { label: 'Logo URL', help: 'Example: https://…/logo.svg' },\n },\n },\n\n company: {\n title: 'Company',\n description: 'Legal entity identity — registered name, address, tax IDs, and primary contact.',\n groups: {\n identity: { title: 'Identity' },\n address: { title: 'Registered address' },\n contact: { title: 'Contact' },\n },\n keys: {\n legal_name: { label: 'Legal name', help: 'Registered legal name (may differ from the workspace name).' },\n registration_number: { label: 'Registration number', help: 'Company registration / incorporation number (e.g. EIN).' },\n tax_id: { label: 'Tax / VAT ID', help: 'Shown on invoices (e.g. VAT, GST, ABN).' },\n address_line1: { label: 'Address line 1' },\n address_line2: { label: 'Address line 2' },\n city: { label: 'City' },\n state: { label: 'State / Province' },\n postal_code: { label: 'Postal code' },\n country: { label: 'Country', help: 'ISO 3166-1 alpha-2 code (e.g. US, GB, CN).' },\n phone: { label: 'Phone', help: 'E.164 recommended, e.g. +1 415 555 0100.' },\n website: { label: 'Website', help: 'Example: https://example.com' },\n primary_contact_name: { label: 'Primary contact name' },\n primary_contact_email: { label: 'Primary contact email', help: 'Example: ops@example.com' },\n },\n },\n\n localization: {\n title: 'Localization',\n description: 'Default timezone, language, currency, and date/number formats.',\n groups: {\n region: { title: 'Region' },\n formats: { title: 'Formats' },\n finance: { title: 'Finance' },\n },\n keys: {\n timezone: { label: 'Default timezone', help: 'IANA zone for today()/daysFromNow, analytics date buckets, and rendered datetimes.' },\n locale: { label: 'Default language', help: 'BCP-47 locale for message catalogs and number/date formatting.' },\n default_country: { label: 'Default country', help: 'ISO 3166-1 alpha-2 code (e.g. US, GB, CN).' },\n date_format: { label: 'Date format' },\n time_format: { label: 'Time format', options: { '24h': '24-hour (14:30)', '12h': '12-hour (2:30 PM)' } },\n number_format: { label: 'Number format' },\n first_day_of_week: { label: 'First day of week', options: { monday: 'Monday (ISO)', sunday: 'Sunday', saturday: 'Saturday' } },\n currency: { label: 'Default currency' },\n fiscal_year_start: { label: 'Fiscal year start' },\n },\n },\n\n auth: {\n title: 'Authentication',\n description: 'Sign-in, registration, and built-in auth feature controls.',\n groups: {\n email_password: {\n title: 'Email and password',\n description: 'Control local email/password sign-in and self-service registration.',\n },\n password_policy: {\n title: 'Password policy',\n description: 'Length bounds enforced by the auth provider on sign-up and password reset.',\n },\n sessions: {\n title: 'Sessions',\n description: 'How long a signed-in session stays valid.',\n },\n social: {\n title: 'Social sign-in',\n description:\n 'Configure the built-in Google sign-in provider. Deployment env vars still win.',\n },\n },\n keys: {\n email_password_enabled: { label: 'Enable email/password login' },\n signup_enabled: { label: 'Allow self-service registration' },\n require_email_verification: { label: 'Require email verification' },\n password_min_length: { label: 'Minimum password length' },\n password_max_length: { label: 'Maximum password length', help: 'Guards against denial-of-service via very long password hashing.' },\n session_expiry_days: { label: 'Session lifetime (days)', help: 'A session expires this many days after sign-in.' },\n session_refresh_days: { label: 'Refresh threshold (days)', help: 'An active session is extended when it is older than this.' },\n google_enabled: {\n label: 'Enable Google login',\n help: 'Requires a Google OAuth client ID and secret from Google Cloud Console.',\n },\n google_client_id: {\n label: 'Google client ID',\n help: 'OAuth client ID from Google Cloud Console. GOOGLE_CLIENT_ID can also be set on the server.',\n },\n google_client_secret: {\n label: 'Google client secret',\n help: 'Stored encrypted at rest. GOOGLE_CLIENT_SECRET can also be set on the server.',\n },\n },\n },\n\n feature_flags: {\n title: 'Feature Flags',\n description: 'Toggle experimental and beta features for this workspace.',\n groups: {\n productivity: { title: 'Productivity' },\n collaboration: { title: 'Collaboration' },\n },\n keys: {\n ai_enabled: {\n label: 'AI Assistant',\n help: 'Enables the in-app AI assistant panel.',\n },\n kanban_swimlanes: { label: 'Kanban swimlanes' },\n realtime_cursors: { label: 'Realtime cursors' },\n inline_comments: { label: 'Inline comments' },\n },\n },\n\n storage: {\n title: 'File Storage',\n description:\n 'Backend used for attachments, exports, and user uploads. ' +\n '⚠ Switching adapter does not migrate existing files — files ' +\n 'uploaded under the previous adapter become unreachable through ' +\n 'the new one.',\n groups: {\n adapter: { title: 'Backend', description: 'Choose where uploaded files are stored.' },\n local: { title: 'Local' },\n s3: { title: 'S3' },\n limits: { title: 'Limits' },\n },\n keys: {\n adapter: {\n label: 'Adapter',\n options: { local: 'Local filesystem', s3: 'S3 / S3-compatible' },\n },\n local_root: { label: 'Root directory',\n help: 'Filesystem path under which files are stored. Relative paths resolve from the server CWD.' },\n s3_bucket: { label: 'Bucket',\n help: 'Shared host bucket. Per-environment files are namespaced via the projects/<environmentId>/ prefix.' },\n s3_region: { label: 'Region', help: 'Example: us-east-1' },\n s3_endpoint: { label: 'Endpoint',\n help: 'Custom endpoint for S3-compatible providers (R2, MinIO, Wasabi). Leave blank for AWS S3.' },\n s3_access_key_id: { label: 'Access key ID' },\n s3_secret_access_key: { label: 'Secret access key' },\n s3_force_path_style: { label: 'Force path-style URLs',\n help: 'Enable for MinIO and most S3-compatible providers; disable for AWS S3.' },\n presigned_ttl: { label: 'Presigned URL TTL (seconds)' },\n session_ttl: { label: 'Upload session TTL (seconds)',\n help: 'How long a chunked-upload session stays resumable.' },\n max_upload_mb: { label: 'Max upload size (MB)' },\n },\n actions: {\n test: { label: 'Test connection' },\n },\n },\n\n ai: {\n title: 'AI & Embedder',\n description:\n 'LLM provider, model, credentials, and embedder configuration used by ' +\n 'the platform AI and knowledge services.',\n groups: {\n provider: { title: 'Provider',\n description: 'Choose the LLM backend. Memory mode echoes input — useful for tests but never for production.' },\n gateway: { title: 'Vercel AI Gateway',\n description: 'Multi-provider router. The model spec follows `provider/model`, e.g. `openai/gpt-4o`.' },\n openai: { title: 'OpenAI' },\n anthropic: { title: 'Anthropic' },\n google: { title: 'Google' },\n defaults: { title: 'Generation defaults',\n description: 'Applied when an agent or chat request does not specify its own value.' },\n observability: { title: 'Observability' },\n embedder: { title: 'Embedder',\n description:\n 'Text → vector provider used by knowledge sources and RAG. ' +\n 'Independent from the chat provider above.' },\n },\n keys: {\n provider: {\n label: 'Provider',\n options: {\n memory: 'Memory (echo — testing only)',\n gateway: 'Vercel AI Gateway',\n openai: 'OpenAI',\n anthropic: 'Anthropic',\n google: 'Google Generative AI',\n },\n },\n gateway_model: { label: 'Gateway model',\n help: 'Forwarded as AI_GATEWAY_MODEL. Example: openai/gpt-4o' },\n gateway_api_key: { label: 'Gateway API key',\n help: 'Optional — required only if the gateway enforces auth.' },\n openai_api_key: { label: 'OpenAI API key',\n help: 'Forwarded as OPENAI_API_KEY. Stored encrypted at rest.' },\n openai_model: { label: 'Model',\n help: 'Default model id. Per-agent overrides take precedence.' },\n openai_base_url: { label: 'Base URL',\n help: 'Override for Azure OpenAI or self-hosted gateways. Leave blank for api.openai.com.' },\n anthropic_api_key: { label: 'Anthropic API key',\n help: 'Forwarded as ANTHROPIC_API_KEY. Stored encrypted at rest.' },\n anthropic_model: { label: 'Model' },\n google_api_key: { label: 'Google API key',\n help: 'Forwarded as GOOGLE_GENERATIVE_AI_API_KEY. Stored encrypted at rest.' },\n google_model: { label: 'Model' },\n temperature: { label: 'Temperature',\n help: '0 = deterministic, 2 = highly creative.' },\n max_tokens: { label: 'Max output tokens',\n help: 'Hard cap on tokens generated per response.' },\n request_timeout_ms: { label: 'Request timeout (ms)' },\n trace_enabled: { label: 'Record traces',\n help: 'Persist prompt/response traces to sys_ai_trace for debugging and replay.' },\n log_prompts: { label: 'Log full prompts',\n help: 'Include rendered prompts (not just metadata) in trace rows. ⚠ May leak PII — disable in regulated environments.' },\n embedder_provider: {\n label: 'Provider',\n options: {\n none: 'Disabled (no embeddings)',\n openai: 'OpenAI',\n azure: 'Azure OpenAI',\n dashscope: '阿里通义 DashScope',\n zhipu: '智谱 BigModel',\n siliconflow: '硅基流动 SiliconFlow',\n doubao: '火山引擎 Doubao',\n minimax: 'MiniMax',\n ollama: 'Ollama (local)',\n custom: 'Custom (OpenAI-compatible)',\n },\n },\n embedder_api_key: { label: 'Embedder API key',\n help: 'Bearer token sent as Authorization header. For Ollama any non-empty value works.' },\n embedder_model: { label: 'Model',\n help: 'Examples — OpenAI: text-embedding-3-small · 阿里通义: text-embedding-v3 · 智谱: embedding-3 · 硅基流动: BAAI/bge-m3 · Ollama: bge-m3' },\n embedder_base_url: { label: 'Base URL',\n help: 'Endpoint root (without /embeddings). Auto-filled from preset; override for proxies or self-hosted gateways.' },\n embedder_dimensions: { label: 'Dimensions',\n help: 'Override output dimensionality (Matryoshka models only). Leave blank to use the model default.' },\n embedder_batch_size: { label: 'Batch size',\n help: 'Chunks per embed() call. Reduce if hitting provider rate / size limits.' },\n },\n actions: {\n test: { label: 'Test connection' },\n test_embedder: { label: 'Test embedder' },\n },\n },\n\n knowledge: {\n title: 'Knowledge',\n description:\n 'Vector-store backend for RAG / knowledge sources. ' +\n '⚠ Switching adapter does NOT migrate existing indices.',\n groups: {\n adapter: { title: 'Backend',\n description: 'Choose where document chunks and their vectors are stored.' },\n turso: { title: 'Turso / libSQL',\n description: 'Works against managed Turso, local file, or in-memory.' },\n ragflow: { title: 'RAGFlow',\n description: 'External RAGFlow deployment. See https://ragflow.io for self-host instructions.' },\n indexing: { title: 'Indexing defaults',\n description: 'Per-source values on KnowledgeSource.adapterConfig take precedence.' },\n permissions: { title: 'Permissions' },\n },\n keys: {\n adapter: {\n label: 'Adapter',\n options: {\n memory: 'In-memory (dev / test only)',\n turso: 'Turso / libSQL (cloud or local)',\n ragflow: 'RAGFlow (external)',\n },\n },\n turso_url: { label: 'Connection URL',\n help: 'Examples: libsql://your-tenant.turso.io · file:./.objectstack/knowledge.db · :memory:' },\n turso_auth_token: { label: 'Auth token',\n help: 'Only required for managed Turso URLs.' },\n ragflow_base_url: { label: 'Base URL', help: 'Example: http://localhost:9380' },\n ragflow_api_key: { label: 'API key' },\n ragflow_default_dataset: { label: 'Default dataset id',\n help: 'Used when a KnowledgeSource does not specify its own RAGFlow dataset.' },\n chunk_target: { label: 'Target chunk size (chars)',\n help: 'Soft cap on chunk size before token-aware splitting kicks in.' },\n chunk_overlap: { label: 'Chunk overlap (chars)',\n help: 'Characters retained from the previous chunk so context survives the boundary.' },\n over_fetch: { label: 'Over-fetch multiplier',\n help: 'Internal topK × overFetch candidates fetched so JS-side metadata filtering still has rows.' },\n enforce_rls: { label: 'Enforce RLS on search',\n help: 'Re-check every hit against the caller\\'s record-level permissions. ⚠ Disabling skips the platform\\'s unique safeguard.' },\n },\n actions: {\n test: { label: 'Test connection' },\n },\n },\n },\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { TranslationData } from '@objectstack/spec/system';\n\n/**\n * 简体中文 (zh-CN) — built-in settings manifest translations.\n */\nexport const zhCN: TranslationData = {\n settingsCommon: {\n sourceLabels: {\n env: '环境变量',\n global: '全局',\n tenant: '租户',\n user: '用户',\n default: '默认',\n },\n },\n settings: {\n mail: {\n title: '邮件投递',\n description: 'SMTP 与事务性邮件服务商配置。',\n groups: {\n provider: { title: '服务商', description: '选择此工作区如何发送邮件。' },\n smtp: { title: 'SMTP' },\n api_key: { title: 'API 密钥' },\n from_address: { title: '发件地址' },\n },\n keys: {\n provider: {\n label: '服务商',\n options: {\n smtp: 'SMTP',\n sendgrid: 'SendGrid',\n ses: 'Amazon SES',\n postmark: 'Postmark',\n },\n },\n smtp_host: { label: '主机', help: '示例:smtp.example.com' },\n smtp_port: { label: '端口' },\n smtp_secure: { label: '启用 TLS' },\n smtp_user: { label: '用户名' },\n smtp_password: { label: '密码' },\n api_key: { label: 'API 密钥' },\n from_email: { label: '发件地址', help: '示例:no-reply@example.com' },\n from_name: { label: '发件人名称' },\n },\n actions: {\n test: { label: '发送测试邮件' },\n },\n },\n\n branding: {\n title: '品牌',\n description: '工作区名称、Logo 与主题色。',\n groups: {\n identity: { title: '身份' },\n appearance: { title: '外观' },\n },\n keys: {\n workspace_name: { label: '工作区名称' },\n support_email: { label: '客服邮箱', help: '示例:support@example.com' },\n theme_mode: {\n label: '默认主题',\n options: { light: '浅色', dark: '深色', system: '跟随系统' },\n },\n accent_color: { label: '主题色' },\n logo_url: { label: 'Logo 链接', help: '示例:https://…/logo.svg' },\n },\n },\n\n company: {\n title: '公司',\n description: '法律实体信息——注册名称、地址、税号及主要联系人。',\n groups: {\n identity: { title: '主体信息' },\n address: { title: '注册地址' },\n contact: { title: '联系方式' },\n },\n keys: {\n legal_name: { label: '法定名称', help: '注册的法定名称(可能与工作区名称不同)。' },\n registration_number: { label: '注册号', help: '公司注册/工商登记号(如 EIN、统一社会信用代码)。' },\n tax_id: { label: '税号 / VAT', help: '发票上显示的税务标识(如 VAT、GST、ABN)。' },\n address_line1: { label: '地址行 1' },\n address_line2: { label: '地址行 2' },\n city: { label: '城市' },\n state: { label: '省/州' },\n postal_code: { label: '邮政编码' },\n country: { label: '国家/地区', help: 'ISO 3166-1 二位代码(如 US、GB、CN)。' },\n phone: { label: '电话', help: '建议 E.164 格式,如 +86 21 5555 0100。' },\n website: { label: '网站', help: '示例:https://example.com' },\n primary_contact_name: { label: '主要联系人' },\n primary_contact_email: { label: '主要联系人邮箱', help: '示例:ops@example.com' },\n },\n },\n\n localization: {\n title: '本地化',\n description: '默认时区、语言、货币及日期/数字格式。',\n groups: {\n region: { title: '区域' },\n formats: { title: '格式' },\n finance: { title: '财务' },\n },\n keys: {\n timezone: { label: '默认时区', help: '用于 today()/daysFromNow、分析日期分桶和 datetime 渲染的 IANA 时区。' },\n locale: { label: '默认语言', help: '用于消息文案和数字/日期格式的 BCP-47 语言。' },\n default_country: { label: '默认国家/地区', help: 'ISO 3166-1 二位代码(如 US、GB、CN)。' },\n date_format: { label: '日期格式' },\n time_format: { label: '时间格式', options: { '24h': '24 小时制(14:30)', '12h': '12 小时制(2:30 PM)' } },\n number_format: { label: '数字格式', help: '用于显示数字的千分位与小数分隔符。' },\n first_day_of_week: { label: '每周起始日', help: '用作周度分析分桶与日历网格的起始基准。', options: { monday: '周一(ISO)', sunday: '周日', saturday: '周六' } },\n currency: { label: '默认货币', help: '当货币字段未指定币种时套用的 ISO 4217 代码。' },\n fiscal_year_start: { label: '财年起始月', help: '财年的起始月份——决定报表中的\"本季度/本财年\"。' },\n },\n },\n\n auth: {\n title: '认证',\n description: '登录、注册以及内置认证功能的控制项。',\n groups: {\n email_password: {\n title: '邮箱与密码',\n description: '控制本地邮箱/密码登录与自助注册。',\n },\n password_policy: {\n title: '密码策略',\n description: '由认证提供商在注册和重置密码时强制的长度限制。',\n },\n sessions: {\n title: '会话',\n description: '登录会话的有效时长。',\n },\n social: {\n title: '社交登录',\n description: '配置内置的 Google 登录提供商。部署环境变量仍优先生效。',\n },\n },\n keys: {\n email_password_enabled: { label: '启用邮箱/密码登录' },\n signup_enabled: { label: '允许自助注册' },\n require_email_verification: { label: '要求邮箱验证' },\n password_min_length: { label: '密码最小长度' },\n password_max_length: { label: '密码最大长度', help: '防止超长密码哈希导致的拒绝服务。' },\n session_expiry_days: { label: '会话有效期(天)', help: '登录后会话在此天数后过期。' },\n session_refresh_days: { label: '刷新阈值(天)', help: '活跃会话在超过此时长后自动续期。' },\n google_enabled: {\n label: '启用 Google 登录',\n help: '需要在 Google Cloud Console 中创建的 Google OAuth 客户端 ID 与密钥。',\n },\n google_client_id: {\n label: 'Google 客户端 ID',\n help: '来自 Google Cloud Console 的 OAuth 客户端 ID。也可在服务器上设置 GOOGLE_CLIENT_ID。',\n },\n google_client_secret: {\n label: 'Google 客户端密钥',\n help: '加密存储。也可在服务器上设置 GOOGLE_CLIENT_SECRET。',\n },\n },\n },\n\n feature_flags: {\n title: '功能开关',\n description: '为当前工作区开启实验性与测试功能。',\n groups: {\n productivity: { title: '生产力' },\n collaboration: { title: '协作' },\n },\n keys: {\n ai_enabled: {\n label: 'AI 助手',\n help: '启用应用内 AI 助手面板。',\n },\n kanban_swimlanes: { label: '看板泳道' },\n realtime_cursors: { label: '实时光标' },\n inline_comments: { label: '行内评论' },\n },\n },\n\n storage: {\n title: '文件存储',\n description:\n '附件、导出文件与用户上传所使用的存储后端。' +\n '⚠ 切换适配器不会迁移已有文件 —— 通过旧适配器上传的文件,在新适配器中将不可访问。',\n groups: {\n adapter: { title: '存储后端', description: '选择上传文件的存放位置。' },\n local: { title: '本地' },\n s3: { title: 'S3' },\n limits: { title: '限制' },\n },\n keys: {\n adapter: {\n label: '适配器',\n options: { local: '本地文件系统', s3: 'S3 / S3 兼容' },\n },\n local_root: { label: '根目录',\n help: '文件存放的文件系统路径。相对路径相对于服务进程的工作目录。' },\n s3_bucket: { label: 'Bucket',\n help: '共享主机 Bucket。各项目的文件通过 projects/<environmentId>/ 前缀进行隔离。' },\n s3_region: { label: '区域', help: '示例:us-east-1' },\n s3_endpoint: { label: 'Endpoint',\n help: 'S3 兼容服务(R2、MinIO、Wasabi)的自定义 Endpoint;AWS S3 请留空。' },\n s3_access_key_id: { label: 'Access Key ID' },\n s3_secret_access_key: { label: 'Secret Access Key' },\n s3_force_path_style: { label: '强制路径风格 URL',\n help: 'MinIO 与大多数 S3 兼容服务请开启;AWS S3 请关闭。' },\n presigned_ttl: { label: '预签名 URL 有效期(秒)' },\n session_ttl: { label: '分片上传会话有效期(秒)',\n help: '分片上传会话保持可续传的时长。' },\n max_upload_mb: { label: '单文件最大上传(MB)' },\n },\n actions: {\n test: { label: '测试连接' },\n },\n },\n\n ai: {\n title: 'AI 与 Embedder',\n description: '平台 AI 与知识库服务使用的 LLM 提供商、模型、凭据与向量化配置。',\n groups: {\n provider: { title: '提供商', description: '选择 LLM 后端。Memory 模式仅原样回显输入,仅用于测试,严禁用于生产。' },\n gateway: { title: 'Vercel AI Gateway', description: '多提供商路由器。模型规格遵循 `provider/model` 格式,例如 `openai/gpt-4o`。' },\n openai: { title: 'OpenAI' },\n anthropic: { title: 'Anthropic' },\n google: { title: 'Google' },\n defaults: { title: '生成默认值', description: '当 Agent 或聊天请求未指定时使用。' },\n observability: { title: '可观测性' },\n embedder: { title: 'Embedder', description: '知识库和 RAG 使用的文本→向量提供商,与上方聊天提供商相互独立。' },\n },\n keys: {\n provider: {\n label: '提供商',\n options: {\n memory: 'Memory(回显 — 仅测试)',\n gateway: 'Vercel AI Gateway',\n openai: 'OpenAI',\n anthropic: 'Anthropic',\n google: 'Google Generative AI',\n },\n },\n gateway_model: { label: 'Gateway 模型', help: '作为 AI_GATEWAY_MODEL 转发。示例:openai/gpt-4o' },\n gateway_api_key: { label: 'Gateway API Key', help: '可选 —— 仅当 Gateway 强制鉴权时需要。' },\n openai_api_key: { label: 'OpenAI API Key', help: '作为 OPENAI_API_KEY 转发,加密存储。' },\n openai_model: { label: '模型', help: '默认模型 ID。Agent 级覆盖优先生效。' },\n openai_base_url: { label: 'Base URL', help: '用于 Azure OpenAI 或自建网关。留空走 api.openai.com。' },\n anthropic_api_key: { label: 'Anthropic API Key', help: '作为 ANTHROPIC_API_KEY 转发,加密存储。' },\n anthropic_model: { label: '模型' },\n google_api_key: { label: 'Google API Key', help: '作为 GOOGLE_GENERATIVE_AI_API_KEY 转发,加密存储。' },\n google_model: { label: '模型' },\n temperature: { label: '温度', help: '0 = 确定性,2 = 高度发散。' },\n max_tokens: { label: '最大输出 tokens', help: '单次响应生成的硬上限。' },\n request_timeout_ms: { label: '请求超时(毫秒)' },\n trace_enabled: { label: '记录 Trace', help: '将 prompt/response 落入 sys_ai_trace,便于调试与回放。' },\n log_prompts: { label: '记录完整 Prompt', help: '在 trace 行中包含完整 prompt 而非仅元数据。⚠ 可能泄露 PII,合规场景请关闭。' },\n embedder_provider: {\n label: '提供商',\n options: {\n none: '禁用(不做向量化)',\n openai: 'OpenAI',\n azure: 'Azure OpenAI',\n dashscope: '阿里通义 DashScope',\n zhipu: '智谱 BigModel',\n siliconflow: '硅基流动 SiliconFlow',\n doubao: '火山引擎 Doubao',\n minimax: 'MiniMax',\n ollama: 'Ollama(本地)',\n custom: '自定义(OpenAI 兼容)',\n },\n },\n embedder_api_key: { label: 'Embedder API Key', help: '作为 Authorization Bearer 发送。Ollama 任意非空值均可。' },\n embedder_model: { label: '模型', help: '示例 — OpenAI: text-embedding-3-small · 阿里通义: text-embedding-v3 · 智谱: embedding-3 · 硅基流动: BAAI/bge-m3 · Ollama: bge-m3' },\n embedder_base_url: { label: 'Base URL', help: '端点根路径(不含 /embeddings)。预设会自动填充,可覆盖为代理或自建网关。' },\n embedder_dimensions: { label: '维度', help: '覆盖输出维度(仅 Matryoshka 模型支持)。留空使用模型默认值。' },\n embedder_batch_size: { label: '批量大小', help: '单次 embed() 调用的 chunk 数。命中速率/大小限制时调小。' },\n },\n actions: {\n test: { label: '测试连接' },\n test_embedder: { label: '测试 Embedder' },\n },\n },\n\n knowledge: {\n title: '知识库',\n description: 'RAG / 知识源使用的向量存储后端。⚠ 切换适配器不会迁移已有索引。',\n groups: {\n adapter: { title: '后端', description: '选择文档分块及其向量的存储位置。' },\n turso: { title: 'Turso / libSQL', description: '支持托管 Turso、本地文件、内存三种模式。' },\n ragflow: { title: 'RAGFlow', description: '外部 RAGFlow 部署。自部署文档见 https://ragflow.io 。' },\n indexing: { title: '索引默认值', description: 'KnowledgeSource.adapterConfig 上的逐源覆盖优先生效。' },\n permissions: { title: '权限' },\n },\n keys: {\n adapter: {\n label: '适配器',\n options: {\n memory: '内存(仅开发/测试)',\n turso: 'Turso / libSQL(云端或本地)',\n ragflow: 'RAGFlow(外部)',\n },\n },\n turso_url: { label: '连接 URL', help: '示例:libsql://your-tenant.turso.io · file:./.objectstack/knowledge.db · :memory:' },\n turso_auth_token: { label: 'Auth Token', help: '仅托管 Turso URL 需要。' },\n ragflow_base_url: { label: 'Base URL', help: '示例:http://localhost:9380' },\n ragflow_api_key: { label: 'API Key' },\n ragflow_default_dataset: { label: '默认 Dataset ID', help: 'KnowledgeSource 未指定时使用。' },\n chunk_target: { label: '目标 chunk 大小(字符)', help: '在按 token 切分之前的软上限。' },\n chunk_overlap: { label: 'Chunk 重叠(字符)', help: '保留上一个 chunk 末尾的字符,以保证跨界上下文。' },\n over_fetch: { label: '过取倍数', help: '内部按 topK × overFetch 拉取候选,以便 JS 端元数据过滤仍有行可返回。' },\n enforce_rls: { label: '搜索时强制 RLS', help: '对每条命中通过 IDataEngine 再次校验调用方的行级权限。⚠ 关闭将跳过平台对向量存储数据外泄的独有防护。' },\n },\n actions: {\n test: { label: '测试连接' },\n },\n },\n },\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { TranslationData } from '@objectstack/spec/system';\n\n/**\n * 日本語 (ja-JP) — built-in settings manifest translations.\n */\nexport const jaJP: TranslationData = {\n settingsCommon: {\n sourceLabels: {\n env: '環境変数',\n global: 'グローバル',\n tenant: 'テナント',\n user: 'ユーザー',\n default: 'デフォルト',\n },\n },\n settings: {\n mail: {\n title: 'メール配信',\n description: 'SMTP およびトランザクションメールプロバイダー設定。',\n groups: {\n provider: { title: 'プロバイダー', description: 'このワークスペースの送信方法を選択します。' },\n smtp: { title: 'SMTP' },\n api_key: { title: 'API キー' },\n from_address: { title: '差出人アドレス' },\n },\n keys: {\n provider: {\n label: 'プロバイダー',\n options: {\n smtp: 'SMTP',\n sendgrid: 'SendGrid',\n ses: 'Amazon SES',\n postmark: 'Postmark',\n },\n },\n smtp_host: { label: 'ホスト', help: '例: smtp.example.com' },\n smtp_port: { label: 'ポート' },\n smtp_secure: { label: 'TLS を使用' },\n smtp_user: { label: 'ユーザー名' },\n smtp_password: { label: 'パスワード' },\n api_key: { label: 'API キー' },\n from_email: { label: '差出人アドレス', help: '例: no-reply@example.com' },\n from_name: { label: '差出人名' },\n },\n actions: {\n test: { label: 'テストメール送信' },\n },\n },\n\n branding: {\n title: 'ブランディング',\n description: 'ワークスペース名・ロゴ・アクセントカラー。',\n groups: {\n identity: { title: 'アイデンティティ' },\n appearance: { title: '外観' },\n },\n keys: {\n workspace_name: { label: 'ワークスペース名' },\n support_email: { label: 'サポートメール', help: '例: support@example.com' },\n theme_mode: {\n label: 'デフォルトテーマ',\n options: { light: 'ライト', dark: 'ダーク', system: 'システムに従う' },\n },\n accent_color: { label: 'アクセントカラー' },\n logo_url: { label: 'ロゴ URL', help: '例: https://…/logo.svg' },\n },\n },\n\n auth: {\n title: '認証',\n description: 'サインイン、登録、組み込み認証機能の制御。',\n groups: {\n email_password: {\n title: 'メールとパスワード',\n description: 'ローカルのメール/パスワードサインインとセルフサービス登録を制御します。',\n },\n social: {\n title: 'ソーシャルサインイン',\n description:\n '組み込みの Google サインインプロバイダーを設定します。デプロイの環境変数が優先されます。',\n },\n },\n keys: {\n email_password_enabled: { label: 'メール/パスワードログインを有効化' },\n signup_enabled: { label: 'セルフサービス登録を許可' },\n require_email_verification: { label: 'メール確認を必須にする' },\n google_enabled: {\n label: 'Google ログインを有効化',\n help: 'Google Cloud Console の Google OAuth クライアント ID とシークレットが必要です。',\n },\n google_client_id: {\n label: 'Google クライアント ID',\n help: 'Google Cloud Console の OAuth クライアント ID。サーバー側で GOOGLE_CLIENT_ID を設定することもできます。',\n },\n google_client_secret: {\n label: 'Google クライアントシークレット',\n help: '保存時に暗号化されます。サーバー側で GOOGLE_CLIENT_SECRET を設定することもできます。',\n },\n },\n },\n\n feature_flags: {\n title: '機能フラグ',\n description: 'このワークスペースで実験的・ベータ機能を切替えます。',\n groups: {\n productivity: { title: '生産性' },\n collaboration: { title: 'コラボレーション' },\n },\n keys: {\n ai_enabled: {\n label: 'AI アシスタント',\n help: 'アプリ内 AI アシスタントパネルを有効化します。',\n },\n kanban_swimlanes: { label: 'カンバンのスイムレーン' },\n realtime_cursors: { label: 'リアルタイムカーソル' },\n inline_comments: { label: 'インラインコメント' },\n },\n },\n\n storage: {\n title: 'ファイルストレージ',\n description:\n '添付ファイル・エクスポート・ユーザーアップロードに使用するバックエンド。' +\n '⚠ アダプターを切替えても既存ファイルは移行されません。以前のアダプターでアップロードされたファイルは新しいアダプターからアクセスできなくなります。',\n groups: {\n adapter: { title: 'バックエンド', description: 'アップロードファイルの保存先を選択します。' },\n local: { title: 'ローカル' },\n s3: { title: 'S3' },\n limits: { title: '制限' },\n },\n keys: {\n adapter: {\n label: 'アダプター',\n options: { local: 'ローカルファイルシステム', s3: 'S3 / S3 互換' },\n },\n local_root: { label: 'ルートディレクトリ',\n help: 'ファイルを保存するファイルシステムパス。相対パスはサーバーの CWD から解決されます。' },\n s3_bucket: { label: 'バケット',\n help: '共有ホストバケット。プロジェクト毎のファイルは projects/<environmentId>/ プレフィックスで分離されます。' },\n s3_region: { label: 'リージョン', help: '例: us-east-1' },\n s3_endpoint: { label: 'エンドポイント',\n help: 'S3 互換プロバイダ (R2, MinIO, Wasabi) のカスタムエンドポイント。AWS S3 の場合は空欄。' },\n s3_access_key_id: { label: 'アクセスキー ID' },\n s3_secret_access_key: { label: 'シークレットアクセスキー' },\n s3_force_path_style: { label: 'パススタイル URL を強制',\n help: 'MinIO や多くの S3 互換プロバイダで有効化。AWS S3 では無効化。' },\n presigned_ttl: { label: '署名付き URL の有効期間 (秒)' },\n session_ttl: { label: 'アップロードセッション TTL (秒)',\n help: 'チャンクアップロードの再開可能期間。' },\n max_upload_mb: { label: '最大アップロードサイズ (MB)' },\n },\n actions: {\n test: { label: '接続テスト' },\n },\n },\n\n ai: {\n title: 'AI と Embedder',\n description:\n 'プラットフォームの AI およびナレッジサービスが使用する LLM プロバイダー、モデル、認証情報、Embedder 設定。',\n groups: {\n provider: { title: 'プロバイダー',\n description: 'LLM バックエンドを選択します。Memory モードは入力をそのまま返します。テスト用であり、本番では使用しないでください。' },\n gateway: { title: 'Vercel AI Gateway',\n description: 'マルチプロバイダールーター。モデル指定は `provider/model` 形式に従います(例: `openai/gpt-4o`)。' },\n openai: { title: 'OpenAI' },\n anthropic: { title: 'Anthropic' },\n google: { title: 'Google' },\n defaults: { title: '生成のデフォルト値',\n description: 'エージェントまたはチャットリクエストが独自の値を指定しない場合に適用されます。' },\n observability: { title: '可観測性' },\n embedder: { title: 'Embedder',\n description:\n 'ナレッジソースと RAG が使用するテキスト → ベクトルプロバイダー。' +\n '上記のチャットプロバイダーとは独立しています。' },\n },\n keys: {\n provider: {\n label: 'プロバイダー',\n options: {\n memory: 'Memory(エコー — テスト専用)',\n gateway: 'Vercel AI Gateway',\n openai: 'OpenAI',\n anthropic: 'Anthropic',\n google: 'Google Generative AI',\n },\n },\n gateway_model: { label: 'Gateway モデル',\n help: 'AI_GATEWAY_MODEL として転送されます。例: openai/gpt-4o' },\n gateway_api_key: { label: 'Gateway API キー',\n help: '任意 — Gateway が認証を要求する場合のみ必要です。' },\n openai_api_key: { label: 'OpenAI API キー',\n help: 'OPENAI_API_KEY として転送されます。保存時に暗号化されます。' },\n openai_model: { label: 'モデル',\n help: 'デフォルトのモデル ID。エージェント単位の上書きが優先されます。' },\n openai_base_url: { label: 'Base URL',\n help: 'Azure OpenAI や自己ホスト型ゲートウェイ用の上書き。api.openai.com の場合は空欄にします。' },\n anthropic_api_key: { label: 'Anthropic API キー',\n help: 'ANTHROPIC_API_KEY として転送されます。保存時に暗号化されます。' },\n anthropic_model: { label: 'モデル' },\n google_api_key: { label: 'Google API キー',\n help: 'GOOGLE_GENERATIVE_AI_API_KEY として転送されます。保存時に暗号化されます。' },\n google_model: { label: 'モデル' },\n temperature: { label: 'Temperature',\n help: '0 = 決定的、2 = 非常に創造的。' },\n max_tokens: { label: '最大出力トークン数',\n help: 'レスポンスごとに生成されるトークンの上限。' },\n request_timeout_ms: { label: 'リクエストタイムアウト (ms)' },\n trace_enabled: { label: 'トレースを記録',\n help: 'デバッグと再生のため prompt/response トレースを sys_ai_trace に保存します。' },\n log_prompts: { label: '完全なプロンプトを記録',\n help: 'メタデータだけでなくレンダリングされたプロンプトをトレース行に含めます。⚠ PII が漏えいする可能性があります。規制環境では無効にしてください。' },\n embedder_provider: {\n label: 'プロバイダー',\n options: {\n none: '無効(埋め込みなし)',\n openai: 'OpenAI',\n azure: 'Azure OpenAI',\n dashscope: '阿里通义 DashScope',\n zhipu: '智谱 BigModel',\n siliconflow: '硅基流动 SiliconFlow',\n doubao: '火山引擎 Doubao',\n minimax: 'MiniMax',\n ollama: 'Ollama(ローカル)',\n custom: 'カスタム(OpenAI 互換)',\n },\n },\n embedder_api_key: { label: 'Embedder API キー',\n help: 'Authorization ヘッダーとして送信される Bearer トークン。Ollama では空でない任意の値で動作します。' },\n embedder_model: { label: 'モデル',\n help: '例 — OpenAI: text-embedding-3-small · 阿里通义: text-embedding-v3 · 智谱: embedding-3 · 硅基流动: BAAI/bge-m3 · Ollama: bge-m3' },\n embedder_base_url: { label: 'Base URL',\n help: 'エンドポイントのルート(/embeddings を含まない)。プリセットから自動入力されます。プロキシや自己ホスト型ゲートウェイ用に上書きできます。' },\n embedder_dimensions: { label: '次元数',\n help: '出力次元数を上書きします(Matryoshka モデルのみ)。空欄の場合はモデルのデフォルトを使用します。' },\n embedder_batch_size: { label: 'バッチサイズ',\n help: 'embed() 呼び出しごとのチャンク数。プロバイダーのレート/サイズ制限に達する場合は減らします。' },\n },\n actions: {\n test: { label: '接続テスト' },\n test_embedder: { label: 'Embedder をテスト' },\n },\n },\n\n knowledge: {\n title: 'ナレッジ',\n description:\n 'RAG / ナレッジソース用のベクトルストアバックエンド。' +\n '⚠ アダプターを切替えても既存のインデックスは移行されません。',\n groups: {\n adapter: { title: 'バックエンド',\n description: 'ドキュメントチャンクとそのベクトルの保存先を選択します。' },\n turso: { title: 'Turso / libSQL',\n description: 'マネージド Turso、ローカルファイル、インメモリのいずれでも動作します。' },\n ragflow: { title: 'RAGFlow',\n description: '外部 RAGFlow デプロイ。セルフホストの手順は https://ragflow.io を参照してください。' },\n indexing: { title: 'インデックスのデフォルト値',\n description: 'KnowledgeSource.adapterConfig のソース単位の値が優先されます。' },\n permissions: { title: '権限' },\n },\n keys: {\n adapter: {\n label: 'アダプター',\n options: {\n memory: 'インメモリ(開発/テスト専用)',\n turso: 'Turso / libSQL(クラウドまたはローカル)',\n ragflow: 'RAGFlow(外部)',\n },\n },\n turso_url: { label: '接続 URL',\n help: '例: libsql://your-tenant.turso.io · file:./.objectstack/knowledge.db · :memory:' },\n turso_auth_token: { label: '認証トークン',\n help: 'マネージド Turso URL の場合のみ必要です。' },\n ragflow_base_url: { label: 'Base URL', help: '例: http://localhost:9380' },\n ragflow_api_key: { label: 'API キー' },\n ragflow_default_dataset: { label: 'デフォルトデータセット ID',\n help: 'KnowledgeSource が独自の RAGFlow データセットを指定しない場合に使用されます。' },\n chunk_target: { label: '目標チャンクサイズ(文字数)',\n help: 'トークン単位の分割が行われる前のチャンクサイズのソフト上限。' },\n chunk_overlap: { label: 'チャンクの重なり(文字数)',\n help: '境界を越えてコンテキストを維持するため、前のチャンクから保持する文字数。' },\n over_fetch: { label: 'オーバーフェッチ倍率',\n help: 'JS 側のメタデータフィルタリングでも行が残るよう、内部で topK × overFetch 件の候補を取得します。' },\n enforce_rls: { label: '検索時に RLS を強制',\n help: '各ヒットを呼び出し元のレコードレベル権限に対して再確認します。⚠ 無効化するとプラットフォーム固有のセーフガードがスキップされます。' },\n },\n actions: {\n test: { label: '接続テスト' },\n },\n },\n },\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { TranslationData } from '@objectstack/spec/system';\n\n/**\n * Español (es-ES) — built-in settings manifest translations.\n */\nexport const esES: TranslationData = {\n settingsCommon: {\n sourceLabels: {\n env: 'Entorno',\n global: 'Global',\n tenant: 'Inquilino',\n user: 'Usuario',\n default: 'Predeterminado',\n },\n },\n settings: {\n mail: {\n title: 'Envío de correo',\n description: 'Configuración de SMTP y del proveedor de correo transaccional.',\n groups: {\n provider: { title: 'Proveedor', description: 'Elige cómo envía correo saliente este espacio de trabajo.' },\n smtp: { title: 'SMTP' },\n api_key: { title: 'Clave de API' },\n from_address: { title: 'Dirección de remitente' },\n },\n keys: {\n provider: {\n label: 'Proveedor',\n options: {\n smtp: 'SMTP',\n sendgrid: 'SendGrid',\n ses: 'Amazon SES',\n postmark: 'Postmark',\n },\n },\n smtp_host: { label: 'Host', help: 'Ejemplo: smtp.example.com' },\n smtp_port: { label: 'Puerto' },\n smtp_secure: { label: 'Usar TLS' },\n smtp_user: { label: 'Usuario' },\n smtp_password: { label: 'Contraseña' },\n api_key: { label: 'Clave de API' },\n from_email: { label: 'Correo del remitente', help: 'Ejemplo: no-reply@example.com' },\n from_name: { label: 'Nombre del remitente' },\n },\n actions: {\n test: { label: 'Enviar correo de prueba' },\n },\n },\n\n branding: {\n title: 'Marca',\n description: 'Nombre del espacio de trabajo, logotipo y color de acento.',\n groups: {\n identity: { title: 'Identidad' },\n appearance: { title: 'Apariencia' },\n },\n keys: {\n workspace_name: { label: 'Nombre del espacio de trabajo' },\n support_email: { label: 'Correo de soporte', help: 'Ejemplo: support@example.com' },\n theme_mode: {\n label: 'Tema predeterminado',\n options: { light: 'Claro', dark: 'Oscuro', system: 'Según el sistema' },\n },\n accent_color: { label: 'Color de acento' },\n logo_url: { label: 'URL del logotipo', help: 'Ejemplo: https://…/logo.svg' },\n },\n },\n\n auth: {\n title: 'Autenticación',\n description: 'Inicio de sesión, registro y controles de las funciones de autenticación integradas.',\n groups: {\n email_password: {\n title: 'Correo y contraseña',\n description: 'Controla el inicio de sesión local con correo/contraseña y el registro de autoservicio.',\n },\n social: {\n title: 'Inicio de sesión social',\n description:\n 'Configura el proveedor de inicio de sesión de Google integrado. Las variables de entorno del despliegue siguen teniendo prioridad.',\n },\n },\n keys: {\n email_password_enabled: { label: 'Habilitar inicio de sesión con correo/contraseña' },\n signup_enabled: { label: 'Permitir registro de autoservicio' },\n require_email_verification: { label: 'Requerir verificación de correo' },\n google_enabled: {\n label: 'Habilitar inicio de sesión con Google',\n help: 'Requiere un ID de cliente y un secreto de OAuth de Google desde Google Cloud Console.',\n },\n google_client_id: {\n label: 'ID de cliente de Google',\n help: 'ID de cliente de OAuth desde Google Cloud Console. También se puede definir GOOGLE_CLIENT_ID en el servidor.',\n },\n google_client_secret: {\n label: 'Secreto de cliente de Google',\n help: 'Se almacena cifrado en reposo. También se puede definir GOOGLE_CLIENT_SECRET en el servidor.',\n },\n },\n },\n\n feature_flags: {\n title: 'Indicadores de función',\n description: 'Activa funciones experimentales y en beta para este espacio de trabajo.',\n groups: {\n productivity: { title: 'Productividad' },\n collaboration: { title: 'Colaboración' },\n },\n keys: {\n ai_enabled: {\n label: 'Asistente de IA',\n help: 'Habilita el panel del asistente de IA dentro de la aplicación.',\n },\n kanban_swimlanes: { label: 'Carriles de Kanban' },\n realtime_cursors: { label: 'Cursores en tiempo real' },\n inline_comments: { label: 'Comentarios en línea' },\n },\n },\n\n storage: {\n title: 'Almacenamiento de archivos',\n description:\n 'Backend usado para adjuntos, exportaciones y subidas de usuarios. ' +\n '⚠ Cambiar de adaptador no migra los archivos existentes: los archivos ' +\n 'subidos con el adaptador anterior dejan de ser accesibles a través ' +\n 'del nuevo.',\n groups: {\n adapter: { title: 'Backend', description: 'Elige dónde se almacenan los archivos subidos.' },\n local: { title: 'Local' },\n s3: { title: 'S3' },\n limits: { title: 'Límites' },\n },\n keys: {\n adapter: {\n label: 'Adaptador',\n options: { local: 'Sistema de archivos local', s3: 'S3 / compatible con S3' },\n },\n local_root: { label: 'Directorio raíz',\n help: 'Ruta del sistema de archivos donde se almacenan los archivos. Las rutas relativas se resuelven desde el directorio de trabajo del servidor.' },\n s3_bucket: { label: 'Bucket',\n help: 'Bucket compartido del host. Los archivos de cada entorno se aíslan mediante el prefijo projects/<environmentId>/.' },\n s3_region: { label: 'Región', help: 'Ejemplo: us-east-1' },\n s3_endpoint: { label: 'Endpoint',\n help: 'Endpoint personalizado para proveedores compatibles con S3 (R2, MinIO, Wasabi). Déjalo en blanco para AWS S3.' },\n s3_access_key_id: { label: 'Access Key ID' },\n s3_secret_access_key: { label: 'Secret Access Key' },\n s3_force_path_style: { label: 'Forzar URLs de tipo path',\n help: 'Actívalo para MinIO y la mayoría de proveedores compatibles con S3; desactívalo para AWS S3.' },\n presigned_ttl: { label: 'TTL de URL prefirmada (segundos)' },\n session_ttl: { label: 'TTL de sesión de subida (segundos)',\n help: 'Tiempo durante el cual una sesión de subida por fragmentos sigue siendo reanudable.' },\n max_upload_mb: { label: 'Tamaño máximo de subida (MB)' },\n },\n actions: {\n test: { label: 'Probar conexión' },\n },\n },\n\n ai: {\n title: 'IA y Embedder',\n description:\n 'Proveedor de LLM, modelo, credenciales y configuración del embedder usados por ' +\n 'los servicios de IA y de conocimiento de la plataforma.',\n groups: {\n provider: { title: 'Proveedor',\n description: 'Elige el backend de LLM. El modo Memory repite la entrada: útil para pruebas, nunca para producción.' },\n gateway: { title: 'Vercel AI Gateway',\n description: 'Enrutador multiproveedor. La especificación del modelo sigue `provider/model`, p. ej. `openai/gpt-4o`.' },\n openai: { title: 'OpenAI' },\n anthropic: { title: 'Anthropic' },\n google: { title: 'Google' },\n defaults: { title: 'Valores predeterminados de generación',\n description: 'Se aplican cuando un agente o una solicitud de chat no especifica su propio valor.' },\n observability: { title: 'Observabilidad' },\n embedder: { title: 'Embedder',\n description:\n 'Proveedor de texto → vector usado por las fuentes de conocimiento y RAG. ' +\n 'Independiente del proveedor de chat anterior.' },\n },\n keys: {\n provider: {\n label: 'Proveedor',\n options: {\n memory: 'Memory (eco — solo pruebas)',\n gateway: 'Vercel AI Gateway',\n openai: 'OpenAI',\n anthropic: 'Anthropic',\n google: 'Google Generative AI',\n },\n },\n gateway_model: { label: 'Modelo de Gateway',\n help: 'Se reenvía como AI_GATEWAY_MODEL. Ejemplo: openai/gpt-4o' },\n gateway_api_key: { label: 'Clave de API de Gateway',\n help: 'Opcional: solo se requiere si el gateway exige autenticación.' },\n openai_api_key: { label: 'Clave de API de OpenAI',\n help: 'Se reenvía como OPENAI_API_KEY. Se almacena cifrada en reposo.' },\n openai_model: { label: 'Modelo',\n help: 'ID de modelo predeterminado. Las anulaciones por agente tienen prioridad.' },\n openai_base_url: { label: 'Base URL',\n help: 'Anulación para Azure OpenAI o gateways autoalojados. Déjalo en blanco para api.openai.com.' },\n anthropic_api_key: { label: 'Clave de API de Anthropic',\n help: 'Se reenvía como ANTHROPIC_API_KEY. Se almacena cifrada en reposo.' },\n anthropic_model: { label: 'Modelo' },\n google_api_key: { label: 'Clave de API de Google',\n help: 'Se reenvía como GOOGLE_GENERATIVE_AI_API_KEY. Se almacena cifrada en reposo.' },\n google_model: { label: 'Modelo' },\n temperature: { label: 'Temperatura',\n help: '0 = determinista, 2 = muy creativo.' },\n max_tokens: { label: 'Máximo de tokens de salida',\n help: 'Límite estricto de tokens generados por respuesta.' },\n request_timeout_ms: { label: 'Tiempo de espera de la solicitud (ms)' },\n trace_enabled: { label: 'Registrar trazas',\n help: 'Persiste las trazas de prompt/respuesta en sys_ai_trace para depuración y reproducción.' },\n log_prompts: { label: 'Registrar prompts completos',\n help: 'Incluye los prompts renderizados (no solo metadatos) en las filas de traza. ⚠ Puede filtrar PII: desactívalo en entornos regulados.' },\n embedder_provider: {\n label: 'Proveedor',\n options: {\n none: 'Deshabilitado (sin embeddings)',\n openai: 'OpenAI',\n azure: 'Azure OpenAI',\n dashscope: '阿里通义 DashScope',\n zhipu: '智谱 BigModel',\n siliconflow: '硅基流动 SiliconFlow',\n doubao: '火山引擎 Doubao',\n minimax: 'MiniMax',\n ollama: 'Ollama (local)',\n custom: 'Personalizado (compatible con OpenAI)',\n },\n },\n embedder_api_key: { label: 'Clave de API del embedder',\n help: 'Token bearer enviado en la cabecera Authorization. Para Ollama sirve cualquier valor no vacío.' },\n embedder_model: { label: 'Modelo',\n help: 'Ejemplos — OpenAI: text-embedding-3-small · 阿里通义: text-embedding-v3 · 智谱: embedding-3 · 硅基流动: BAAI/bge-m3 · Ollama: bge-m3' },\n embedder_base_url: { label: 'Base URL',\n help: 'Raíz del endpoint (sin /embeddings). Se autocompleta desde el preset; anúlalo para proxys o gateways autoalojados.' },\n embedder_dimensions: { label: 'Dimensiones',\n help: 'Anula la dimensionalidad de salida (solo modelos Matryoshka). Déjalo en blanco para usar el valor predeterminado del modelo.' },\n embedder_batch_size: { label: 'Tamaño de lote',\n help: 'Fragmentos por llamada a embed(). Redúcelo si alcanzas los límites de tasa o tamaño del proveedor.' },\n },\n actions: {\n test: { label: 'Probar conexión' },\n test_embedder: { label: 'Probar embedder' },\n },\n },\n\n knowledge: {\n title: 'Conocimiento',\n description:\n 'Backend de almacén de vectores para RAG / fuentes de conocimiento. ' +\n '⚠ Cambiar de adaptador NO migra los índices existentes.',\n groups: {\n adapter: { title: 'Backend',\n description: 'Elige dónde se almacenan los fragmentos de documento y sus vectores.' },\n turso: { title: 'Turso / libSQL',\n description: 'Funciona con Turso gestionado, archivo local o en memoria.' },\n ragflow: { title: 'RAGFlow',\n description: 'Despliegue externo de RAGFlow. Consulta https://ragflow.io para instrucciones de autoalojamiento.' },\n indexing: { title: 'Valores predeterminados de indexación',\n description: 'Los valores por fuente en KnowledgeSource.adapterConfig tienen prioridad.' },\n permissions: { title: 'Permisos' },\n },\n keys: {\n adapter: {\n label: 'Adaptador',\n options: {\n memory: 'En memoria (solo desarrollo / pruebas)',\n turso: 'Turso / libSQL (nube o local)',\n ragflow: 'RAGFlow (externo)',\n },\n },\n turso_url: { label: 'URL de conexión',\n help: 'Ejemplos: libsql://your-tenant.turso.io · file:./.objectstack/knowledge.db · :memory:' },\n turso_auth_token: { label: 'Token de autenticación',\n help: 'Solo se requiere para URLs de Turso gestionado.' },\n ragflow_base_url: { label: 'Base URL', help: 'Ejemplo: http://localhost:9380' },\n ragflow_api_key: { label: 'Clave de API' },\n ragflow_default_dataset: { label: 'ID de dataset predeterminado',\n help: 'Se usa cuando una KnowledgeSource no especifica su propio dataset de RAGFlow.' },\n chunk_target: { label: 'Tamaño objetivo de fragmento (caracteres)',\n help: 'Límite flexible del tamaño de fragmento antes de que actúe la división consciente de tokens.' },\n chunk_overlap: { label: 'Solapamiento de fragmentos (caracteres)',\n help: 'Caracteres conservados del fragmento anterior para que el contexto sobreviva al límite.' },\n over_fetch: { label: 'Multiplicador de sobre-obtención',\n help: 'Se obtienen topK × overFetch candidatos internos para que el filtrado de metadatos en JS siga teniendo filas.' },\n enforce_rls: { label: 'Aplicar RLS en la búsqueda',\n help: 'Vuelve a comprobar cada resultado contra los permisos a nivel de registro del solicitante. ⚠ Desactivarlo omite la salvaguarda exclusiva de la plataforma.' },\n },\n actions: {\n test: { label: 'Probar conexión' },\n },\n },\n },\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Built-in Settings translations.\n *\n * Mirrors the CRM example's `src/translations/{en,zh-CN,ja-JP}.ts` convention —\n * one file per locale, aggregated into a `TranslationBundle` here.\n *\n * Hosts merge `settingsBuiltinTranslations` into the i18next resource tree\n * under whatever namespace makes sense (the console wires it as `system`),\n * making keys resolvable as `<ns>.settings.<namespace>.{title,description,...}`.\n */\n\nimport type { TranslationBundle } from '@objectstack/spec/system';\nimport { en } from './en.js';\nimport { zhCN } from './zh-CN.js';\nimport { jaJP } from './ja-JP.js';\nimport { esES } from './es-ES.js';\n\nexport { en, zhCN, jaJP, esES };\n\nexport const settingsBuiltinTranslations: TranslationBundle = {\n en,\n 'zh-CN': zhCN,\n 'ja-JP': jaJP,\n 'es-ES': esES,\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Plugin, PluginContext } from '@objectstack/core';\nimport type { IHttpServer, IDataEngine } from '@objectstack/spec/contracts';\nimport type { SettingsManifest } from '@objectstack/spec/system';\nimport { SettingsService } from './settings-service.js';\nimport type { ICryptoProvider } from '@objectstack/spec/contracts';\nimport type { SettingsAuditWriter, SettingsEngine, SettingsSecretStore } from './settings-service.types.js';\nimport type { CryptoAdapter } from './crypto-adapter.js';\nimport { LocalCryptoProvider } from './local-crypto-provider.js';\nimport { registerSettingsRoutes } from './settings-routes.js';\nimport {\n settingsObjects,\n settingsPluginManifestHeader,\n SETTINGS_PLUGIN_ID,\n SETTINGS_PLUGIN_VERSION,\n} from './manifest.js';\nimport {\n builtinSettingsManifests,\n mailTestActionHandler,\n storageTestActionHandler,\n aiTestActionHandler,\n} from './manifests/index.js';\nimport { settingsBuiltinTranslations } from './translations/index.js';\n\n/** Configuration options for the SettingsServicePlugin. */\nexport interface SettingsServicePluginOptions {\n /**\n * Pre-register these manifests at boot. When omitted, the bundled\n * builtin manifests (mail / branding / feature_flags) are loaded so\n * a host gets a working Settings hub out of the box. Pass an empty\n * array to opt out entirely.\n */\n manifests?: SettingsManifest[];\n /** Override the default crypto adapter. */\n crypto?: CryptoAdapter;\n\n /**\n * Phase 3 KMS hook. When provided, encrypted specifier values are\n * routed through this provider into `sys_secret`; `sys_setting.value_enc`\n * holds the handle id only. Defaults to `LocalCryptoProvider`, an\n * AES-256-GCM provider keyed off `OS_SECRET_KEY` (or a persisted dev key).\n * In production it refuses to boot without a stable key rather than\n * silently minting an ephemeral one. Swap in an AWS / GCP / Vault\n * KMS-backed implementation for managed custody and per-tenant keys.\n */\n cryptoProvider?: ICryptoProvider;\n /** Override the default base path (`/api/settings`). */\n basePath?: string;\n /** Disable REST route registration. */\n registerRoutes?: boolean;\n /** Override the env source. Defaults to `process.env`. */\n env?: Record<string, string | undefined>;\n /**\n * Action handlers to register at boot, keyed by namespace and action\n * id. The bundled `mail.test` handler is registered automatically\n * unless this object is provided.\n */\n actionHandlers?: Record<string, Record<string, import('./settings-service.types.js').SettingsActionHandler>>;\n}\n\n/**\n * SettingsServicePlugin — wires the SettingsService into the kernel.\n *\n * 1. `init`: instantiate the service, register it under `'settings'`,\n * and ship `sys_setting` to the manifest service so the engine\n * auto-provisions the table.\n * 2. `start` → `kernel:ready`: bind the data engine (when present),\n * wire the audit sink (when present), mount REST routes.\n */\nexport class SettingsServicePlugin implements Plugin {\n name = SETTINGS_PLUGIN_ID;\n version = SETTINGS_PLUGIN_VERSION;\n type = 'standard' as const;\n\n private readonly opts: SettingsServicePluginOptions;\n private service: SettingsService | null = null;\n\n constructor(opts: SettingsServicePluginOptions = {}) {\n this.opts = {\n ...opts,\n manifests: opts.manifests ?? builtinSettingsManifests,\n actionHandlers: opts.actionHandlers ?? {\n mail: { test: mailTestActionHandler },\n storage: { test: storageTestActionHandler },\n ai: { test: aiTestActionHandler },\n },\n };\n }\n\n async init(ctx: PluginContext): Promise<void> {\n this.service = new SettingsService({\n crypto: this.opts.crypto,\n env: this.opts.env,\n });\n for (const m of this.opts.manifests ?? []) this.service.registerManifest(m);\n for (const [ns, handlers] of Object.entries(this.opts.actionHandlers ?? {})) {\n for (const [id, fn] of Object.entries(handlers)) {\n this.service.registerAction(ns, id, fn);\n }\n }\n\n ctx.registerService('settings', this.service);\n ctx.logger?.info?.(\n `SettingsServicePlugin: registered (manifests=${this.opts.manifests?.length ?? 0})`,\n );\n\n // Register the K/V object so the engine creates the table.\n try {\n ctx.getService<{ register(m: any): void }>('manifest').register({\n ...settingsPluginManifestHeader,\n objects: settingsObjects,\n });\n } catch {\n // manifest service is optional — skip in lean test kernels.\n }\n }\n\n async start(ctx: PluginContext): Promise<void> {\n if (!this.service) return;\n\n ctx.hook('kernel:ready', async () => {\n // Contribute built-in settings translations into the i18n service.\n // Done in `kernel:ready` (not `init`) because the i18n service plugin\n // is typically registered AFTER capability-loaded service plugins.\n try {\n const i18n = ctx.getService<{\n loadTranslations: (locale: string, data: Record<string, unknown>) => void;\n }>('i18n');\n let loaded = 0;\n for (const [locale, data] of Object.entries(settingsBuiltinTranslations)) {\n if (data && typeof data === 'object') {\n try {\n i18n.loadTranslations(locale, data as Record<string, unknown>);\n loaded++;\n } catch (err: any) {\n ctx.logger?.warn?.(\n `SettingsServicePlugin: failed to load translations for '${locale}': ${err?.message ?? err}`,\n );\n }\n }\n }\n if (loaded > 0) {\n ctx.logger?.info?.(\n `SettingsServicePlugin: contributed built-in translations (${loaded} locale${loaded > 1 ? 's' : ''})`,\n );\n }\n } catch {\n // i18n service not registered — manifest literals remain authoritative.\n }\n\n // Late-bind the data engine.\n let engine: IDataEngine | null = null;\n try {\n engine = ctx.getService<IDataEngine>('objectql');\n } catch {\n // ok — fall back to in-memory.\n }\n if (engine) {\n // Late-bind the engine + audit sink on the existing service\n // instance. We avoid re-registering the service because the\n // kernel disallows `registerService` for an already-registered\n // name.\n //\n // SettingsEngine and IDataEngine have *different* update\n // signatures — SettingsEngine bundles `{ where, data }` into a\n // single opts object, while IDataEngine takes\n // `(object, data, options?)` and extracts the row id from\n // `data.id` or `options.where.id`. A force-cast leaves runtime\n // calls to `update(object, { where, data })` reaching the real\n // engine as a malformed payload with no id, which then throws\n // \"Update requires an ID or options.multi=true\". The adapter\n // below performs the translation so SettingsService can keep\n // its narrow, bundled signature.\n this.service!.bindEngine(\n wrapEngineAsSettingsEngine(engine),\n undefined,\n {\n secretStore: this.buildSecretStore(engine),\n auditWriter: this.buildAuditWriter(ctx, engine),\n cryptoProvider: this.opts.cryptoProvider ?? new LocalCryptoProvider(),\n },\n );\n }\n\n if (this.opts.registerRoutes === false) return;\n\n let http: IHttpServer | null = null;\n try {\n http = ctx.getService<IHttpServer>('http-server');\n } catch {\n // ok — no HTTP server in this deployment.\n }\n if (!http) {\n ctx.logger?.warn?.(\n 'SettingsServicePlugin: no HTTP server available — REST routes not registered. ' +\n 'SettingsService is still reachable via kernel.getService(\"settings\").',\n );\n return;\n }\n registerSettingsRoutes(http, this.service!, { basePath: this.opts.basePath });\n ctx.logger?.info?.(\n 'SettingsServicePlugin: REST routes registered at ' + (this.opts.basePath ?? '/api/settings'),\n );\n });\n }\n\n /**\n * Phase 3: build a `sys_secret`-backed implementation of\n * `SettingsSecretStore`. The store bypasses the tenant audit\n * warning because secrets are scoped through their owning\n * `sys_setting` row (which already carries the tenant context).\n */\n private buildSecretStore(engine: IDataEngine): SettingsSecretStore {\n const eng: any = engine;\n return {\n async insert(row) {\n await eng.insert('sys_secret', row, { bypassTenantAudit: true });\n return { id: row.id };\n },\n async get(id) {\n const rows = await eng.find('sys_secret', {\n where: { id },\n limit: 1,\n bypassTenantAudit: true,\n });\n const row = Array.isArray(rows) ? rows[0] : rows?.data?.[0];\n return row ?? null;\n },\n async update(id, patch) {\n // IDataEngine.update signature is `(object, data, options?)`\n // and extracts the record id from `data.id` (or\n // `options.where.id`). Passing `{ where, data, ... }` as the\n // data argument left id=undefined and tripped\n // \"Update requires an ID or options.multi=true\".\n await eng.update(\n 'sys_secret',\n { id, ...patch },\n { bypassTenantAudit: true },\n );\n },\n };\n }\n\n /**\n * Phase 3: append-only writer for `sys_setting_audit`. Failures here\n * MUST NOT abort the settings write, so all calls are wrapped in a\n * try/catch and reported through the plugin logger.\n */\n private buildAuditWriter(ctx: PluginContext, engine: IDataEngine): SettingsAuditWriter {\n const eng: any = engine;\n return {\n write: async (entry) => {\n try {\n await eng.insert('sys_setting_audit', {\n namespace: entry.namespace,\n key: entry.key,\n scope: entry.scope,\n action: entry.action,\n source: entry.source ?? 'api',\n actor_id: entry.actorId ?? null,\n old_hash: entry.oldHash ?? null,\n new_hash: entry.newHash ?? null,\n encrypted: !!entry.encrypted,\n request_id: entry.requestId ?? null,\n reason: entry.reason ?? null,\n created_at: new Date().toISOString(),\n }, { bypassTenantAudit: true });\n } catch (err: any) {\n ctx.logger?.warn?.('SettingsServicePlugin: setting-audit write failed: ' + (err?.message ?? err));\n }\n },\n };\n }\n}\n\n/**\n * Translate an `IDataEngine` instance into the narrower `SettingsEngine`\n * surface used inside `SettingsService`. The two interfaces diverge on\n * `update`:\n *\n * - SettingsEngine: `update(object, { where, data, bypassTenantAudit })`\n * - IDataEngine: `update(object, data, options?)` — id comes from\n * `data.id` or `options.where.id`; otherwise the engine throws\n * \"Update requires an ID or options.multi=true\".\n *\n * The adapter resolves the row id from `where.id` when present and\n * forwards everything in IDataEngine's positional form. When the caller\n * supplies a non-id where clause (composite-key tables), we fall back\n * to `multi: true` so the engine routes through `driver.updateMany`\n * instead of throwing.\n */\nfunction wrapEngineAsSettingsEngine(engine: IDataEngine): SettingsEngine {\n const eng: any = engine;\n return {\n async find(objectName, opts) {\n return eng.find(objectName, opts);\n },\n async insert(objectName, data, opts) {\n return eng.insert(objectName, data, opts);\n },\n async update(objectName, opts) {\n const { where, data, bypassTenantAudit } = opts as {\n where: Record<string, unknown>;\n data: Record<string, unknown>;\n bypassTenantAudit?: boolean;\n };\n const driverOpts = bypassTenantAudit ? { bypassTenantAudit: true } : undefined;\n const id = (where as any)?.id;\n if (id !== undefined && id !== null) {\n return eng.update(objectName, { id, ...data }, driverOpts);\n }\n return eng.update(objectName, data, {\n where,\n multi: true,\n ...(driverOpts ?? {}),\n });\n },\n };\n}\n"],"mappings":"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","names":["manifest","def","persisted","manifest","manifest","manifest","model","manifest"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/crypto-adapter.ts","../src/settings-service.types.ts","../src/visibility-eval.ts","../src/settings-service.ts","../src/local-crypto-provider.ts","../src/settings-routes.ts","../src/manifest.ts","../src/manifests/auth.manifest.ts","../src/manifests/mail.manifest.ts","../src/manifests/branding.manifest.ts","../src/manifests/feature-flags.manifest.ts","../src/manifests/storage.manifest.ts","../src/manifests/ai.manifest.ts","../src/manifests/knowledge.manifest.ts","../src/manifests/localization.manifest.ts","../src/manifests/company.manifest.ts","../src/manifests/index.ts","../src/translations/en.ts","../src/translations/zh-CN.ts","../src/translations/ja-JP.ts","../src/translations/es-ES.ts","../src/translations/index.ts","../src/settings-service-plugin.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Public entrypoint for `@objectstack/service-settings`.\n * See ADR-0007 and `README.md`.\n */\n\nexport { SettingsService } from './settings-service.js';\nexport {\n type CryptoAdapter,\n NoopCryptoAdapter,\n} from './crypto-adapter.js';\n// Default, KMS-free ICryptoProvider. AES-256-GCM keyed off `OS_SECRET_KEY`\n// (production) or a persisted dev key; fails loud in production rather than\n// silently minting an ephemeral key. Hosts swap in a KMS/Vault provider for\n// managed custody. Exported so other subsystems (e.g. the runtime-UI\n// datasource secret binder) can reuse the same wrapping. `InMemoryCryptoProvider`\n// remains a deprecated alias for backward compatibility.\nexport {\n LocalCryptoProvider,\n InMemoryCryptoProvider,\n type LocalCryptoProviderOptions,\n type CryptoMode,\n type KeySource,\n} from './local-crypto-provider.js';\nexport {\n type SettingsActionHandler,\n type SettingsAuditSink,\n type SettingsContext,\n type SettingsEngine,\n type SettingsRow,\n type SettingsServiceOptions,\n envKeyOf,\n SettingsLockedError,\n SettingsValidationError,\n UnknownKeyError,\n UnknownNamespaceError,\n} from './settings-service.types.js';\nexport {\n evaluateVisibility,\n referencedKeys,\n VisibilityParseError,\n} from './visibility-eval.js';\nexport {\n SettingsServicePlugin,\n type SettingsServicePluginOptions,\n} from './settings-service-plugin.js';\nexport {\n registerSettingsRoutes,\n type SettingsRoutesOptions,\n} from './settings-routes.js';\nexport {\n settingsObjects,\n settingsPluginManifestHeader,\n SETTINGS_PLUGIN_ID,\n SETTINGS_PLUGIN_VERSION,\n} from './manifest.js';\n\n// Reference manifests (mail / branding / feature flags) and the\n// convenience aggregate. Hosts can pass `builtinSettingsManifests`\n// directly to `new SettingsServicePlugin({ manifests })`.\nexport {\n builtinSettingsManifests,\n brandingSettingsManifest,\n featureFlagsSettingsManifest,\n mailSettingsManifest,\n mailTestActionHandler,\n storageSettingsManifest,\n storageTestActionHandler,\n} from './manifests/index.js';\n\n// Re-export the spec types for convenience so plugin authors only need\n// one import.\nexport type {\n SettingsManifest,\n ResolvedSettingValue,\n SettingsNamespacePayload,\n SettingsActionResult,\n SpecifierScope,\n} from '@objectstack/spec/system';\n\n// Built-in translations (en / zh-CN / ja-JP) for the reference manifests.\n// Hosts merge `settingsBuiltinTranslations` into their i18next resource tree\n// so SettingsView resolves labels via `<ns>.settings.<namespace>.…`.\nexport {\n settingsBuiltinTranslations,\n en as settingsTranslationsEn,\n zhCN as settingsTranslationsZhCN,\n jaJP as settingsTranslationsJaJP,\n} from './translations/index.js';\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Pluggable adapter for at-rest encryption of `Specifier.encrypted: true`\n * values. The default {@link NoopCryptoAdapter} provides a transparent\n * base64 wrapping suitable for development and tests; production\n * deployments MUST inject a real KMS-backed adapter.\n *\n * encrypt/decrypt are async to leave room for KMS round-trips.\n */\nexport interface CryptoAdapter {\n /** Returns the ciphertext blob to store in `sys_setting.value_enc`. */\n encrypt(plaintext: string, ctx: { namespace: string; key: string }): Promise<string>;\n /** Returns the plaintext used by the resolver. */\n decrypt(ciphertext: string, ctx: { namespace: string; key: string }): Promise<string>;\n /**\n * Stable, short, non-reversible digest used for audit-log entries so\n * operators can correlate value changes without leaking secrets.\n */\n digest(plaintext: string): string;\n}\n\n/**\n * Development / test default. Base64-wraps the plaintext so the column\n * isn't a literal mirror but provides no real confidentiality.\n *\n * Operators are expected to override this via\n * `SettingsServicePluginOptions.crypto`.\n */\nexport class NoopCryptoAdapter implements CryptoAdapter {\n async encrypt(plaintext: string): Promise<string> {\n return 'b64:' + Buffer.from(plaintext, 'utf8').toString('base64');\n }\n async decrypt(ciphertext: string): Promise<string> {\n if (!ciphertext.startsWith('b64:')) {\n // Tolerate legacy plaintext rows during the dev rollout.\n return ciphertext;\n }\n return Buffer.from(ciphertext.slice(4), 'base64').toString('utf8');\n }\n digest(plaintext: string): string {\n // FNV-1a 32-bit — short, stable, non-cryptographic. Audit-only.\n let h = 0x811c9dc5;\n for (let i = 0; i < plaintext.length; i++) {\n h ^= plaintext.charCodeAt(i);\n h = (h + ((h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24))) >>> 0;\n }\n return 'fnv32:' + h.toString(16).padStart(8, '0');\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * SettingsService — the runtime implementation of ADR-0007.\n *\n * Responsibilities:\n * - Maintain an in-memory registry of `SettingsManifest` instances.\n * - Read/write values from the shared `sys_setting` K/V table via the\n * `objectql` data engine, with an in-memory fallback so the service\n * is usable before a real persistence layer is wired up (e.g. unit\n * tests, bootstrap, control-plane mock).\n * - Resolve effective values with `OS_* env > Tenant > User > Default`\n * precedence and tag every value with provenance.\n * - Encrypt-at-rest for `encrypted: true` specifiers using a pluggable\n * {@link CryptoAdapter}.\n * - Emit `sys_audit_log` rows for every successful write (encrypted\n * values are masked).\n * - Dispatch `runAction` for `action_button` specifiers — used by\n * \"Test connection\" / \"Send test email\" etc.\n *\n * The service is intentionally framework-agnostic: it doesn't import\n * the HTTP server, the plugin context, or the audit object schema. The\n * plugin wires those pieces up.\n */\n\nimport type { SettingsActionResult, SpecifierScope } from '@objectstack/spec/system';\nimport { type CryptoAdapter } from './crypto-adapter.js';\n\n/** Caller identity used by the resolver and audit log. */\nexport interface SettingsContext {\n /** Calling user id, when known. Required for `scope: 'user'` reads. */\n userId?: string;\n /** Tenant / project id. Reserved for multi-tenant deployments. */\n tenantId?: string;\n /** Permissions held by the caller (used by REST authz). */\n permissions?: string[];\n /** Source IP / request id for audit correlation. */\n requestId?: string;\n}\n\n/** Storage row shape used by both the engine and the in-memory store. */\nexport interface SettingsRow {\n namespace: string;\n key: string;\n scope: SpecifierScope;\n user_id: string | null;\n value: unknown | null;\n value_enc: string | null;\n encrypted: boolean;\n /**\n * When true, lower-scope rows for the same (namespace, key) are\n * read-only — the resolver still returns this row's value and the\n * mutation API throws `SettingsLockedError`. Only meaningful on\n * upper-scope rows (`global`, `tenant`). (Phase 2)\n */\n locked?: boolean;\n /** Human-readable reason the lock was applied (UI tooltip). */\n locked_reason?: string | null;\n updated_at?: string;\n updated_by?: string | null;\n}\n\n/**\n * Minimal data-engine surface used by the SettingsService. Mirrors the\n * methods we actually call so we can stub it cleanly in tests without\n * pulling the whole `IDataEngine`.\n */\nexport interface SettingsEngine {\n find(\n objectName: string,\n opts: { where?: Record<string, unknown>; limit?: number; bypassTenantAudit?: boolean },\n ): Promise<any[]>;\n insert(\n objectName: string,\n data: Record<string, unknown>,\n opts?: { bypassTenantAudit?: boolean },\n ): Promise<any>;\n update(\n objectName: string,\n opts: {\n where: Record<string, unknown>;\n data: Record<string, unknown>;\n bypassTenantAudit?: boolean;\n },\n ): Promise<any>;\n delete?(objectName: string, opts: { where: Record<string, unknown> }): Promise<any>;\n}\n\n/** Optional audit hook — service-settings won't crash if absent. */\nexport interface SettingsAuditSink {\n record(entry: {\n namespace: string;\n key: string;\n scope: SpecifierScope;\n userId?: string;\n actor?: string;\n action: 'set' | 'reset';\n valueDigest: string;\n encrypted: boolean;\n requestId?: string;\n }): Promise<void> | void;\n}\n\n/**\n * Persistence hook for the `sys_secret` object — used by the secret\n * split introduced in Phase 3. When provided, `SettingsService` writes\n * encrypted specifier values via `ICryptoProvider` into `sys_secret`\n * and stores only the handle id in `sys_setting.value_enc`. When\n * absent, the legacy inline `crypto.encrypt → value_enc` path is used.\n */\nexport interface SettingsSecretStore {\n /** Insert a new secret row; returns the row id (handle id). */\n insert(row: {\n id: string;\n namespace: string;\n key: string;\n kms_key_id: string;\n alg: string;\n version: number;\n ciphertext: string;\n }): Promise<{ id: string }>;\n /** Look up the latest ciphertext for a handle id; null when missing. */\n get(id: string): Promise<{\n id: string;\n namespace: string;\n key: string;\n kms_key_id: string;\n alg: string;\n version: number;\n ciphertext: string;\n } | null>;\n /** Replace an existing secret row (used by rotateKey). */\n update(id: string, patch: {\n kms_key_id?: string;\n alg?: string;\n version?: number;\n ciphertext?: string;\n }): Promise<void>;\n}\n\n/**\n * Append-only writer for the `sys_setting_audit` object — Phase 3\n * audit trail. Distinct from `SettingsAuditSink` (which still writes\n * to the generic `sys_audit_log`) so audit consumers can subscribe\n * to settings activity without scanning the firehose.\n */\nexport interface SettingsAuditWriter {\n write(entry: {\n namespace: string;\n key: string;\n scope: SpecifierScope;\n action: 'set' | 'reset' | 'lock' | 'unlock' | 'rotate';\n source?: 'ui' | 'api' | 'migration' | 'import' | 'system';\n actorId?: string;\n oldHash?: string | null;\n newHash?: string | null;\n encrypted: boolean;\n requestId?: string;\n reason?: string;\n }): Promise<void> | void;\n}\n\n/** Action handler signature for `Specifier.type === 'action_button'`. */\nexport type SettingsActionHandler = (input: {\n namespace: string;\n actionId: string;\n values: Record<string, unknown>;\n payload?: unknown;\n ctx: SettingsContext;\n}) => Promise<SettingsActionResult> | SettingsActionResult;\n\nexport interface SettingsServiceOptions {\n /** Persistence engine. When undefined, an in-memory store is used. */\n engine?: SettingsEngine;\n /** Crypto adapter for `encrypted` values. Defaults to NoopCryptoAdapter. */\n crypto?: CryptoAdapter;\n /**\n * Phase 3 ICryptoProvider used together with `secretStore`. When both\n * are wired, encrypted writes flow to `sys_secret` and `value_enc`\n * holds the handle id. When omitted, the legacy inline `crypto`\n * adapter path remains in effect (back-compat).\n */\n cryptoProvider?: import('@objectstack/spec/contracts').ICryptoProvider;\n /** Phase 3 secret store backing the `sys_secret` object. */\n secretStore?: SettingsSecretStore;\n /** Audit sink. When undefined, writes still succeed but are not logged. */\n audit?: SettingsAuditSink;\n /** Phase 3 dedicated writer for `sys_setting_audit`. */\n auditWriter?: SettingsAuditWriter;\n /**\n * `process.env`-like map. Defaults to `process.env`. Injected so\n * unit tests can simulate locked values without polluting the host\n * environment.\n */\n env?: Record<string, string | undefined>;\n /** Object name backing the K/V store. Defaults to 'sys_setting'. */\n objectName?: string;\n}\n\n/**\n * Convert `(namespace, key)` to the ObjectStack-owned env var convention:\n * `OS_` prefix, uppercase, dots → underscores, hyphens → underscores.\n */\nexport function envKeyOf(namespace: string, key: string): string {\n const slug = `${namespace}_${key}`.replace(/[.-]/g, '_').toUpperCase();\n return `OS_${slug}`;\n}\n\n/** Thrown when a caller tries to write a value pinned by env. */\nexport class SettingsLockedError extends Error {\n readonly code = 'SETTINGS_LOCKED' as const;\n constructor(\n readonly namespace: string,\n readonly key: string,\n readonly reason = 'locked-by-env',\n ) {\n super(`Setting '${namespace}.${key}' is locked (${reason}).`);\n }\n}\n\n/** Thrown when the requested namespace has no registered manifest. */\nexport class UnknownNamespaceError extends Error {\n readonly code = 'SETTINGS_UNKNOWN_NAMESPACE' as const;\n constructor(readonly namespace: string) {\n super(`No settings manifest registered for namespace '${namespace}'.`);\n }\n}\n\n/** Thrown when a key isn't declared by the namespace's manifest. */\nexport class UnknownKeyError extends Error {\n readonly code = 'SETTINGS_UNKNOWN_KEY' as const;\n constructor(readonly namespace: string, readonly key: string) {\n super(`Key '${key}' is not declared in manifest '${namespace}'.`);\n }\n}\n\n/**\n * Thrown when a write would leave the namespace in an invalid state —\n * a `required` field that is visible under the post-write values is\n * empty (e.g. provider=cloudflare saved without an API key). The whole\n * batch is rejected; `fields` maps each offending key to a message the\n * UI can render inline.\n */\nexport class SettingsValidationError extends Error {\n readonly code = 'SETTINGS_VALIDATION' as const;\n constructor(\n readonly namespace: string,\n readonly fields: Record<string, string>,\n ) {\n super(\n `Settings for '${namespace}' are incomplete: ` +\n Object.entries(fields).map(([k, msg]) => `${k} — ${msg}`).join('; '),\n );\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Evaluator for the restricted visibility expressions used by settings\n * manifests, e.g. `\"${data.provider === 'cloudflare'}\"` or\n * `\"${data.embedder_provider && data.embedder_provider !== 'none'}\"`.\n *\n * The server needs these at save time so `setMany` can enforce `required`\n * only on fields that are actually visible for the current provider —\n * a half-filled Cloudflare form must be rejected, while OpenAI fields\n * stay irrelevant. The console UI evaluates the same strings client-side;\n * this is deliberately NOT a general JS evaluator, just the tiny grammar\n * the manifests use:\n *\n * orExpr := andExpr ('||' andExpr)*\n * andExpr := unary ('&&' unary)*\n * unary := '!' unary | comparison\n * compare := primary (('===' | '!==' | '==' | '!=') primary)?\n * primary := '(' orExpr ')' | string | number | true | false | null | data.<ident>\n *\n * Anything outside the grammar throws `VisibilityParseError`; callers\n * should treat that as \"cannot determine visibility\" and skip validation\n * for the field (lenient) rather than block the save.\n */\n\nexport class VisibilityParseError extends Error {\n constructor(expr: string, detail: string) {\n super(`Cannot parse visibility expression \"${expr}\": ${detail}`);\n this.name = 'VisibilityParseError';\n }\n}\n\ntype Token =\n | { kind: 'punct'; value: '(' | ')' | '!' | '&&' | '||' | '===' | '!==' | '==' | '!=' }\n | { kind: 'string'; value: string }\n | { kind: 'number'; value: number }\n | { kind: 'keyword'; value: boolean | null }\n | { kind: 'ref'; value: string };\n\n/**\n * Unwrap the manifest forms a `visible` field can take: a bare string,\n * a `${…}` template string, or a `{ dialect, source }` envelope.\n */\nexport function visibilitySource(visible: unknown): string | undefined {\n let src: string | undefined;\n if (typeof visible === 'string') src = visible;\n else if (visible && typeof visible === 'object' && typeof (visible as { source?: unknown }).source === 'string') {\n src = (visible as { source: string }).source;\n }\n if (src === undefined) return undefined;\n const trimmed = src.trim();\n if (trimmed.startsWith('${') && trimmed.endsWith('}')) return trimmed.slice(2, -1).trim();\n return trimmed;\n}\n\n/** `data.*` keys referenced by a visibility expression (regex-level scan). */\nexport function referencedKeys(visible: unknown): string[] {\n const src = visibilitySource(visible);\n if (!src) return [];\n return [...src.matchAll(/data\\.([A-Za-z_][A-Za-z0-9_]*)/g)].map((m) => m[1]);\n}\n\nfunction tokenize(expr: string): Token[] {\n const tokens: Token[] = [];\n let i = 0;\n while (i < expr.length) {\n const ch = expr[i];\n if (/\\s/.test(ch)) { i++; continue; }\n if (ch === '(' || ch === ')') { tokens.push({ kind: 'punct', value: ch }); i++; continue; }\n let matchedOp = false;\n for (const op of ['===', '!==', '==', '!=', '&&', '||'] as const) {\n if (expr.startsWith(op, i)) {\n tokens.push({ kind: 'punct', value: op });\n i += op.length;\n matchedOp = true;\n break;\n }\n }\n if (matchedOp) continue;\n if (ch === '!') { tokens.push({ kind: 'punct', value: '!' }); i++; continue; }\n if (ch === \"'\" || ch === '\"') {\n const quote = ch;\n let j = i + 1;\n let out = '';\n while (j < expr.length && expr[j] !== quote) {\n if (expr[j] === '\\\\' && j + 1 < expr.length) { out += expr[j + 1]; j += 2; }\n else { out += expr[j]; j++; }\n }\n if (j >= expr.length) throw new VisibilityParseError(expr, 'unterminated string');\n tokens.push({ kind: 'string', value: out });\n i = j + 1;\n continue;\n }\n if (/[0-9]/.test(ch)) {\n const m = /^[0-9]+(\\.[0-9]+)?/.exec(expr.slice(i))!;\n tokens.push({ kind: 'number', value: Number(m[0]) });\n i += m[0].length;\n continue;\n }\n if (/[A-Za-z_]/.test(ch)) {\n const m = /^[A-Za-z_][A-Za-z0-9_.]*/.exec(expr.slice(i))!;\n const word = m[0];\n if (word === 'true') tokens.push({ kind: 'keyword', value: true });\n else if (word === 'false') tokens.push({ kind: 'keyword', value: false });\n else if (word === 'null') tokens.push({ kind: 'keyword', value: null });\n else if (word.startsWith('data.')) {\n const key = word.slice('data.'.length);\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) throw new VisibilityParseError(expr, `unsupported reference \"${word}\"`);\n tokens.push({ kind: 'ref', value: key });\n } else throw new VisibilityParseError(expr, `unsupported identifier \"${word}\"`);\n i += word.length;\n continue;\n }\n throw new VisibilityParseError(expr, `unexpected character \"${ch}\"`);\n }\n return tokens;\n}\n\n/**\n * Evaluate a visibility expression against the merged form data.\n * Throws {@link VisibilityParseError} for anything outside the grammar.\n */\nexport function evaluateVisibility(visible: unknown, data: Record<string, unknown>): boolean {\n const src = visibilitySource(visible);\n if (!src) return true;\n const tokens = tokenize(src);\n let pos = 0;\n\n const peek = (): Token | undefined => tokens[pos];\n const eat = (value: string): boolean => {\n const t = tokens[pos];\n if (t?.kind === 'punct' && t.value === value) { pos++; return true; }\n return false;\n };\n\n function primary(): unknown {\n const t = peek();\n if (!t) throw new VisibilityParseError(src!, 'unexpected end of expression');\n if (t.kind === 'punct' && t.value === '(') {\n pos++;\n const v = orExpr();\n if (!eat(')')) throw new VisibilityParseError(src!, 'missing closing parenthesis');\n return v;\n }\n if (t.kind === 'string' || t.kind === 'number' || t.kind === 'keyword') { pos++; return t.value; }\n if (t.kind === 'ref') { pos++; return data[t.value]; }\n throw new VisibilityParseError(src!, `unexpected token`);\n }\n\n function comparison(): unknown {\n const left = primary();\n const t = peek();\n if (t?.kind === 'punct' && ['===', '!==', '==', '!='].includes(t.value)) {\n pos++;\n const right = primary();\n // Loose == / != are treated as strict — manifest values are\n // primitives written by hand; the distinction never matters here.\n return t.value === '===' || t.value === '==' ? left === right : left !== right;\n }\n return left;\n }\n\n function unary(): unknown {\n if (eat('!')) return !unary();\n return comparison();\n }\n\n function andExpr(): unknown {\n let v = unary();\n while (eat('&&')) {\n const r = unary();\n v = v && r;\n }\n return v;\n }\n\n function orExpr(): unknown {\n let v = andExpr();\n while (eat('||')) {\n const r = andExpr();\n v = v || r;\n }\n return v;\n }\n\n const result = orExpr();\n if (pos !== tokens.length) throw new VisibilityParseError(src, 'trailing tokens');\n return Boolean(result);\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type {\n SettingsManifest,\n ResolvedSettingValue,\n SettingsNamespacePayload,\n SettingsActionResult,\n SpecifierScope,\n SettingsChangeEvent,\n SettingsChangeHandler,\n SettingsUnsubscribe,\n} from '@objectstack/spec/system';\nimport {\n type CryptoAdapter,\n NoopCryptoAdapter,\n} from './crypto-adapter.js';\nimport {\n type SettingsActionHandler,\n type SettingsAuditSink,\n type SettingsContext,\n type SettingsEngine,\n type SettingsRow,\n type SettingsServiceOptions,\n envKeyOf,\n SettingsLockedError,\n SettingsValidationError,\n UnknownKeyError,\n UnknownNamespaceError,\n} from './settings-service.types.js';\nimport { evaluateVisibility, referencedKeys } from './visibility-eval.js';\n\nconst DEFAULT_OBJECT = 'sys_setting';\n\n/**\n * Value-bearing specifier types — drives which entries we expect to\n * find in the K/V store. Keeps the resolver in sync with the spec\n * without importing the (large) Zod enum at runtime.\n */\nconst LAYOUT_ONLY_TYPES = new Set([\n 'group',\n 'info_banner',\n 'child_pane',\n 'title_value',\n 'action_button',\n]);\n\ninterface RegisteredManifest {\n manifest: SettingsManifest;\n /** Resolved specifier scopes for fast lookup. */\n scopes: Map<string, SpecifierScope>;\n /** Specifiers marked encrypted (or implicit for `password`). */\n encryptedKeys: Set<string>;\n /** Default values from the manifest, keyed by specifier key. */\n defaults: Map<string, unknown>;\n /** Action handlers registered alongside this manifest. */\n actions: Map<string, SettingsActionHandler>;\n}\n\n/**\n * Concrete SettingsService. See `src/settings-service.types.ts` for\n * the supporting types and `README.md` for the high-level contract.\n */\nexport class SettingsService {\n private engine?: SettingsEngine;\n private readonly crypto: CryptoAdapter;\n private cryptoProvider?: import('@objectstack/spec/contracts').ICryptoProvider;\n private secretStore?: import('./settings-service.types.js').SettingsSecretStore;\n private audit?: SettingsAuditSink;\n private auditWriter?: import('./settings-service.types.js').SettingsAuditWriter;\n private readonly env: Record<string, string | undefined>;\n private readonly objectName: string;\n private readonly registry = new Map<string, RegisteredManifest>();\n /** In-memory fallback when no engine is wired. */\n private readonly memory: SettingsRow[] = [];\n /** Change subscribers, optionally scoped to a namespace. */\n private readonly subscribers = new Set<{\n ns?: string;\n handler: SettingsChangeHandler;\n }>();\n\n constructor(opts: SettingsServiceOptions = {}) {\n this.engine = opts.engine;\n this.crypto = opts.crypto ?? new NoopCryptoAdapter();\n this.cryptoProvider = opts.cryptoProvider;\n this.secretStore = opts.secretStore;\n this.audit = opts.audit;\n this.auditWriter = opts.auditWriter;\n this.env = opts.env ?? (typeof process !== 'undefined' ? process.env : {});\n this.objectName = opts.objectName ?? DEFAULT_OBJECT;\n }\n\n /**\n * Late-bind a data engine and (optionally) an audit sink. Plugins\n * call this from `kernel:ready` once `objectql` is wired so the\n * SettingsService swaps from its in-memory fallback to the real\n * `sys_setting` table without re-registering the service.\n */\n bindEngine(\n engine: SettingsEngine,\n audit?: SettingsAuditSink,\n extras?: {\n secretStore?: import('./settings-service.types.js').SettingsSecretStore;\n auditWriter?: import('./settings-service.types.js').SettingsAuditWriter;\n cryptoProvider?: import('@objectstack/spec/contracts').ICryptoProvider;\n },\n ): void {\n this.engine = engine;\n if (audit) this.audit = audit;\n if (extras?.secretStore) this.secretStore = extras.secretStore;\n if (extras?.auditWriter) this.auditWriter = extras.auditWriter;\n if (extras?.cryptoProvider) this.cryptoProvider = extras.cryptoProvider;\n\n // Notify subscribers that the persistent store is now available so\n // late-binders (e.g. AIServicePlugin's adapter rebuild on saved\n // provider settings) can re-fetch with real DB-backed values rather\n // than only the in-memory defaults that were visible at\n // `kernel:ready` ordering before the engine was wired.\n for (const ns of this.registry.keys()) {\n this.emitChange({\n namespace: ns,\n key: '*',\n scope: 'global',\n action: 'set',\n at: new Date().toISOString(),\n });\n }\n }\n\n /**\n * Cascade priority ranks for lock comparisons (lower = higher\n * precedence). env<global<tenant<user<default. A locked row at a\n * lower rank blocks writes at all higher ranks.\n */\n private scopeRank(scope: SpecifierScope | 'env' | 'default'): number {\n switch (scope) {\n case 'global': return 1;\n case 'tenant': return 2;\n case 'user': return 3;\n default: return 99;\n }\n }\n\n // ---------------------------------------------------------------------\n // Change events (Phase 1)\n // ---------------------------------------------------------------------\n\n /**\n * Subscribe to `settings:changed` events. When `namespace` is set the\n * handler only fires for that namespace, otherwise it fires for every\n * mutation across the service.\n *\n * Returns an idempotent unsubscribe handle — call it from the\n * consumer's shutdown hook to avoid leaks.\n */\n subscribe(\n namespace: string | undefined,\n handler: SettingsChangeHandler,\n ): SettingsUnsubscribe {\n const entry = { ns: namespace, handler };\n this.subscribers.add(entry);\n return () => {\n this.subscribers.delete(entry);\n };\n }\n\n /**\n * Dispatch a change event to all matching subscribers. Errors thrown\n * by a handler are swallowed to keep the bus crash-safe — handlers\n * are expected to enqueue async work themselves.\n */\n private emitChange(event: SettingsChangeEvent): void {\n if (this.subscribers.size === 0) return;\n for (const sub of this.subscribers) {\n if (sub.ns && sub.ns !== event.namespace) continue;\n try {\n sub.handler(event);\n } catch {\n // Swallow — never break the writer because a listener misbehaves.\n }\n }\n }\n\n // ---------------------------------------------------------------------\n // Manifest registry\n // ---------------------------------------------------------------------\n\n /** Register (or replace) a manifest. Idempotent. */\n registerManifest(manifest: SettingsManifest): void {\n const scopes = new Map<string, SpecifierScope>();\n const encryptedKeys = new Set<string>();\n const defaults = new Map<string, unknown>();\n const defaultScope = manifest.scope ?? 'tenant';\n for (const spec of manifest.specifiers) {\n if (!spec.key || LAYOUT_ONLY_TYPES.has(spec.type)) continue;\n scopes.set(spec.key, spec.scope ?? defaultScope);\n if (spec.encrypted || spec.type === 'password') encryptedKeys.add(spec.key);\n if (typeof spec.default !== 'undefined') defaults.set(spec.key, spec.default);\n }\n const prev = this.registry.get(manifest.namespace);\n const actions = prev?.actions ?? new Map<string, SettingsActionHandler>();\n this.registry.set(manifest.namespace, { manifest, scopes, encryptedKeys, defaults, actions });\n }\n\n /** Look up a manifest, or throw `UnknownNamespaceError`. */\n getManifest(namespace: string): SettingsManifest {\n const reg = this.registry.get(namespace);\n if (!reg) throw new UnknownNamespaceError(namespace);\n return reg.manifest;\n }\n\n /** List all registered manifests, optionally filtered by permission. */\n listManifests(ctx: SettingsContext = {}): SettingsManifest[] {\n const perms = new Set(ctx.permissions ?? []);\n const all = Array.from(this.registry.values()).map((r) => r.manifest);\n // Empty permissions ⇒ pass-through (server-side trust, e.g. boot tests).\n if (perms.size === 0) return all;\n return all.filter((m) => perms.has(m.readPermission ?? 'setup.access'));\n }\n\n /** Register a handler for an `action_button` declared in a manifest. */\n registerAction(namespace: string, actionId: string, handler: SettingsActionHandler): void {\n const reg = this.registry.get(namespace);\n if (!reg) throw new UnknownNamespaceError(namespace);\n reg.actions.set(actionId, handler);\n }\n\n // ---------------------------------------------------------------------\n // Resolver\n // ---------------------------------------------------------------------\n\n /** Resolve a single key. */\n async get<T = unknown>(\n namespace: string,\n key: string,\n ctx: SettingsContext = {},\n ): Promise<ResolvedSettingValue<T>> {\n const reg = this.registry.get(namespace);\n if (!reg) throw new UnknownNamespaceError(namespace);\n if (!reg.scopes.has(key)) throw new UnknownKeyError(namespace, key);\n\n // 1. OS_* env\n const envName = envKeyOf(namespace, key);\n const envRaw = this.env[envName];\n if (typeof envRaw === 'string') {\n const def = reg.defaults.get(key);\n const value = coerceEnvValue(envRaw, def);\n return {\n value: value as T,\n source: 'env',\n locked: true,\n lockedReason: `Set via env: ${envName}`,\n cascadeChain: [\n { scope: 'env', value, locked: true, lockedReason: `Set via env: ${envName}`, effective: true },\n ],\n };\n }\n\n const scope = reg.scopes.get(key)!;\n // For 'user' scope we pre-filter by user_id; for 'tenant' and 'global'\n // we load everything for the namespace and pick the right row below.\n const rows = await this.loadRows(namespace, scope === 'user' ? ctx.userId ?? null : null);\n\n // 2. cascade walk — OS_* env (handled above) > global > tenant > user > default\n //\n // Build the full chain in declared order so the UI can render\n // \"Inherited from Global / Locked by Global / Overrides tenant\"\n // badges. The first non-null entry wins as `source`.\n const chain: NonNullable<ResolvedSettingValue['cascadeChain']> = [];\n\n const globalRow = rows.find((r) => r.key === key && r.scope === 'global');\n if (globalRow) {\n const value = await this.materialiseRow(globalRow);\n chain.push({\n scope: 'global',\n value,\n locked: !!globalRow.locked,\n lockedReason: globalRow.locked_reason ?? undefined,\n });\n }\n\n if (scope === 'tenant' || scope === 'user') {\n const tenantRow = rows.find((r) => r.key === key && r.scope === 'tenant');\n if (tenantRow) {\n chain.push({\n scope: 'tenant',\n value: await this.materialiseRow(tenantRow),\n locked: !!tenantRow.locked,\n lockedReason: tenantRow.locked_reason ?? undefined,\n });\n }\n }\n\n if (scope === 'user') {\n const userRow = rows.find((r) => r.key === key && r.scope === 'user');\n if (userRow) {\n chain.push({\n scope: 'user',\n value: await this.materialiseRow(userRow),\n });\n }\n }\n\n const def = reg.defaults.get(key);\n chain.push({ scope: 'default', value: def ?? null });\n\n // Effective row: highest priority entry. Lock anywhere up the chain\n // locks the effective value (lower scopes can't shadow it).\n const lockedEntry = chain.find((e) => e.locked === true);\n const effective = chain.find((e) => e.value !== null && e.value !== undefined) ?? chain[chain.length - 1];\n effective.effective = true;\n\n return {\n value: effective.value as T,\n source: effective.scope as ResolvedSettingValue['source'],\n locked: !!lockedEntry,\n lockedReason: lockedEntry?.lockedReason,\n cascadeChain: chain,\n };\n }\n\n /** Resolve every value in a namespace + return the manifest. */\n async getNamespace(\n namespace: string,\n ctx: SettingsContext = {},\n ): Promise<SettingsNamespacePayload> {\n const reg = this.registry.get(namespace);\n if (!reg) throw new UnknownNamespaceError(namespace);\n\n const values: Record<string, ResolvedSettingValue> = {};\n for (const [key] of reg.scopes) {\n values[key] = await this.get(namespace, key, ctx);\n }\n return { manifest: reg.manifest, values };\n }\n\n // ---------------------------------------------------------------------\n // Reactive client (Phase 1)\n // ---------------------------------------------------------------------\n\n /**\n * Build a reactive `ISettingsClient` for a namespace.\n *\n * The client maintains an internal snapshot of the resolved values,\n * refreshing on every `settings:changed` event for the namespace.\n * Consumers call `current` / `get(key)` for synchronous reads and\n * register handlers via `onChange()`.\n *\n * `schema` is optional. When supplied, the snapshot is parsed (and\n * defaulted) through the Zod schema on each refresh — this gives\n * plugins strong types and runtime validation in one call. When\n * absent, raw resolved values flow through unchanged (used by the\n * dynamic console UI which validates per-field).\n */\n async createClient<T extends Record<string, unknown> = Record<string, unknown>>(\n namespace: string,\n opts: {\n ctx?: SettingsContext;\n parse?: (raw: Record<string, unknown>) => T;\n } = {},\n ): Promise<{\n readonly namespace: string;\n readonly current: T;\n get<K extends keyof T>(key: K): T[K];\n onChange(handler: SettingsChangeHandler): SettingsUnsubscribe;\n refresh(): Promise<void>;\n dispose(): void;\n }> {\n const ctx = opts.ctx ?? {};\n let snapshot: T = await this.snapshotOf<T>(namespace, ctx, opts.parse);\n\n const off = this.subscribe(namespace, () => {\n // Fire-and-forget refresh; new readers see the latest snapshot.\n void this.snapshotOf<T>(namespace, ctx, opts.parse).then((next) => {\n snapshot = next;\n });\n });\n\n return {\n namespace,\n get current() {\n return snapshot;\n },\n get<K extends keyof T>(key: K): T[K] {\n return snapshot[key];\n },\n onChange: (handler) => this.subscribe(namespace, handler),\n refresh: async () => {\n snapshot = await this.snapshotOf<T>(namespace, ctx, opts.parse);\n },\n dispose: off,\n };\n }\n\n private async snapshotOf<T>(\n namespace: string,\n ctx: SettingsContext,\n parse?: (raw: Record<string, unknown>) => T,\n ): Promise<T> {\n const payload = await this.getNamespace(namespace, ctx);\n const raw: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(payload.values)) raw[k] = v.value;\n return parse ? parse(raw) : (raw as T);\n }\n\n // ---------------------------------------------------------------------\n // Mutations\n // ---------------------------------------------------------------------\n\n /** Persist a single key. Throws SettingsLockedError when env-locked. */\n async set(\n namespace: string,\n key: string,\n value: unknown,\n ctx: SettingsContext = {},\n ): Promise<ResolvedSettingValue> {\n return (await this.setMany(namespace, { [key]: value }, ctx))[key];\n }\n\n /** Persist multiple keys atomically (best-effort). */\n async setMany(\n namespace: string,\n patch: Record<string, unknown>,\n ctx: SettingsContext = {},\n ): Promise<Record<string, ResolvedSettingValue>> {\n const reg = this.registry.get(namespace);\n if (!reg) throw new UnknownNamespaceError(namespace);\n\n // Pre-flight: reject the whole batch if any key is locked or unknown.\n for (const key of Object.keys(patch)) {\n if (!reg.scopes.has(key)) throw new UnknownKeyError(namespace, key);\n const envRaw = this.env[envKeyOf(namespace, key)];\n if (typeof envRaw === 'string') throw new SettingsLockedError(namespace, key);\n\n // Phase 2 lock: a row at an upper scope marked locked=true\n // refuses writes at this (lower) scope. Writing AT the same\n // scope as the lock is still permitted (i.e. a platform admin\n // can edit a globally-locked value; a tenant admin cannot).\n const scope = reg.scopes.get(key)!;\n const rows = await this.loadRows(namespace, scope === 'user' ? ctx.userId ?? null : null);\n const upper = rows.find(\n (r) =>\n r.key === key &&\n r.locked === true &&\n this.scopeRank(r.scope) < this.scopeRank(scope),\n );\n if (upper) {\n throw new SettingsLockedError(namespace, key, `locked-by-${upper.scope}`);\n }\n }\n\n // Reject writes that would leave the namespace in a known-broken\n // state (visible required field empty / pattern mismatch). See\n // validatePatch for the exact semantics.\n await this.validatePatch(namespace, patch, ctx);\n\n for (const [key, rawValue] of Object.entries(patch)) {\n const scope = reg.scopes.get(key)!;\n // global rows are platform-wide (tenant_id=null, user_id=null);\n // user rows pin to ctx.userId; tenant rows leave user_id null and\n // let the engine's tenant scoping fill in tenant_id from ctx.\n const userId = scope === 'user' ? ctx.userId ?? null : null;\n const isEncrypted = reg.encryptedKeys.has(key);\n const isNull = rawValue === null || typeof rawValue === 'undefined';\n\n let storedValue: unknown | null = null;\n let storedEnc: string | null = null;\n let digest = '';\n\n if (!isNull) {\n if (isEncrypted) {\n const plain = typeof rawValue === 'string' ? rawValue : JSON.stringify(rawValue);\n // Phase 3 split: when a sys_secret store + ICryptoProvider are\n // wired, persist the ciphertext in sys_secret and keep the\n // handle id in sys_setting.value_enc. Otherwise fall back to\n // the legacy inline crypto adapter path for back-compat.\n if (this.cryptoProvider && this.secretStore) {\n const handle = await this.cryptoProvider.encrypt(plain, {\n namespace,\n key,\n tenantId: ctx.tenantId,\n });\n await this.secretStore.insert({\n id: handle.id,\n namespace,\n key,\n kms_key_id: handle.kmsKeyId,\n alg: handle.alg,\n version: handle.version,\n ciphertext: handle.ciphertext,\n });\n storedEnc = handle.id;\n digest = this.cryptoProvider.digest(plain);\n } else {\n storedEnc = await this.crypto.encrypt(plain, { namespace, key });\n digest = this.crypto.digest(plain);\n }\n } else {\n storedValue = rawValue;\n digest = this.crypto.digest(stableStringify(rawValue));\n }\n }\n\n await this.upsertRow({\n namespace,\n key,\n scope,\n user_id: userId,\n value: storedValue,\n value_enc: storedEnc,\n encrypted: isEncrypted,\n updated_at: new Date().toISOString(),\n updated_by: ctx.userId ?? null,\n });\n\n if (this.audit) {\n await this.audit.record({\n namespace,\n key,\n scope,\n userId: ctx.userId,\n action: isNull ? 'reset' : 'set',\n valueDigest: isEncrypted ? '<encrypted:' + digest + '>' : digest,\n encrypted: isEncrypted,\n requestId: ctx.requestId,\n });\n }\n\n if (this.auditWriter) {\n try {\n await this.auditWriter.write({\n namespace,\n key,\n scope,\n action: isNull ? 'reset' : 'set',\n source: 'api',\n actorId: ctx.userId,\n oldHash: null,\n newHash: isNull ? null : digest,\n encrypted: isEncrypted,\n requestId: ctx.requestId,\n });\n } catch {\n // never fail a write because the audit table is unhappy.\n }\n }\n\n this.emitChange({\n namespace,\n key,\n scope,\n action: isNull ? 'reset' : 'set',\n at: new Date().toISOString(),\n });\n }\n\n // Re-resolve so callers see the post-write effective values.\n const out: Record<string, ResolvedSettingValue> = {};\n for (const key of Object.keys(patch)) {\n out[key] = await this.get(namespace, key, ctx);\n }\n return out;\n }\n\n /**\n * Save-time validation for `setMany`, fulfilling the spec promise that\n * `required` is enforced server-side and hidden specifiers are not\n * validated. Semantics, tuned to reject broken configs without\n * breaking unrelated single-key writes:\n *\n * - The post-write value map is computed (current values overlaid\n * with the patch; `null` patch entries fall back to the default).\n * - A specifier is checked only when the patch TOUCHES it — its own\n * key is in the patch, or a key its `visible` expression references\n * is (switching provider must validate that provider's fields).\n * - `required` + visible + empty → rejected.\n * - `pattern` (text fields) + non-empty value that mismatches → rejected.\n * - All-null patches (namespace reset) and unparseable visibility\n * expressions skip validation rather than block the write.\n */\n private async validatePatch(\n namespace: string,\n patch: Record<string, unknown>,\n ctx: SettingsContext,\n ): Promise<void> {\n const reg = this.registry.get(namespace);\n if (!reg) return;\n const entries = Object.entries(patch);\n if (entries.length === 0) return;\n // An all-null patch is a reset — clearing values is never blocked.\n if (entries.every(([, v]) => v === null || typeof v === 'undefined')) return;\n\n // Post-write value map: resolved values overlaid with the patch.\n const data: Record<string, unknown> = {};\n for (const [key] of reg.scopes) {\n data[key] = (await this.get(namespace, key, ctx)).value;\n }\n for (const [key, value] of entries) {\n data[key] = value === null || typeof value === 'undefined'\n ? reg.defaults.get(key) ?? null\n : value;\n }\n\n const patchKeys = new Set(Object.keys(patch));\n const errors: Record<string, string> = {};\n\n for (const spec of (reg.manifest.specifiers ?? []) as Array<Record<string, unknown>>) {\n const key = spec.key as string | undefined;\n const type = String(spec.type ?? '');\n if (!key || LAYOUT_ONLY_TYPES.has(type)) continue;\n\n let visible = true;\n let deps: string[] = [];\n if (typeof spec.visible !== 'undefined') {\n try {\n visible = evaluateVisibility(spec.visible, data);\n deps = referencedKeys(spec.visible);\n } catch {\n continue; // can't determine visibility — stay lenient\n }\n }\n if (!visible) continue;\n if (!patchKeys.has(key) && !deps.some((d) => patchKeys.has(d))) continue;\n\n const value = data[key];\n const label = typeof spec.label === 'string' ? spec.label : key;\n const empty =\n value === null || typeof value === 'undefined' ||\n (typeof value === 'string' && value.trim() === '');\n\n if (spec.required === true && empty) {\n errors[key] = `${label} is required for this configuration.`;\n continue;\n }\n if (!empty && typeof spec.pattern === 'string' && typeof value === 'string') {\n let re: RegExp | undefined;\n try {\n re = new RegExp(spec.pattern);\n } catch {\n re = undefined; // invalid manifest pattern — don't block writes\n }\n if (re && !re.test(value)) {\n const hint = typeof spec.description === 'string' ? ` ${spec.description}` : '';\n errors[key] = `${label} does not match the expected format.${hint}`;\n }\n }\n }\n\n if (Object.keys(errors).length > 0) {\n throw new SettingsValidationError(namespace, errors);\n }\n }\n\n /**\n * Clear every persisted row in a namespace so values fall back to\n * env/defaults. Env-locked keys are untouched (env wins over rows\n * anyway and refuses writes). Persisted rows are nulled rather than\n * deleted so the audit trail records the reset per key.\n *\n * Returns the number of cleared keys.\n */\n async resetNamespace(namespace: string, ctx: SettingsContext = {}): Promise<number> {\n const payload = await this.getNamespace(namespace, ctx);\n const patch: Record<string, null> = {};\n for (const [key, v] of Object.entries(payload.values)) {\n if (v.source === 'global' || v.source === 'tenant' || v.source === 'user') {\n patch[key] = null;\n }\n }\n const keys = Object.keys(patch);\n if (keys.length > 0) await this.setMany(namespace, patch, ctx);\n return keys.length;\n }\n\n /** Invoke a declared action (test connection, rotate, …). */\n async runAction(\n namespace: string,\n actionId: string,\n payload: unknown,\n ctx: SettingsContext = {},\n ): Promise<SettingsActionResult> {\n const reg = this.registry.get(namespace);\n if (!reg) throw new UnknownNamespaceError(namespace);\n const handler = reg.actions.get(actionId);\n if (!handler) {\n // Built-in fallback: every namespace gets a `reset` action that\n // clears persisted rows (back to env/defaults). Plugins may\n // override it via registerAction for richer behaviour (e.g. the\n // AI plugin re-runs env adapter detection after the clear).\n if (actionId === 'reset') {\n const cleared = await this.resetNamespace(namespace, ctx);\n return {\n ok: true,\n severity: 'info',\n message: cleared > 0\n ? `Cleared ${cleared} saved value(s); environment/default configuration is back in effect.`\n : 'No saved values to clear — already using environment/default configuration.',\n };\n }\n return {\n ok: false,\n severity: 'error',\n message: `No handler registered for action '${actionId}' in '${namespace}'.`,\n };\n }\n const values: Record<string, unknown> = {};\n for (const [key] of reg.scopes) {\n values[key] = (await this.get(namespace, key, ctx)).value;\n }\n try {\n return await handler({ namespace, actionId, values, payload, ctx });\n } catch (err: any) {\n return {\n ok: false,\n severity: 'error',\n message: err?.message ?? 'Action handler threw.',\n };\n }\n }\n\n // ---------------------------------------------------------------------\n // Persistence helpers (engine or in-memory)\n // ---------------------------------------------------------------------\n\n private async loadRows(namespace: string, userId: string | null): Promise<SettingsRow[]> {\n if (this.engine) {\n const where: Record<string, unknown> = { namespace };\n if (userId !== null) where.user_id = userId;\n // Settings rows include platform-wide (`global` scope, tenant_id=null)\n // entries; bypass the tenant-scoping audit warning so loads work\n // uniformly across global/tenant/user without log noise. Per-tenant\n // isolation for `tenant`-scope rows is still enforced by the engine\n // once an ExecutionContext.tenantId is plumbed through (Phase 2+).\n const rows = await this.engine.find(this.objectName, {\n where,\n bypassTenantAudit: true,\n } as any);\n return rows.map((r) => ({\n namespace: r.namespace,\n key: r.key,\n scope: r.scope as SpecifierScope,\n user_id: r.user_id ?? null,\n value: r.value ?? null,\n value_enc: r.value_enc ?? null,\n encrypted: Boolean(r.encrypted),\n locked: Boolean(r.locked),\n locked_reason: r.locked_reason ?? null,\n updated_at: r.updated_at,\n updated_by: r.updated_by ?? null,\n }));\n }\n return this.memory.filter(\n (r) =>\n r.namespace === namespace &&\n (userId === null || r.user_id === userId || r.scope === 'tenant' || r.scope === 'global'),\n );\n }\n\n private async upsertRow(row: SettingsRow): Promise<void> {\n if (this.engine) {\n const where: Record<string, unknown> = {\n namespace: row.namespace,\n key: row.key,\n scope: row.scope,\n user_id: row.user_id ?? null,\n };\n // global rows are platform-wide — bypass the tenant audit warning\n // (we intentionally write tenant_id=null). tenant/user rows still\n // benefit from the warning when ctx.tenantId is missing.\n const bypass = row.scope === 'global' ? { bypassTenantAudit: true } : {};\n const existing = await this.engine.find(this.objectName, {\n where,\n limit: 1,\n ...bypass,\n } as any);\n if (existing[0]) {\n await this.engine.update(this.objectName, {\n where,\n data: { ...row },\n ...bypass,\n } as any);\n } else {\n await this.engine.insert(this.objectName, { ...row }, bypass as any);\n }\n return;\n }\n const idx = this.memory.findIndex(\n (r) =>\n r.namespace === row.namespace &&\n r.key === row.key &&\n r.scope === row.scope &&\n (r.user_id ?? null) === (row.user_id ?? null),\n );\n if (idx >= 0) this.memory[idx] = row;\n else this.memory.push(row);\n }\n\n private async materialiseRow(row: SettingsRow): Promise<unknown> {\n if (row.encrypted) {\n if (!row.value_enc) return null;\n let plain: string;\n try {\n // Phase 3: when the value_enc looks like a sys_secret handle and\n // both the secretStore + cryptoProvider are wired, dereference\n // through sys_secret. Otherwise (legacy rows or in-memory tests)\n // fall back to inline crypto-adapter decryption.\n if (\n this.cryptoProvider &&\n this.secretStore &&\n typeof row.value_enc === 'string' &&\n row.value_enc.startsWith('sec_')\n ) {\n const secret = await this.secretStore.get(row.value_enc);\n if (!secret) return null;\n plain = await this.cryptoProvider.decrypt(\n {\n id: secret.id,\n kmsKeyId: secret.kms_key_id,\n alg: secret.alg,\n version: secret.version,\n ciphertext: secret.ciphertext,\n },\n { namespace: row.namespace, key: row.key },\n );\n } else {\n plain = await this.crypto.decrypt(row.value_enc, {\n namespace: row.namespace,\n key: row.key,\n });\n }\n } catch (err) {\n // Decrypt failures are almost always operational: the crypto\n // provider's data key changed (e.g. InMemoryCryptoProvider\n // generated a fresh ephemeral key after a restart) and the\n // stored AES-GCM auth tag no longer verifies. Bubbling the\n // raw Node error would 500 the entire `getNamespace` request\n // and lock the operator out of the settings UI — including\n // the very inputs they'd use to re-enter the secret. Instead,\n // log once and surface `null` so the field renders as empty\n // and remains editable.\n console.warn(\n `[SettingsService] failed to decrypt ${row.namespace}.${row.key}: ${(err as Error)?.message ?? err}. ` +\n `Returning null so the namespace remains readable; re-save the field to repair.`,\n );\n return null;\n }\n // Try JSON parse so non-string secrets round-trip.\n try {\n return JSON.parse(plain);\n } catch {\n return plain;\n }\n }\n return row.value ?? null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Local helpers\n// ---------------------------------------------------------------------------\n\n/** Stable stringify so the audit digest is order-independent. */\nfunction stableStringify(input: unknown): string {\n if (input === null || typeof input !== 'object') return JSON.stringify(input);\n if (Array.isArray(input)) return '[' + input.map(stableStringify).join(',') + ']';\n const obj = input as Record<string, unknown>;\n const keys = Object.keys(obj).sort();\n return '{' + keys.map((k) => JSON.stringify(k) + ':' + stableStringify(obj[k])).join(',') + '}';\n}\n\n/** Re-typed env coercer (the canonical one lives in settings-service.types). */\nfunction coerceEnvValue(raw: string, hint: unknown): unknown {\n if (typeof hint === 'boolean') return raw === 'true' || raw === '1' || raw === 'yes';\n if (typeof hint === 'number') {\n const n = Number(raw);\n return Number.isFinite(n) ? n : raw;\n }\n if (Array.isArray(hint) || (hint && typeof hint === 'object')) {\n try {\n return JSON.parse(raw);\n } catch {\n return raw;\n }\n }\n return raw;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type {\n CryptoContext,\n CryptoHandle,\n ICryptoProvider,\n} from '@objectstack/spec/contracts';\nimport { createHash, randomBytes, createCipheriv, createDecipheriv } from 'node:crypto';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\n\n/**\n * LocalCryptoProvider — the default, KMS-free `ICryptoProvider`. It is an\n * AES-256-GCM provider keyed off a single 32-byte data key, suitable for\n * single-operator / self-host deployments where a managed KMS or Vault is\n * overkill. KMS / Vault providers (per-tenant keys, automatic rotation,\n * managed custody) plug in behind the same `ICryptoProvider` seam.\n *\n * Key resolution (first match wins):\n *\n * 1. `opts.key` — explicit Buffer (tests / embedders).\n * 2. `OS_SECRET_KEY` — canonical production master key\n * (32-byte hex or base64).\n * 3. `OS_DEV_CRYPTO_KEY` — dev convenience key (legacy\n * (legacy `OBJECTSTACK_DEV_CRYPTO_KEY`) `OBJECTSTACK_DEV_CRYPTO_KEY`\n * still honoured).\n * 4. Persisted file — `~/.objectstack/dev-crypto-key`\n * (mode 0600). In development it is\n * auto-created; in production it is\n * only *read* unless `OS_CRYPTO_AUTOKEY`\n * opts the single-node self-host case\n * into minting + persisting it too.\n * 5. Ephemeral random key — development/test only.\n *\n * ## Fail-loud guarantee (the reason this class exists)\n *\n * The original provider would *silently* fall back to a fresh per-process\n * `randomBytes(32)` key whenever no env key and no readable file were\n * available — or auto-mint a new on-disk key on every boot. In an\n * ephemeral-FS container or a multi-node cluster that means each\n * restart / each node encrypts under a different key, and **every**\n * previously-written `sys_secret` value (encrypted settings, `secret`\n * fields, datasource credentials) becomes undecryptable. The failure was\n * invisible at encrypt and boot time and only surfaced later as\n * \"all my saved passwords/API keys/DB creds fail to decrypt\".\n *\n * To turn that silent data-loss into a config error at boot, the provider\n * REFUSES to mint a key in production: when `mode === 'production'` and no\n * stable key source (env var or pre-existing key file) is available, the\n * constructor throws an actionable error instead of generating one. The one\n * exception is the `OS_CRYPTO_AUTOKEY` opt-in: a single-node self-host\n * (`os start` on a durable filesystem) may mint + *persist* a key so the\n * zero-config quickstart boots — but even then the ephemeral fallback stays\n * forbidden, so a non-writable / ephemeral FS still fails loud rather than\n * running under a key that won't survive a restart. Development and test keep\n * the ergonomic fallback so local loops and unit tests stay frictionless.\n *\n * `mode` is auto-detected from `NODE_ENV` (`production` → strict;\n * `test`/`VITEST` → ephemeral, no disk; otherwise `development`) and can be\n * overridden via `opts.mode` for embedders that manage their own lifecycle.\n *\n * ## Handle format\n * id — `sec_` + 32 hex chars (122 bits of entropy)\n * kmsKeyId — `local:v<version>`\n * alg — `aes-256-gcm`\n * version — bumps on rotateKey()\n * ciphertext— base64(iv (12) || authTag (16) || cipher)\n *\n * ## AAD binding\n * The CryptoContext (namespace + key) is folded into AES-GCM AAD so a\n * ciphertext rewrapped from a different (ns, key) tuple fails decryption —\n * guards against operators accidentally copying rows between namespaces.\n *\n * ## WebContainer (StackBlitz) note\n * `node:crypto.createCipheriv('aes-256-gcm', …)` is not implemented in\n * WebContainer. When we detect that runtime, we swap to a pure-JS AES-GCM\n * from `@noble/ciphers/aes.js`, producing the same `iv || tag || ciphertext`\n * byte layout so the handle shape is unchanged. The swap is best-effort: if\n * the dependency is missing, we fall back to the Node implementation and let\n * it throw, surfacing the configuration problem clearly.\n */\nconst SECRET_KEY_ENV = 'OS_SECRET_KEY';\nconst DEV_KEY_ENV = 'OS_DEV_CRYPTO_KEY';\nconst DEV_KEY_LEGACY_ENV = 'OBJECTSTACK_DEV_CRYPTO_KEY';\n/**\n * Opt-in that lets the strict production path mint + PERSIST a key (but never\n * fall back to an ephemeral one). Set by `os start` for the single-node\n * self-host quickstart so the documented zero-config boot works out of the\n * box, while a real cluster deploy (which must provision `OS_SECRET_KEY`)\n * leaves it unset and keeps the fail-loud guarantee. See `commands/start.ts`.\n */\nconst AUTOKEY_ENV = 'OS_CRYPTO_AUTOKEY';\n\ntype EnvMap = Record<string, string | undefined>;\n\n/** Where the provider resolved its data key from (for diagnostics). */\nexport type KeySource =\n | 'explicit'\n | 'env:OS_SECRET_KEY'\n | 'env:OS_DEV_CRYPTO_KEY'\n | 'file'\n | 'generated-file'\n | 'ephemeral';\n\nexport type CryptoMode = 'production' | 'development' | 'test';\n\nexport interface LocalCryptoProviderOptions {\n /** Explicit 32-byte data key. Overrides all env / file resolution. */\n key?: Buffer;\n /**\n * Env source. Defaults to `process.env`. Injectable so embedders and\n * tests can drive key resolution deterministically.\n */\n env?: EnvMap;\n /**\n * Deployment mode. Controls whether an ephemeral / auto-generated key is\n * tolerated. Defaults to auto-detection from `NODE_ENV`:\n * - `production` → a stable key (env var or pre-existing file) is\n * REQUIRED; construction throws otherwise (fail loud).\n * - `development` → persists an auto-generated key to disk so restarts\n * reuse it; falls back to an ephemeral key (loud warning) if disk is\n * unwritable.\n * - `test` → never touches disk; uses an ephemeral key silently.\n */\n mode?: CryptoMode;\n}\n\nconst processEnv = (): EnvMap =>\n ((globalThis as { process?: { env?: EnvMap } }).process?.env ?? {}) as EnvMap;\n\nconst detectMode = (env: EnvMap): CryptoMode => {\n if (env.VITEST || env.NODE_ENV === 'test') return 'test';\n if (env.NODE_ENV === 'production') return 'production';\n return 'development';\n};\n\n/**\n * Per-user persistent key location. Honours `OS_HOME`\n * (legacy `OBJECTSTACK_HOME`) for projects that pin a non-default config dir.\n */\nconst keyFilePath = (env: EnvMap): string => {\n const home =\n env.OS_HOME ||\n env.OBJECTSTACK_HOME ||\n (env.HOME ? join(env.HOME, '.objectstack') : undefined) ||\n join(homedir(), '.objectstack');\n return join(home, 'dev-crypto-key');\n};\n\n/**\n * Parse an env key value (hex or base64) into a 32-byte Buffer. Returns\n * `undefined` when the value is unusable so the caller can decide whether to\n * fall through (dev) or throw (production / explicit master key).\n */\nconst parseKey = (raw: string | undefined): Buffer | undefined => {\n if (!raw) return undefined;\n const trimmed = raw.trim();\n if (!trimmed) return undefined;\n // hex: 64 chars of [0-9a-f]\n if (/^[0-9a-fA-F]{64}$/.test(trimmed)) return Buffer.from(trimmed, 'hex');\n // base64 (standard or url-safe): decode and check length\n try {\n const normalised = trimmed.replace(/-/g, '+').replace(/_/g, '/');\n const buf = Buffer.from(normalised, 'base64');\n if (buf.length === 32) return buf;\n } catch {\n /* fall through */\n }\n return undefined;\n};\n\n/** Truthy env flag: `1` / `true` / `yes` (case-insensitive). */\nconst parseBool = (raw: string | undefined): boolean => {\n const v = raw?.trim().toLowerCase();\n return v === '1' || v === 'true' || v === 'yes';\n};\n\n/** Read an existing key file (no creation). Returns `undefined` on miss / IO error. */\nconst loadExistingKey = (path: string): Buffer | undefined => {\n try {\n if (!existsSync(path)) return undefined;\n return parseKey(readFileSync(path, 'utf8').trim());\n } catch {\n return undefined;\n }\n};\n\n/**\n * Load (or generate-then-persist) the key file. Returns `undefined` on any\n * I/O error so the caller can degrade to an ephemeral key without breaking\n * boot. Only used in development.\n */\nconst loadOrCreateKey = (path: string): { key: Buffer; generated: boolean } | undefined => {\n try {\n const existing = loadExistingKey(path);\n if (existing) return { key: existing, generated: false };\n const key = randomBytes(32);\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, key.toString('base64'), { mode: 0o600 });\n return { key, generated: true };\n } catch {\n return undefined;\n }\n};\n\nconst INVALID_KEY_MSG = (name: string): string =>\n `[LocalCryptoProvider] ${name} is set but is not a 32-byte key (expected 64 hex chars or base64 of 32 bytes). ` +\n `Generate one with \\`openssl rand -hex 32\\`.`;\n\nconst MISSING_PROD_KEY_MSG = (path: string): string =>\n `[LocalCryptoProvider] Refusing to start in production without a stable encryption key.\\n` +\n ` No ${SECRET_KEY_ENV} (or ${DEV_KEY_ENV}) is set and no persisted key file was found at:\\n` +\n ` ${path}\\n` +\n ` Minting a key here would make every sys_secret value (encrypted settings, secret\\n` +\n ` fields, datasource credentials) undecryptable after the next restart or on another node.\\n` +\n ` Fix: generate a 32-byte key and set it in the environment (identical across every\\n` +\n ` restart and every node), e.g.\\n` +\n ` ${SECRET_KEY_ENV}=$(openssl rand -hex 32)`;\n\ninterface ResolvedKey {\n key: Buffer;\n source: KeySource;\n}\n\nconst warn = (msg: string): void => {\n try {\n (globalThis as { console?: { warn?: (m: string) => void } }).console?.warn?.(msg);\n } catch {\n /* exotic runtime without console — ignore */\n }\n};\n\nconst legacyDeprecationWarned = { value: false };\n\nfunction resolveDataKey(opts: LocalCryptoProviderOptions): ResolvedKey {\n if (opts.key) return { key: opts.key, source: 'explicit' };\n\n const env = opts.env ?? processEnv();\n const mode = opts.mode ?? detectMode(env);\n\n // 1) Canonical production master key.\n if (env[SECRET_KEY_ENV] !== undefined) {\n const parsed = parseKey(env[SECRET_KEY_ENV]);\n if (parsed) return { key: parsed, source: 'env:OS_SECRET_KEY' };\n // Present-but-invalid is an explicit operator error — never silently\n // fall through to a different key (that would be silent data divergence).\n throw new Error(INVALID_KEY_MSG(SECRET_KEY_ENV));\n }\n\n // 2) Dev convenience key (legacy alias honoured with a deprecation note).\n let devRaw = env[DEV_KEY_ENV];\n if (devRaw === undefined && env[DEV_KEY_LEGACY_ENV] !== undefined) {\n devRaw = env[DEV_KEY_LEGACY_ENV];\n if (!legacyDeprecationWarned.value) {\n legacyDeprecationWarned.value = true;\n warn(\n `[ObjectStack] Env var \\`${DEV_KEY_LEGACY_ENV}\\` is deprecated; rename it to \\`${DEV_KEY_ENV}\\`.`,\n );\n }\n }\n if (devRaw !== undefined) {\n const parsed = parseKey(devRaw);\n if (parsed) return { key: parsed, source: 'env:OS_DEV_CRYPTO_KEY' };\n if (mode === 'production') throw new Error(INVALID_KEY_MSG(DEV_KEY_ENV));\n warn(`${INVALID_KEY_MSG(DEV_KEY_ENV)} Ignoring and generating a local key.`);\n }\n\n // 3) No usable env key — behaviour depends on mode.\n if (mode === 'test') {\n // Tests never touch disk; an ephemeral key round-trips within the process.\n return { key: randomBytes(32), source: 'ephemeral' };\n }\n\n const path = keyFilePath(env);\n\n if (mode === 'production') {\n // Honour a pre-existing, operator-provisioned key file first.\n const existing = loadExistingKey(path);\n if (existing) {\n warn(\n `[LocalCryptoProvider] No ${SECRET_KEY_ENV} set — using the persisted key at ${path}. ` +\n `For containers / multi-node, prefer setting ${SECRET_KEY_ENV} so every node shares one key.`,\n );\n return { key: existing, source: 'file' };\n }\n\n // Single-node self-host opt-in (`os start` on a durable filesystem): mint\n // a key AND persist it so the zero-config quickstart boots. We still\n // REFUSE the ephemeral fallback below — if the key cannot be written\n // (read-only / ephemeral FS), running anyway would silently lose every\n // sys_secret on the next restart, the exact footgun this guard prevents.\n // Multi-node deploys must NOT opt in (each node would mint a divergent\n // key); `os start` only sets the flag when no cluster driver is set.\n if (parseBool(env[AUTOKEY_ENV])) {\n const persisted = loadOrCreateKey(path);\n if (persisted) {\n if (persisted.generated) {\n warn(\n `[LocalCryptoProvider] No ${SECRET_KEY_ENV} set — minted a new AES-256-GCM key and ` +\n `persisted it to ${path} (mode 0600). Restarts on this host reuse it automatically. ` +\n `For containers, CI, or multi-node, set ${SECRET_KEY_ENV} so every node shares one key.`,\n );\n }\n return { key: persisted.key, source: persisted.generated ? 'generated-file' : 'file' };\n }\n // Persist failed → fall through to the hard error. Never run ephemeral\n // in production, even with the opt-in.\n }\n\n throw new Error(MISSING_PROD_KEY_MSG(path));\n }\n\n // development: persist an auto-generated key so restarts reuse it.\n const persisted = loadOrCreateKey(path);\n if (persisted) {\n if (persisted.generated) {\n warn(\n `[LocalCryptoProvider] No ${SECRET_KEY_ENV}/${DEV_KEY_ENV} set — generated a new AES-256-GCM key ` +\n `and persisted it to ${path} (mode 0600). Restarts on this host reuse it automatically. ` +\n `For containers, CI, or multi-node, set ${SECRET_KEY_ENV} explicitly so the key survives.`,\n );\n }\n return { key: persisted.key, source: persisted.generated ? 'generated-file' : 'file' };\n }\n\n // Last-resort ephemeral key (e.g. $HOME unwritable). Loud warning: this is\n // the dangerous tier — secrets will NOT survive a restart.\n const key = randomBytes(32);\n warn(\n `[LocalCryptoProvider] No ${SECRET_KEY_ENV} set and could not persist a fallback key at ${path} — ` +\n `generated an EPHEMERAL key. Existing encrypted settings/secrets will fail to decrypt after restart. ` +\n `Set ${SECRET_KEY_ENV} to a stable 32-byte key:\\n ${SECRET_KEY_ENV}=${key.toString('base64')}`,\n );\n return { key, source: 'ephemeral' };\n}\n\nconst isWebContainerRuntime = (): boolean => {\n const g = globalThis as any;\n return (\n typeof g !== 'undefined' &&\n (Boolean(g.process?.versions?.webcontainer) ||\n Boolean(g.process?.env?.SHELL?.includes?.('jsh')) ||\n Boolean(g.process?.env?.STACKBLITZ))\n );\n};\n\ntype GcmFactory = (key: Uint8Array, nonce: Uint8Array, aad?: Uint8Array) => {\n encrypt: (plain: Uint8Array) => Uint8Array;\n decrypt: (cipher: Uint8Array) => Uint8Array;\n};\n\nlet nobleGcmPromise: Promise<GcmFactory | undefined> | undefined;\nconst loadNobleGcm = (): Promise<GcmFactory | undefined> => {\n if (!nobleGcmPromise) {\n nobleGcmPromise = (async () => {\n try {\n const mod = await import('@noble/ciphers/aes.js');\n return mod.gcm as unknown as GcmFactory;\n } catch (err: any) {\n warn(\n `[LocalCryptoProvider] WebContainer detected but @noble/ciphers not installed: ${err?.message ?? err}. Falling back to node:crypto (will throw).`,\n );\n return undefined;\n }\n })();\n }\n return nobleGcmPromise;\n};\n\nexport class LocalCryptoProvider implements ICryptoProvider {\n private readonly key: Buffer;\n private readonly useNoble: boolean;\n /** Where the active data key came from. Exposed for diagnostics/tests. */\n readonly keySource: KeySource;\n\n constructor(opts: LocalCryptoProviderOptions = {}) {\n const resolved = resolveDataKey(opts);\n this.key = resolved.key;\n this.keySource = resolved.source;\n this.useNoble = isWebContainerRuntime();\n }\n\n async encrypt(plain: string, ctx: CryptoContext): Promise<CryptoHandle> {\n const iv = randomBytes(12);\n const aad = Buffer.from(this.aadOf(ctx), 'utf8');\n const plainBytes = Buffer.from(plain, 'utf8');\n\n let blob: string;\n if (this.useNoble) {\n const gcm = await loadNobleGcm();\n if (gcm) {\n const cipher = gcm(this.key, iv, aad);\n const ctWithTag = cipher.encrypt(plainBytes); // ciphertext || tag(16)\n const ct = ctWithTag.subarray(0, ctWithTag.length - 16);\n const tag = ctWithTag.subarray(ctWithTag.length - 16);\n blob = Buffer.concat([iv, Buffer.from(tag), Buffer.from(ct)]).toString('base64');\n } else {\n blob = this.encryptNode(plainBytes, iv, aad);\n }\n } else {\n blob = this.encryptNode(plainBytes, iv, aad);\n }\n\n return {\n id: 'sec_' + randomBytes(16).toString('hex'),\n kmsKeyId: 'local:v1',\n alg: 'aes-256-gcm',\n version: 1,\n ciphertext: blob,\n };\n }\n\n async decrypt(handle: CryptoHandle, ctx: CryptoContext): Promise<string> {\n const buf = Buffer.from(handle.ciphertext, 'base64');\n const iv = buf.subarray(0, 12);\n const tag = buf.subarray(12, 28);\n const data = buf.subarray(28);\n const aad = Buffer.from(this.aadOf(ctx), 'utf8');\n\n if (this.useNoble) {\n const gcm = await loadNobleGcm();\n if (gcm) {\n const cipher = gcm(this.key, iv, aad);\n const ctWithTag = Buffer.concat([data, tag]); // noble expects ciphertext || tag\n const out = cipher.decrypt(ctWithTag);\n return Buffer.from(out).toString('utf8');\n }\n }\n const decipher = createDecipheriv('aes-256-gcm', this.key, iv);\n decipher.setAAD(aad);\n decipher.setAuthTag(tag);\n return Buffer.concat([decipher.update(data), decipher.final()]).toString('utf8');\n }\n\n async rotateKey(handle: CryptoHandle, ctx: CryptoContext): Promise<CryptoHandle> {\n const plain = await this.decrypt(handle, ctx);\n const next = await this.encrypt(plain, ctx);\n return {\n ...next,\n id: handle.id,\n kmsKeyId: `local:v${handle.version + 1}`,\n version: handle.version + 1,\n };\n }\n\n digest(plain: string): string {\n return 'sha256:' + createHash('sha256').update(plain, 'utf8').digest('hex');\n }\n\n private encryptNode(plainBytes: Buffer, iv: Buffer, aad: Buffer): string {\n const cipher = createCipheriv('aes-256-gcm', this.key, iv);\n cipher.setAAD(aad);\n const enc = Buffer.concat([cipher.update(plainBytes), cipher.final()]);\n const tag = cipher.getAuthTag();\n return Buffer.concat([iv, tag, enc]).toString('base64');\n }\n\n private aadOf(ctx: CryptoContext): string {\n // Bind ciphertext to (namespace,key) so a row cannot be moved across\n // specifiers. Tenant binding is intentionally omitted because the\n // handle is dereferenced from a `sys_setting` row already scoped to\n // its tenant — adding tenant here would force the decrypt path to\n // re-read that scope.\n return [ctx.namespace, ctx.key].join('|');\n }\n}\n\n/**\n * @deprecated Renamed to {@link LocalCryptoProvider}. The old name implied an\n * \"in-memory / ephemeral\" key when the provider in fact persists its key\n * (env var or on-disk file). Kept as an alias for backward compatibility.\n */\nexport const InMemoryCryptoProvider = LocalCryptoProvider;\n/** @deprecated Use {@link LocalCryptoProviderOptions}. */\nexport type InMemoryCryptoProviderOptions = LocalCryptoProviderOptions;\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * REST surface for the SettingsService — see ADR-0007 §REST.\n *\n * GET /api/settings → visible manifests\n * GET /api/settings/:namespace → { manifest, values }\n * PUT /api/settings/:namespace → batch upsert\n * POST /api/settings/:namespace/:actionId → invoke declared action\n *\n * The route layer is a thin wrapper that maps thrown service errors\n * into proper HTTP status codes; all business logic lives in\n * `SettingsService`.\n */\n\nimport type { IHttpServer, IHttpRequest, IHttpResponse, RouteHandler } from '@objectstack/spec/contracts';\nimport { SettingsService } from './settings-service.js';\nimport {\n SettingsLockedError,\n SettingsValidationError,\n UnknownKeyError,\n UnknownNamespaceError,\n type SettingsContext,\n} from './settings-service.types.js';\n\nexport interface SettingsRoutesOptions {\n /** Base path. Default `/api/settings`. */\n basePath?: string;\n /**\n * Extract caller identity from the request. The default reads\n * `x-user-id` / `x-tenant-id` headers and parses\n * `x-permissions` as a comma-separated list — fine for dev and\n * straightforward to override in production wiring.\n */\n contextFromRequest?: (req: IHttpRequest) => SettingsContext;\n}\n\nconst defaultContext = (req: IHttpRequest): SettingsContext => {\n const header = (name: string): string | undefined => {\n const v = req.headers?.[name];\n return Array.isArray(v) ? v[0] : v;\n };\n const perms = header('x-permissions');\n return {\n userId: header('x-user-id'),\n tenantId: header('x-tenant-id'),\n permissions: perms ? perms.split(',').map((s) => s.trim()).filter(Boolean) : undefined,\n requestId: header('x-request-id'),\n };\n};\n\nfunction sendError(res: IHttpResponse, status: number, code: string, message: string, extra?: Record<string, unknown>) {\n res.status(status).json({ error: { code, message, ...extra } });\n}\n\nexport function registerSettingsRoutes(\n http: IHttpServer,\n service: SettingsService,\n opts: SettingsRoutesOptions = {},\n): void {\n const base = opts.basePath ?? '/api/settings';\n const ctxOf = opts.contextFromRequest ?? defaultContext;\n\n http.get(base, (async (req, res) => {\n try {\n const ctx = ctxOf(req);\n const manifests = service.listManifests(ctx);\n await res.json({ manifests });\n } catch (err: any) {\n sendError(res, 500, 'INTERNAL', err?.message ?? 'Failed to list manifests');\n }\n }) satisfies RouteHandler);\n\n http.get(`${base}/:namespace`, (async (req, res) => {\n const ns = req.params.namespace;\n try {\n const ctx = ctxOf(req);\n const payload = await service.getNamespace(ns, ctx);\n await res.json(payload);\n } catch (err: any) {\n if (err instanceof UnknownNamespaceError) {\n sendError(res, 404, 'UNKNOWN_NAMESPACE', err.message);\n } else {\n sendError(res, 500, 'INTERNAL', err?.message ?? 'Failed to read namespace');\n }\n }\n }) satisfies RouteHandler);\n\n http.put(`${base}/:namespace`, (async (req, res) => {\n const ns = req.params.namespace;\n let body = (req.body ?? {}) as Record<string, unknown>;\n // DX symmetry: GET returns `{ values: { key: { value, source, … } } }`.\n // Accept that same envelope on PUT (sole top-level `values` object) so a\n // caller can write back exactly what it read instead of tripping a\n // confusing UNKNOWN_KEY('values'). Per-key, unwrap the read-shape\n // `{ value, … }` wrapper to the bare value; flat `{ key: value }` bodies\n // (and a manifest that genuinely declares a `values` key alongside others)\n // are untouched.\n if (\n Object.keys(body).length === 1 &&\n body.values && typeof body.values === 'object' && !Array.isArray(body.values)\n ) {\n const inner = body.values as Record<string, unknown>;\n body = Object.fromEntries(\n Object.entries(inner).map(([k, v]) =>\n v && typeof v === 'object' && !Array.isArray(v) && 'value' in (v as object)\n ? [k, (v as { value: unknown }).value]\n : [k, v],\n ),\n );\n }\n try {\n const ctx = ctxOf(req);\n const result = await service.setMany(ns, body, ctx);\n await res.json({ values: result });\n } catch (err: any) {\n if (err instanceof SettingsLockedError) {\n sendError(res, 409, 'SETTINGS_LOCKED', err.message, {\n namespace: err.namespace,\n key: err.key,\n reason: err.reason,\n });\n } else if (err instanceof UnknownNamespaceError) {\n sendError(res, 404, 'UNKNOWN_NAMESPACE', err.message);\n } else if (err instanceof UnknownKeyError) {\n sendError(res, 400, 'UNKNOWN_KEY', err.message, { namespace: err.namespace, key: err.key });\n } else if (err instanceof SettingsValidationError) {\n sendError(res, 400, 'SETTINGS_VALIDATION', err.message, {\n namespace: err.namespace,\n fields: err.fields,\n });\n } else {\n sendError(res, 500, 'INTERNAL', err?.message ?? 'Failed to write namespace');\n }\n }\n }) satisfies RouteHandler);\n\n http.post(`${base}/:namespace/:actionId`, (async (req, res) => {\n const { namespace, actionId } = req.params;\n try {\n const ctx = ctxOf(req);\n const result = await service.runAction(namespace, actionId, req.body, ctx);\n const status = result.ok ? 200 : 400;\n await res.status(status).json(result);\n } catch (err: any) {\n if (err instanceof UnknownNamespaceError) {\n sendError(res, 404, 'UNKNOWN_NAMESPACE', err.message);\n } else {\n sendError(res, 500, 'INTERNAL', err?.message ?? 'Action failed');\n }\n }\n }) satisfies RouteHandler);\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { SysSetting, SysSecret, SysSettingAudit } from '@objectstack/platform-objects/system';\n\nexport const SETTINGS_PLUGIN_ID = 'com.objectstack.service.settings';\nexport const SETTINGS_PLUGIN_VERSION = '0.1.0';\n\n/** Objects owned by service-settings. Currently just the K/V store. */\nexport const settingsObjects: any[] = [SysSetting, SysSecret, SysSettingAudit];\n\n/** Manifest header shared by compile-time config and runtime registration. */\nexport const settingsPluginManifestHeader = {\n id: SETTINGS_PLUGIN_ID,\n namespace: 'sys',\n version: SETTINGS_PLUGIN_VERSION,\n type: 'plugin' as const,\n scope: 'system' as const,\n name: 'Settings Service',\n description:\n 'Generic settings registry + K/V resolver with OS_* env > Tenant > User > Default precedence. ADR-0007.',\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { SettingsManifest } from '@objectstack/spec/system';\n\n// Open-source auth settings intentionally stay small: platform-wide auth\n// policy toggles plus the baseline Google social-login provider.\nconst manifest = {\n namespace: 'auth',\n version: 1,\n label: 'Authentication',\n icon: 'LockKeyhole',\n description: 'Sign-in, registration, and built-in auth feature controls.',\n scope: 'global',\n readPermission: 'manage_platform_settings',\n writePermission: 'manage_platform_settings',\n category: 'Security',\n order: 15,\n specifiers: [\n {\n type: 'group',\n id: 'email_password',\n label: 'Email and password',\n required: false,\n description: 'Control local email/password sign-in and self-service registration.',\n },\n {\n type: 'toggle',\n key: 'email_password_enabled',\n label: 'Enable email/password login',\n required: false,\n default: true,\n },\n {\n type: 'toggle',\n key: 'signup_enabled',\n label: 'Allow self-service registration',\n required: false,\n default: true,\n visible: \"${data.email_password_enabled !== false}\",\n },\n {\n type: 'toggle',\n key: 'require_email_verification',\n label: 'Require email verification',\n required: false,\n default: false,\n visible: \"${data.email_password_enabled !== false}\",\n },\n\n {\n type: 'group',\n id: 'password_policy',\n label: 'Password policy',\n required: false,\n description: 'Length bounds enforced by the auth provider on sign-up and password reset.',\n },\n {\n type: 'number',\n key: 'password_min_length',\n label: 'Minimum password length',\n required: false,\n default: 8,\n min: 6,\n max: 64,\n visible: \"${data.email_password_enabled !== false}\",\n },\n {\n type: 'number',\n key: 'password_max_length',\n label: 'Maximum password length',\n required: false,\n default: 128,\n min: 16,\n max: 256,\n description: 'Upper bound guards against denial-of-service via very long password hashing.',\n visible: \"${data.email_password_enabled !== false}\",\n },\n {\n type: 'toggle',\n key: 'password_reject_breached',\n label: 'Reject breached passwords',\n required: false,\n default: false,\n description:\n 'Block passwords found in public breach corpora via Have I Been Pwned (k-anonymity range check; the password is never sent in full).',\n visible: \"${data.email_password_enabled !== false}\",\n },\n {\n type: 'toggle',\n key: 'password_require_complexity',\n label: 'Require complex passwords',\n required: false,\n default: false,\n description:\n 'Require passwords to mix character classes (uppercase, lowercase, digits, symbols) on sign-up and password change/reset.',\n visible: \"${data.email_password_enabled !== false}\",\n },\n {\n type: 'number',\n key: 'password_min_classes',\n label: 'Minimum character classes',\n required: false,\n default: 3,\n min: 1,\n max: 4,\n description: 'How many of the four classes (upper / lower / digit / symbol) a password must include.',\n visible: \"${data.email_password_enabled !== false && data.password_require_complexity === true}\",\n },\n {\n type: 'number',\n key: 'password_history_count',\n label: 'Password history (no reuse)',\n required: false,\n default: 0,\n min: 0,\n max: 24,\n description: 'Block reusing this many previous passwords on change/reset. 0 disables the check.',\n visible: \"${data.email_password_enabled !== false}\",\n },\n {\n type: 'number',\n key: 'password_expiry_days',\n label: 'Password expiry (days)',\n required: false,\n default: 0,\n min: 0,\n max: 3650,\n description: 'Force a password change after this many days. 0 disables expiry. While expired, the user is blocked from data until they change their password.',\n visible: \"${data.email_password_enabled !== false}\",\n },\n\n {\n type: 'group',\n id: 'anti_abuse',\n label: 'Anti-abuse',\n required: false,\n description:\n 'Brute-force protection: per-identity account lockout and per-IP rate limiting on auth endpoints.',\n },\n {\n type: 'number',\n key: 'lockout_threshold',\n label: 'Account lockout threshold',\n required: false,\n default: 0,\n min: 0,\n max: 20,\n description:\n 'Lock an account after this many consecutive failed sign-ins. 0 disables lockout. While locked, sign-in is rejected even with the correct password.',\n visible: \"${data.email_password_enabled !== false}\",\n },\n {\n type: 'number',\n key: 'lockout_duration_minutes',\n label: 'Lockout duration (minutes)',\n required: false,\n default: 15,\n min: 1,\n max: 1440,\n description: 'How long an account stays locked once the threshold is crossed.',\n visible: \"${data.email_password_enabled !== false && data.lockout_threshold > 0}\",\n },\n {\n type: 'number',\n key: 'rate_limit_max',\n label: 'Auth rate-limit: max requests',\n required: false,\n default: 10,\n min: 1,\n max: 1000,\n description: 'Maximum requests per IP, per window, to the sign-in / sign-up / password-reset endpoints.',\n },\n {\n type: 'number',\n key: 'rate_limit_window_seconds',\n label: 'Auth rate-limit: window (seconds)',\n required: false,\n default: 60,\n min: 1,\n max: 3600,\n description: 'Sliding window over which the request cap above is counted.',\n },\n {\n type: 'group',\n id: 'multi_factor',\n label: 'Multi-factor',\n required: false,\n description: 'Require members to protect their account with an authenticator app (TOTP).',\n },\n {\n type: 'toggle',\n key: 'mfa_required',\n label: 'Require multi-factor authentication',\n required: false,\n default: false,\n description:\n 'Users without an authenticator enrolled are blocked from data once their grace period ends. Enabling this also turns on the two-factor feature so users can enroll.',\n visible: \"${data.email_password_enabled !== false}\",\n },\n {\n type: 'number',\n key: 'mfa_grace_period_days',\n label: 'MFA grace period (days)',\n required: false,\n default: 7,\n min: 0,\n max: 90,\n description: 'How long users may defer enrollment before the hard block. 0 blocks immediately.',\n visible: \"${data.mfa_required === true}\",\n },\n {\n type: 'group',\n id: 'sessions',\n label: 'Sessions',\n required: false,\n description: 'How long a signed-in session stays valid.',\n },\n {\n type: 'number',\n key: 'session_expiry_days',\n label: 'Session lifetime (days)',\n required: false,\n default: 7,\n min: 1,\n max: 365,\n description: 'A session expires this many days after sign-in.',\n },\n {\n type: 'number',\n key: 'session_refresh_days',\n label: 'Refresh threshold (days)',\n required: false,\n default: 1,\n min: 1,\n max: 90,\n description: 'An active session is extended when it is older than this.',\n },\n {\n type: 'number',\n key: 'session_idle_timeout_minutes',\n label: 'Idle timeout (minutes)',\n required: false,\n default: 0,\n min: 0,\n max: 10080,\n description: 'Sign a user out after this many minutes of inactivity. 0 disables.',\n },\n {\n type: 'number',\n key: 'session_absolute_max_hours',\n label: 'Absolute session lifetime (hours)',\n required: false,\n default: 0,\n min: 0,\n max: 8760,\n description: 'Force re-authentication this many hours after sign-in, regardless of activity. 0 disables.',\n },\n {\n type: 'number',\n key: 'max_concurrent_sessions_per_user',\n label: 'Max concurrent sessions per user',\n required: false,\n default: 0,\n min: 0,\n max: 100,\n description: 'Cap simultaneous signed-in sessions per user; the oldest are signed out past the cap. 0 = unlimited.',\n },\n\n {\n type: 'group',\n id: 'network',\n label: 'Network',\n required: false,\n description: 'Restrict where users can authenticate from.',\n },\n {\n type: 'textarea',\n key: 'allowed_ip_ranges',\n label: 'Allowed IP ranges',\n required: false,\n description:\n 'CIDR ranges or exact IPs (one per line, or comma-separated), e.g. 203.0.113.0/24. When set, sign-in from outside these ranges is rejected. Empty = no restriction. Requires a trusted proxy to set X-Forwarded-For.',\n },\n {\n type: 'group',\n id: 'social',\n label: 'Social sign-in',\n required: false,\n description:\n 'Configure the built-in Google sign-in provider. Deployment env vars still win.',\n },\n {\n type: 'toggle',\n key: 'google_enabled',\n label: 'Enable Google login',\n required: false,\n default: true,\n description:\n 'Requires a Google OAuth client ID and secret from Google Cloud Console.',\n },\n {\n type: 'text',\n key: 'google_client_id',\n label: 'Google client ID',\n required: true,\n description:\n 'OAuth client ID from Google Cloud Console. GOOGLE_CLIENT_ID can also be set on the server.',\n visible: \"${data.google_enabled !== false}\",\n },\n {\n type: 'password',\n key: 'google_client_secret',\n label: 'Google client secret',\n required: true,\n encrypted: true,\n description:\n 'Stored encrypted at rest. GOOGLE_CLIENT_SECRET can also be set on the server.',\n visible: \"${data.google_enabled !== false}\",\n },\n\n ],\n};\n\n/** Authentication - sign-in, registration, and built-in auth controls. */\nexport const authSettingsManifest = manifest as unknown as SettingsManifest;\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { SettingsManifest } from '@objectstack/spec/system';\nimport type { SettingsActionHandler } from '../settings-service.types.js';\n\n// Visibility expressions are written as inline strings here for\n// readability. The spec's ExpressionInputSchema accepts a bare string\n// and normalises it at parse time, but the inferred TypeScript output\n// type expects `{ dialect, source }` objects. Build the manifest as\n// `unknown` first, then cast — keeps the manifest source compact.\nconst manifest = {\n namespace: 'mail',\n version: 1,\n label: 'Mail Delivery',\n icon: 'Mail',\n description: 'SMTP and transactional email provider configuration.',\n scope: 'global',\n readPermission: 'manage_platform_settings',\n writePermission: 'manage_platform_settings',\n category: 'Communication',\n order: 10,\n specifiers: [\n { type: 'group', id: 'provider', label: 'Provider', required: false,\n description: 'Choose how this workspace sends outbound email.' },\n\n { type: 'select', key: 'provider', label: 'Provider', required: true, default: 'smtp',\n options: [\n { value: 'smtp', label: 'SMTP' },\n { value: 'sendgrid', label: 'SendGrid' },\n { value: 'ses', label: 'Amazon SES' },\n { value: 'postmark', label: 'Postmark' },\n ],\n },\n\n { type: 'group', id: 'smtp', label: 'SMTP', required: false, visible: \"${data.provider === 'smtp'}\" },\n { type: 'text', key: 'smtp_host', label: 'Host', required: true,\n description: 'Example: smtp.example.com', visible: \"${data.provider === 'smtp'}\" },\n { type: 'number', key: 'smtp_port', label: 'Port', required: false, default: 587,\n min: 1, max: 65535, visible: \"${data.provider === 'smtp'}\" },\n { type: 'toggle', key: 'smtp_secure', label: 'Use TLS', required: false, default: true,\n visible: \"${data.provider === 'smtp'}\" },\n { type: 'text', key: 'smtp_user', label: 'Username', required: false,\n visible: \"${data.provider === 'smtp'}\" },\n { type: 'password', key: 'smtp_password', label: 'Password', required: false,\n visible: \"${data.provider === 'smtp'}\" },\n\n { type: 'group', id: 'api_key', label: 'API key', required: false, visible: \"${data.provider !== 'smtp'}\" },\n { type: 'password', key: 'api_key', label: 'API key', required: true, encrypted: true,\n visible: \"${data.provider !== 'smtp'}\" },\n\n { type: 'group', id: 'from_address', label: 'From address', required: false },\n { type: 'email', key: 'from_email', label: 'From email', required: true,\n description: 'Example: no-reply@example.com' },\n { type: 'text', key: 'from_name', label: 'From name', required: false, default: 'ObjectStack' },\n\n { type: 'action_button', id: 'test', label: 'Send test email', required: false, icon: 'Send',\n handler: { kind: 'http', method: 'POST', url: '/api/settings/mail/test' } },\n ],\n};\n\n/** Mail Delivery — SMTP / API provider configuration. */\nexport const mailSettingsManifest = manifest as unknown as SettingsManifest;\n\n/** Built-in action handler stub for `mail/test`. */\nexport const mailTestActionHandler: SettingsActionHandler = async ({ values }) => {\n const provider = String(values.provider ?? 'smtp');\n const fromEmail = values.from_email as string | undefined;\n if (!fromEmail) {\n return { ok: false, severity: 'error', message: 'Configure a from address before testing.' };\n }\n if (provider === 'smtp' && !values.smtp_host) {\n return { ok: false, severity: 'error', message: 'SMTP host is required.' };\n }\n if (provider !== 'smtp' && !values.api_key) {\n return { ok: false, severity: 'error', message: 'API key is required.' };\n }\n return {\n ok: true,\n severity: 'info',\n message: `Configuration looks valid (provider=${provider}). Wire @objectstack/plugin-mail for actual delivery.`,\n };\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { SettingsManifest } from '@objectstack/spec/system';\n\n/** Branding — workspace identity (name, logo, theme). */\nexport const brandingSettingsManifest: SettingsManifest = {\n namespace: 'branding',\n version: 1,\n label: 'Branding',\n icon: 'Palette',\n description: 'Workspace name, logo, and accent colour.',\n scope: 'tenant',\n readPermission: 'setup.access',\n writePermission: 'setup.write',\n category: 'Workspace',\n order: 5,\n specifiers: [\n { type: 'group', id: 'identity', label: 'Identity', required: false },\n { type: 'text', key: 'workspace_name', label: 'Workspace name', required: true,\n default: 'ObjectStack', minLength: 1, maxLength: 60 },\n { type: 'email', key: 'support_email', label: 'Support email', required: false,\n description: 'Example: support@example.com' },\n\n { type: 'group', id: 'appearance', label: 'Appearance', required: false },\n { type: 'select', key: 'theme_mode', label: 'Default theme', required: false, default: 'system',\n options: [\n { value: 'light', label: 'Light' },\n { value: 'dark', label: 'Dark' },\n { value: 'system', label: 'Match system' },\n ],\n },\n { type: 'color', key: 'accent_color', label: 'Accent colour', required: false, default: '#6366f1' },\n { type: 'url', key: 'logo_url', label: 'Logo URL', required: false,\n description: 'Example: https://…/logo.svg' },\n ],\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { SettingsManifest } from '@objectstack/spec/system';\n\n/** Feature Flags — opt into experimental capabilities. */\nexport const featureFlagsSettingsManifest: SettingsManifest = {\n namespace: 'feature_flags',\n version: 1,\n label: 'Feature Flags',\n icon: 'FlaskConical',\n description: 'Toggle experimental and beta features for this workspace.',\n scope: 'tenant',\n readPermission: 'setup.access',\n writePermission: 'setup.write',\n category: 'Beta',\n order: 100,\n beta: true,\n specifiers: [\n { type: 'info_banner', id: 'beta_notice', label: 'Heads up', required: false,\n bannerText:\n 'Beta features may change without notice. Pin via env vars (e.g. `OS_FEATURE_FLAGS_AI_ENABLED=true`) to lock for the whole deployment.',\n bannerSeverity: 'warning' },\n\n { type: 'group', id: 'productivity', label: 'Productivity', required: false },\n { type: 'toggle', key: 'ai_enabled', label: 'AI Assistant', required: false, default: false,\n description: 'Enables the in-app AI assistant panel.' },\n { type: 'toggle', key: 'kanban_swimlanes', label: 'Kanban swimlanes', required: false, default: false },\n\n { type: 'group', id: 'collaboration', label: 'Collaboration', required: false },\n { type: 'toggle', key: 'realtime_cursors', label: 'Realtime cursors', required: false, default: false },\n { type: 'toggle', key: 'inline_comments', label: 'Inline comments', required: false, default: true },\n ],\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { SettingsManifest } from '@objectstack/spec/system';\nimport type { SettingsActionHandler } from '../settings-service.types.js';\n\n// Mirrors the shape of `mail.manifest.ts`. The actual adapter rebuild\n// + `storage/test` probe live in `@objectstack/service-storage`; this\n// manifest only declares the form + acts as a safe fallback when the\n// storage plugin is not present.\nconst manifest = {\n namespace: 'storage',\n version: 1,\n label: 'File Storage',\n icon: 'HardDrive',\n description:\n 'Backend used for attachments, exports, and user uploads. ' +\n '⚠ Switching adapter does not migrate existing files — files ' +\n 'uploaded under the previous adapter become unreachable through ' +\n 'the new one.',\n scope: 'global',\n readPermission: 'manage_platform_settings',\n writePermission: 'manage_platform_settings',\n category: 'Infrastructure',\n order: 20,\n specifiers: [\n { type: 'group', id: 'adapter', label: 'Backend', required: false,\n description: 'Choose where uploaded files are stored.' },\n { type: 'select', key: 'adapter', label: 'Adapter', required: true, default: 'local',\n options: [\n { value: 'local', label: 'Local filesystem' },\n { value: 's3', label: 'S3 / S3-compatible' },\n ],\n },\n\n { type: 'group', id: 'local', label: 'Local', required: false,\n visible: \"${data.adapter === 'local'}\" },\n { type: 'text', key: 'local_root', label: 'Root directory', required: false,\n default: './.objectstack/data/uploads',\n description: 'Filesystem path under which files are stored. Relative paths resolve from the server CWD.',\n visible: \"${data.adapter === 'local'}\" },\n\n { type: 'group', id: 's3', label: 'S3', required: false,\n visible: \"${data.adapter === 's3'}\" },\n { type: 'text', key: 's3_bucket', label: 'Bucket', required: true,\n description: 'Shared host bucket. Per-environment files are namespaced via the projects/<environmentId>/ prefix.',\n visible: \"${data.adapter === 's3'}\" },\n { type: 'text', key: 's3_region', label: 'Region', required: true,\n description: 'Example: us-east-1',\n visible: \"${data.adapter === 's3'}\" },\n { type: 'text', key: 's3_endpoint', label: 'Endpoint', required: false,\n description: 'Custom endpoint for S3-compatible providers (R2, MinIO, Wasabi). Leave blank for AWS S3.',\n visible: \"${data.adapter === 's3'}\" },\n { type: 'text', key: 's3_access_key_id', label: 'Access key ID', required: true,\n visible: \"${data.adapter === 's3'}\" },\n { type: 'password', key: 's3_secret_access_key', label: 'Secret access key',\n required: true, encrypted: true,\n visible: \"${data.adapter === 's3'}\" },\n { type: 'toggle', key: 's3_force_path_style', label: 'Force path-style URLs',\n required: false, default: false,\n description: 'Enable for MinIO and most S3-compatible providers; disable for AWS S3.',\n visible: \"${data.adapter === 's3'}\" },\n\n { type: 'group', id: 'limits', label: 'Limits', required: false },\n { type: 'number', key: 'presigned_ttl', label: 'Presigned URL TTL (seconds)',\n required: false, default: 3600, min: 60, max: 604800 },\n { type: 'number', key: 'session_ttl', label: 'Upload session TTL (seconds)',\n required: false, default: 86400, min: 300, max: 604800,\n description: 'How long a chunked-upload session stays resumable.' },\n { type: 'number', key: 'max_upload_mb', label: 'Max upload size (MB)',\n required: false, default: 100, min: 1, max: 10240 },\n\n { type: 'action_button', id: 'test', label: 'Test connection',\n required: false, icon: 'Plug',\n handler: { kind: 'http', method: 'POST', url: '/api/settings/storage/test' } },\n ],\n};\n\n/** File Storage — local FS / S3-compatible backend configuration. */\nexport const storageSettingsManifest = manifest as unknown as SettingsManifest;\n\n/**\n * Built-in fallback action handler for `storage/test`. The real\n * implementation lives in `@objectstack/service-storage` and is\n * registered by `StorageServicePlugin` on `kernel:ready` (it overrides\n * this stub via `registerAction`). This fallback only validates the\n * form so the button is still useful when the storage plugin is\n * absent (e.g. in a unit-test kernel that mounts settings only).\n */\nexport const storageTestActionHandler: SettingsActionHandler = async ({ values }) => {\n const adapter = String(values.adapter ?? 'local');\n if (adapter === 'local') {\n const root = values.local_root as string | undefined;\n if (!root) {\n return { ok: false, severity: 'error', message: 'Configure a root directory before testing.' };\n }\n return {\n ok: true,\n severity: 'info',\n message: `Local adapter configured (root=${root}). Mount @objectstack/service-storage to exercise live I/O.`,\n };\n }\n if (adapter === 's3') {\n const missing: string[] = [];\n if (!values.s3_bucket) missing.push('s3_bucket');\n if (!values.s3_region) missing.push('s3_region');\n if (!values.s3_access_key_id) missing.push('s3_access_key_id');\n if (!values.s3_secret_access_key) missing.push('s3_secret_access_key');\n if (missing.length) {\n return { ok: false, severity: 'error', message: `Missing required field${missing.length > 1 ? 's' : ''}: ${missing.join(', ')}` };\n }\n return {\n ok: true,\n severity: 'info',\n message: `S3 adapter configured (bucket=${values.s3_bucket}, region=${values.s3_region}). Mount @objectstack/service-storage to exercise live I/O.`,\n };\n }\n return { ok: false, severity: 'error', message: `Unknown adapter: ${adapter}` };\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { SettingsManifest } from '@objectstack/spec/system';\nimport type { SettingsActionHandler } from '../settings-service.types.js';\n\n// Visibility expressions are written as inline strings here for\n// readability. The spec's ExpressionInputSchema accepts a bare string\n// and normalises it at parse time, but the inferred TypeScript output\n// type expects `{ dialect, source }` objects. Build the manifest as\n// `unknown` first, then cast — keeps the manifest source compact.\n//\n// The actual LLM adapter selection still happens in\n// `@objectstack/service-ai`'s plugin (env-var driven by default).\n// This manifest gives operators a UI to inspect and override those\n// env-derived defaults without redeploying. AIServicePlugin binds to this\n// namespace once the kernel is ready; env-locked settings values use the\n// OS_AI_* convention and win over UI-stored values.\nconst manifest = {\n namespace: 'ai',\n version: 1,\n label: 'AI',\n icon: 'Sparkles',\n description:\n 'LLM provider, model, credentials, and embedder configuration used by ' +\n 'the platform AI and knowledge services. Provider SDK packages (e.g. ' +\n '@ai-sdk/openai for chat, @objectstack/embedder-openai for embeddings) ' +\n 'must be installed on the host for the chosen provider to be loadable at runtime.',\n scope: 'global',\n readPermission: 'manage_platform_settings',\n writePermission: 'manage_platform_settings',\n category: 'Infrastructure',\n order: 30,\n specifiers: [\n // ── Provider selection ────────────────────────────────────────\n { type: 'group', id: 'provider', label: 'Provider', required: false,\n description: 'Choose the LLM backend. Memory mode echoes input — useful for tests but never for production.' },\n { type: 'select', key: 'provider', label: 'Provider', required: true, default: 'memory',\n options: [\n { value: 'memory', label: 'Memory (echo — testing only)' },\n { value: 'gateway', label: 'Vercel AI Gateway' },\n { value: 'openai', label: 'OpenAI' },\n { value: 'anthropic', label: 'Anthropic' },\n { value: 'google', label: 'Google Generative AI' },\n // Below: providers expose an OpenAI-compatible Chat Completions API,\n // so they reuse the @ai-sdk/openai SDK with a preset base_url. The\n // plugin's buildAdapterFromValues maps these onto provider=\"openai\"\n // + an auto-filled openai_base_url at runtime.\n { value: 'deepseek', label: 'DeepSeek (OpenAI-compatible)' },\n { value: 'dashscope', label: '阿里通义 DashScope (OpenAI-compatible)' },\n { value: 'cloudflare', label: 'Cloudflare AI Gateway (OpenAI-compatible)' },\n { value: 'siliconflow', label: '硅基流动 SiliconFlow (OpenAI-compatible)' },\n { value: 'openrouter', label: 'OpenRouter (OpenAI-compatible)' },\n ],\n },\n\n // ── Vercel AI Gateway ─────────────────────────────────────────\n { type: 'group', id: 'gateway', label: 'Vercel AI Gateway', required: false,\n visible: \"${data.provider === 'gateway'}\",\n description: 'Multi-provider router. The model spec follows `provider/model`, e.g. `openai/gpt-4o`.' },\n { type: 'text', key: 'gateway_model', label: 'Gateway model', required: true,\n description: 'Forwarded as AI_GATEWAY_MODEL. Format: provider/model, e.g. openai/gpt-4o or anthropic/claude-sonnet-4.6.',\n pattern: '^[A-Za-z0-9_-]+\\\\/[A-Za-z0-9._:-]+$',\n visible: \"${data.provider === 'gateway'}\" },\n { type: 'password', key: 'gateway_api_key', label: 'Gateway API key',\n required: false, encrypted: true,\n description: 'Optional — required only if the gateway enforces auth.',\n visible: \"${data.provider === 'gateway'}\" },\n\n // ── OpenAI ───────────────────────────────────────────────────\n { type: 'group', id: 'openai', label: 'OpenAI', required: false,\n visible: \"${data.provider === 'openai'}\" },\n { type: 'password', key: 'openai_api_key', label: 'OpenAI API key',\n required: true, encrypted: true,\n description: 'Forwarded as OPENAI_API_KEY. Stored encrypted at rest.',\n visible: \"${data.provider === 'openai'}\" },\n { type: 'text', key: 'openai_model', label: 'Model', required: false, default: 'gpt-4o',\n description: 'Default model id. Per-agent overrides take precedence.',\n visible: \"${data.provider === 'openai'}\" },\n { type: 'text', key: 'openai_base_url', label: 'Base URL', required: false,\n description: 'Override for Azure OpenAI or self-hosted gateways. Leave blank for api.openai.com.',\n visible: \"${data.provider === 'openai'}\" },\n\n // ── Anthropic ────────────────────────────────────────────────\n { type: 'group', id: 'anthropic', label: 'Anthropic', required: false,\n visible: \"${data.provider === 'anthropic'}\" },\n { type: 'password', key: 'anthropic_api_key', label: 'Anthropic API key',\n required: true, encrypted: true,\n description: 'Forwarded as ANTHROPIC_API_KEY. Stored encrypted at rest.',\n visible: \"${data.provider === 'anthropic'}\" },\n { type: 'text', key: 'anthropic_model', label: 'Model', required: false,\n default: 'claude-sonnet-4-20250514',\n visible: \"${data.provider === 'anthropic'}\" },\n\n // ── Google Generative AI ─────────────────────────────────────\n { type: 'group', id: 'google', label: 'Google', required: false,\n visible: \"${data.provider === 'google'}\" },\n { type: 'password', key: 'google_api_key', label: 'Google API key',\n required: true, encrypted: true,\n description: 'Forwarded as GOOGLE_GENERATIVE_AI_API_KEY. Stored encrypted at rest.',\n visible: \"${data.provider === 'google'}\" },\n { type: 'text', key: 'google_model', label: 'Model', required: false,\n default: 'gemini-2.0-flash',\n visible: \"${data.provider === 'google'}\" },\n\n // ── OpenAI-compatible presets (DeepSeek / DashScope / Cloudflare / …) ──\n //\n // These providers all expose `/v1/chat/completions` in OpenAI shape, so\n // we reuse the `@ai-sdk/openai` SDK with a preset base URL. The plugin\n // normalises `provider=deepseek` (etc.) to `provider=openai` at adapter\n // construction time, injecting the right base URL and a sensible default\n // model id. Users only fill in API key + (optionally) model — the URL\n // is preset, eliminating the #1 onboarding mistake.\n { type: 'group', id: 'deepseek', label: 'DeepSeek', required: false,\n visible: \"${data.provider === 'deepseek'}\",\n description: 'OpenAI-compatible API at https://api.deepseek.com. Base URL is auto-filled.' },\n { type: 'password', key: 'deepseek_api_key', label: 'DeepSeek API key',\n required: true, encrypted: true,\n description: 'sk-... — issued at platform.deepseek.com.',\n visible: \"${data.provider === 'deepseek'}\" },\n { type: 'text', key: 'deepseek_model', label: 'Model', required: false,\n default: 'deepseek-chat',\n description: 'Examples: deepseek-chat (V3), deepseek-reasoner (R1 thinking).',\n visible: \"${data.provider === 'deepseek'}\" },\n\n { type: 'group', id: 'dashscope', label: '阿里通义 DashScope', required: false,\n visible: \"${data.provider === 'dashscope'}\",\n description: 'OpenAI-compatible endpoint at dashscope.aliyuncs.com/compatible-mode/v1. Base URL is auto-filled.' },\n { type: 'password', key: 'dashscope_api_key', label: 'DashScope API key',\n required: true, encrypted: true,\n description: 'sk-... — issued at dashscope.console.aliyun.com.',\n visible: \"${data.provider === 'dashscope'}\" },\n { type: 'text', key: 'dashscope_model', label: 'Model', required: false,\n default: 'qwen-plus',\n description: 'Examples: qwen-plus, qwen-max, qwen3-max, qwen-turbo.',\n visible: \"${data.provider === 'dashscope'}\" },\n\n { type: 'group', id: 'cloudflare', label: 'Cloudflare AI Gateway', required: false,\n visible: \"${data.provider === 'cloudflare'}\",\n description:\n 'Uses the /compat endpoint so the model id is `provider/model` (e.g. ' +\n '`openai/gpt-4o-mini`, `anthropic/claude-3-5-sonnet`, `deepseek/deepseek-chat`). ' +\n 'Note: alibaba/qwen* is NOT supported by Cloudflare /compat — use the DashScope provider for Qwen.' },\n { type: 'text', key: 'cloudflare_account_id', label: 'Cloudflare account id', required: true,\n description: 'The 32-char hex id from your Cloudflare dashboard URL.',\n visible: \"${data.provider === 'cloudflare'}\" },\n { type: 'text', key: 'cloudflare_gateway_id', label: 'Gateway id', required: false, default: 'default',\n description: 'Gateway name configured in Cloudflare → AI Gateway. Defaults to `default`.',\n visible: \"${data.provider === 'cloudflare'}\" },\n { type: 'password', key: 'cloudflare_api_key', label: 'Cloudflare AI Gateway token',\n required: true, encrypted: true,\n description: 'Issued in AI Gateway → \"API tokens\" tab (cfut_… or sk_…).',\n visible: \"${data.provider === 'cloudflare'}\" },\n { type: 'text', key: 'cloudflare_model', label: 'Model', required: false,\n default: 'openai/gpt-4o-mini',\n pattern: '^[A-Za-z0-9_-]+\\\\/[A-Za-z0-9._:@-]+$',\n description:\n 'Format: provider/model. Allowed providers (per Cloudflare /compat): anthropic, openai, groq, ' +\n 'mistral, cohere, perplexity, workers-ai, google-ai-studio, vertex, grok, deepseek, cerebras, baseten, parallel.',\n visible: \"${data.provider === 'cloudflare'}\" },\n\n { type: 'group', id: 'siliconflow', label: '硅基流动 SiliconFlow', required: false,\n visible: \"${data.provider === 'siliconflow'}\",\n description: 'OpenAI-compatible endpoint at api.siliconflow.cn/v1. Base URL is auto-filled.' },\n { type: 'password', key: 'siliconflow_api_key', label: 'SiliconFlow API key',\n required: true, encrypted: true,\n visible: \"${data.provider === 'siliconflow'}\" },\n { type: 'text', key: 'siliconflow_model', label: 'Model', required: false,\n default: 'Qwen/Qwen2.5-7B-Instruct',\n description: 'Examples: Qwen/Qwen2.5-72B-Instruct, deepseek-ai/DeepSeek-V3, meta-llama/Meta-Llama-3.1-8B-Instruct.',\n visible: \"${data.provider === 'siliconflow'}\" },\n\n { type: 'group', id: 'openrouter', label: 'OpenRouter', required: false,\n visible: \"${data.provider === 'openrouter'}\",\n description: 'Multi-provider router at openrouter.ai/api/v1. Base URL is auto-filled.' },\n { type: 'password', key: 'openrouter_api_key', label: 'OpenRouter API key',\n required: true, encrypted: true,\n description: 'sk-or-...',\n visible: \"${data.provider === 'openrouter'}\" },\n { type: 'text', key: 'openrouter_model', label: 'Model', required: false,\n default: 'openai/gpt-4o-mini',\n description: 'Format: provider/model (e.g. anthropic/claude-3.5-sonnet, deepseek/deepseek-chat).',\n visible: \"${data.provider === 'openrouter'}\" },\n\n // ── Generation defaults ──────────────────────────────────────\n { type: 'group', id: 'defaults', label: 'Generation defaults', required: false,\n description: 'Applied when an agent or chat request does not specify its own value.',\n visible: \"${data.provider !== 'memory'}\" },\n { type: 'slider', key: 'temperature', label: 'Temperature',\n required: false, default: 0.7, min: 0, max: 2, step: 0.1,\n description: '0 = deterministic, 2 = highly creative.',\n visible: \"${data.provider !== 'memory'}\" },\n { type: 'number', key: 'max_tokens', label: 'Max output tokens',\n required: false, default: 4096, min: 1, max: 1048576,\n description: 'Hard cap on tokens generated per response.',\n visible: \"${data.provider !== 'memory'}\" },\n { type: 'number', key: 'request_timeout_ms', label: 'Request timeout (ms)',\n required: false, default: 60000, min: 1000, max: 600000,\n visible: \"${data.provider !== 'memory'}\" },\n\n // ── Conversation titles ──────────────────────────────────────\n // After the first assistant turn lands, service-ai fires a one-shot\n // LLM call that asks the model to produce a ≤16-char title and\n // PATCHes it onto the conversation. Without this every row in the\n // sidebar shows \"New conversation\" + a truncated preview.\n { type: 'group', id: 'titles', label: 'Conversation titles', required: false,\n description: 'Auto-generate a short summary title for new conversations.',\n visible: \"${data.provider !== 'memory'}\" },\n { type: 'toggle', key: 'title_generation_enabled', label: 'Auto-summarize conversation titles',\n required: false, default: true,\n description:\n 'When on, the LLM is asked to produce a short title after the first assistant ' +\n 'reply. Disable to save tokens, or leave the title blank to let users name ' +\n 'conversations manually.',\n visible: \"${data.provider !== 'memory'}\" },\n { type: 'number', key: 'title_max_length', label: 'Title max length (chars)',\n required: false, default: 16, min: 8, max: 80,\n description: 'Hard cap on the generated title. Anything longer is truncated server-side.',\n visible: \"${data.provider !== 'memory' && data.title_generation_enabled !== false}\" },\n\n // ── Observability ────────────────────────────────────────────\n { type: 'group', id: 'observability', label: 'Observability', required: false },\n { type: 'toggle', key: 'trace_enabled', label: 'Record traces',\n required: false, default: true,\n description: 'Persist prompt/response traces to sys_ai_trace for debugging and replay.' },\n { type: 'toggle', key: 'log_prompts', label: 'Log full prompts',\n required: false, default: false,\n description: 'Include rendered prompts (not just metadata) in trace rows. ⚠ May leak PII — disable in regulated environments.' },\n\n // ── Probe ────────────────────────────────────────────────────\n { type: 'action_button', id: 'test', label: 'Test connection',\n required: false, icon: 'Plug',\n handler: { kind: 'http', method: 'POST', url: '/api/settings/ai/test' } },\n // Escape hatch: clears every saved row in this namespace so the\n // runtime falls back to env auto-detection (AI_GATEWAY_MODEL /\n // OPENAI_API_KEY / …). Without it, a broken saved config can only\n // be removed by editing sys_setting by hand.\n { type: 'action_button', id: 'reset', label: 'Reset to environment defaults',\n required: false, icon: 'RotateCcw',\n handler: { kind: 'http', method: 'POST', url: '/api/settings/ai/reset' } },\n\n // ════════════════════════════════════════════════════════════════\n // Embedder — text → vector provider used by knowledge / RAG.\n // Decoupled from the chat provider above so an organisation can\n // mix-and-match (e.g. OpenAI for chat + 阿里通义 for embeddings).\n //\n // The preset list mirrors @objectstack/embedder-openai's\n // OPENAI_COMPATIBLE_PRESETS so a UI dropdown maps 1:1 to a\n // runtime baseUrl. The \"none\" choice is the explicit opt-out\n // for instances that disable knowledge / RAG entirely.\n // ════════════════════════════════════════════════════════════════\n { type: 'group', id: 'embedder', label: 'Embedder', required: false,\n description:\n 'Text → vector provider used by knowledge sources and RAG. ' +\n 'Independent from the chat provider above — mix providers freely ' +\n '(e.g. OpenAI for chat + 阿里通义 for embeddings).' },\n { type: 'select', key: 'embedder_provider', label: 'Provider',\n required: false, default: 'none',\n options: [\n { value: 'none', label: 'Disabled (no embeddings)' },\n { value: 'openai', label: 'OpenAI' },\n { value: 'azure', label: 'Azure OpenAI' },\n { value: 'dashscope', label: '阿里通义 DashScope' },\n { value: 'zhipu', label: '智谱 BigModel' },\n { value: 'siliconflow', label: '硅基流动 SiliconFlow' },\n { value: 'doubao', label: '火山引擎 Doubao' },\n { value: 'minimax', label: 'MiniMax' },\n { value: 'ollama', label: 'Ollama (local)' },\n { value: 'custom', label: 'Custom (OpenAI-compatible)' },\n ],\n },\n { type: 'password', key: 'embedder_api_key', label: 'Embedder API key',\n required: false, encrypted: true,\n description: 'Bearer token sent as Authorization header. For Ollama any non-empty value works.',\n visible: \"${data.embedder_provider && data.embedder_provider !== 'none'}\" },\n { type: 'text', key: 'embedder_model', label: 'Model',\n required: false,\n description:\n 'Examples — OpenAI: text-embedding-3-small · 阿里通义: text-embedding-v3 · ' +\n '智谱: embedding-3 · 硅基流动: BAAI/bge-m3 · Ollama: bge-m3',\n visible: \"${data.embedder_provider && data.embedder_provider !== 'none'}\" },\n { type: 'text', key: 'embedder_base_url', label: 'Base URL',\n required: false,\n description:\n 'Endpoint root (without /embeddings). Auto-filled from preset; ' +\n 'override for proxies or self-hosted gateways.',\n visible: \"${data.embedder_provider === 'custom' || data.embedder_provider === 'azure'}\" },\n { type: 'number', key: 'embedder_dimensions', label: 'Dimensions',\n required: false, min: 1, max: 8192,\n description:\n 'Override output dimensionality (Matryoshka models only — OpenAI v3, 智谱 embedding-3, BGE-m3 dense). ' +\n 'Leave blank to use the model default.',\n visible: \"${data.embedder_provider && data.embedder_provider !== 'none'}\" },\n { type: 'number', key: 'embedder_batch_size', label: 'Batch size',\n required: false, default: 64, min: 1, max: 2048,\n description: 'Chunks per embed() call. Reduce if hitting provider rate / size limits.',\n visible: \"${data.embedder_provider && data.embedder_provider !== 'none'}\" },\n { type: 'action_button', id: 'test_embedder', label: 'Test embedder',\n required: false, icon: 'Plug',\n handler: { kind: 'http', method: 'POST', url: '/api/settings/ai/test_embedder' } },\n ],\n};\n\n/** AI — provider / model / credentials configuration. */\nexport const aiSettingsManifest = manifest as unknown as SettingsManifest;\n\n/**\n * Built-in fallback action handler for `ai/test`. The real\n * implementation that issues a live `chat()` round-trip lives in\n * `@objectstack/service-ai` and overrides this stub via\n * `registerAction` on `kernel:ready` (mirrors the storage pattern).\n *\n * This fallback only validates the form so the button is still useful\n * when the AI plugin is absent (e.g. in a unit-test kernel that mounts\n * settings only).\n */\nexport const aiTestActionHandler: SettingsActionHandler = async ({ values, payload }) => {\n // The Settings UI may POST the current (possibly unsaved) form state\n // either as `{ values: {...} }` (nested) or as a bare `{ key: value }`\n // map (Studio default). Prefer those over the persisted snapshot so\n // operators can validate edits before hitting \"Save\".\n const overrides = extractOverrides(payload);\n const merged: Record<string, unknown> = { ...values, ...overrides };\n const provider = String(merged.provider ?? 'memory');\n values = merged;\n if (provider === 'memory') {\n return {\n ok: true,\n severity: 'warning',\n message: 'Memory provider is an echo stub — no external call to validate. Switch to a real provider for production.',\n };\n }\n if (provider === 'gateway') {\n if (!values.gateway_model) {\n return { ok: false, severity: 'error', message: 'Gateway model is required (e.g. openai/gpt-4o).' };\n }\n return {\n ok: true,\n severity: 'info',\n message: `Vercel AI Gateway configured (model=${values.gateway_model}). Mount @objectstack/service-ai to exercise live calls.`,\n };\n }\n // Cloudflare needs more than just an API key.\n if (provider === 'cloudflare') {\n if (!values.cloudflare_account_id) {\n return { ok: false, severity: 'error', message: 'Cloudflare account id is required.' };\n }\n if (!values.cloudflare_api_key) {\n return { ok: false, severity: 'error', message: 'Cloudflare AI Gateway token is required.' };\n }\n const model = values.cloudflare_model ?? '(default openai/gpt-4o-mini)';\n return {\n ok: true,\n severity: 'info',\n message: `Cloudflare AI Gateway configured (model=${model}). Mount @objectstack/service-ai to exercise live calls.`,\n };\n }\n const keyField = `${provider}_api_key`;\n if (!values[keyField]) {\n return { ok: false, severity: 'error', message: `${provider} API key is required.` };\n }\n const modelField = `${provider}_model`;\n const model = values[modelField] ?? '(default)';\n return {\n ok: true,\n severity: 'info',\n message: `${provider} configured (model=${model}). Mount @objectstack/service-ai to exercise live calls.`,\n };\n};\n\n/**\n * Built-in fallback handler for `ai/test_embedder`. Real implementation\n * with a live `embed()` round-trip lives in `@objectstack/service-ai` or\n * `@objectstack/service-knowledge` and overrides this stub at runtime.\n *\n * This fallback validates form completeness only — no network call —\n * so the button is useful even when no embedder plugin is mounted.\n */\nexport const aiTestEmbedderActionHandler: SettingsActionHandler = async ({ values, payload }) => {\n const overrides = extractOverrides(payload);\n const merged: Record<string, unknown> = { ...values, ...overrides };\n const provider = String(merged.embedder_provider ?? 'none');\n\n if (provider === 'none') {\n return {\n ok: false,\n severity: 'warning',\n message: 'Embedder is disabled. Pick a provider to enable knowledge / RAG.',\n };\n }\n\n // For Ollama, an API key is conventionally `ollama` but not enforced.\n if (provider !== 'ollama' && !merged.embedder_api_key) {\n return {\n ok: false,\n severity: 'error',\n message: `${provider} embedder requires an API key.`,\n };\n }\n\n if ((provider === 'custom' || provider === 'azure') && !merged.embedder_base_url) {\n return {\n ok: false,\n severity: 'error',\n message: `${provider} embedder requires a Base URL.`,\n };\n }\n\n const model = merged.embedder_model ?? '(provider default)';\n return {\n ok: true,\n severity: 'info',\n message:\n `${provider} embedder configured (model=${model}). ` +\n 'Mount @objectstack/embedder-openai + a knowledge adapter to exercise live calls.',\n };\n};\n\nfunction extractOverrides(payload: unknown): Record<string, unknown> {\n if (!payload || typeof payload !== 'object') return {};\n const p = payload as Record<string, unknown>;\n if (p.values && typeof p.values === 'object' && p.values !== null) {\n return p.values as Record<string, unknown>;\n }\n return p;\n}\n","// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { SettingsManifest } from '@objectstack/spec/system';\nimport type { SettingsActionHandler } from '../settings-service.types.js';\n\n/**\n * Knowledge — RAG infrastructure: which adapter stores vectors, and\n * how big chunks are. The embedder itself is configured in the AI\n * namespace (see `ai.manifest.ts`) because it's shared between\n * knowledge sources and any future agent that needs to embed ad-hoc\n * inputs.\n *\n * Adapter list mirrors the plugin packages currently published:\n * - memory @objectstack/knowledge-memory (dev / test reference)\n * - turso @objectstack/knowledge-turso (libSQL native F32_BLOB —\n * works for cloud Turso AND\n * local file mode)\n * - ragflow @objectstack/knowledge-ragflow (external RAGFlow service)\n *\n * As with the AI manifest, the real adapter wiring happens in the\n * knowledge plugins; this manifest is the canonical settings surface\n * for \"what knowledge backend is wired\" and saves operators from\n * grepping defineStack() during onboarding / incident response.\n */\nconst manifest = {\n namespace: 'knowledge',\n version: 1,\n label: 'Knowledge',\n icon: 'BookOpen',\n description:\n 'Vector-store backend for RAG / knowledge sources. ' +\n '⚠ Switching adapter does NOT migrate existing indices — documents ' +\n 'indexed under the previous adapter become unreachable until ' +\n 're-indexed. The embedder is configured separately under AI.',\n scope: 'global',\n readPermission: 'manage_platform_settings',\n writePermission: 'manage_platform_settings',\n category: 'Infrastructure',\n order: 35,\n specifiers: [\n // ── Adapter selection ─────────────────────────────────────────\n { type: 'group', id: 'adapter', label: 'Backend', required: false,\n description: 'Choose where document chunks and their vectors are stored.' },\n { type: 'select', key: 'adapter', label: 'Adapter', required: true, default: 'memory',\n options: [\n { value: 'memory', label: 'In-memory (dev / test only)' },\n { value: 'turso', label: 'Turso / libSQL (cloud or local)' },\n { value: 'ragflow', label: 'RAGFlow (external)' },\n ],\n },\n\n // ── Turso / libSQL ────────────────────────────────────────────\n { type: 'group', id: 'turso', label: 'Turso / libSQL', required: false,\n visible: \"${data.adapter === 'turso'}\",\n description:\n 'Works against managed Turso (libsql://…), local file (file:./knowledge.db), ' +\n 'or in-memory (:memory:). For per-tenant cloud deployments, leave blank to ' +\n 'reuse the tenant\\'s primary libSQL connection.' },\n { type: 'text', key: 'turso_url', label: 'Connection URL', required: false,\n description: 'Examples: libsql://your-tenant.turso.io · file:./.objectstack/knowledge.db · :memory:',\n visible: \"${data.adapter === 'turso'}\" },\n { type: 'password', key: 'turso_auth_token', label: 'Auth token',\n required: false, encrypted: true,\n description: 'Only required for managed Turso URLs. Leave blank for local file / :memory:.',\n visible: \"${data.adapter === 'turso'}\" },\n\n // ── RAGFlow ───────────────────────────────────────────────────\n { type: 'group', id: 'ragflow', label: 'RAGFlow', required: false,\n visible: \"${data.adapter === 'ragflow'}\",\n description: 'External RAGFlow deployment. See https://ragflow.io for self-host instructions.' },\n { type: 'text', key: 'ragflow_base_url', label: 'Base URL', required: true,\n description: 'Example: http://localhost:9380',\n visible: \"${data.adapter === 'ragflow'}\" },\n { type: 'password', key: 'ragflow_api_key', label: 'API key',\n required: true, encrypted: true,\n visible: \"${data.adapter === 'ragflow'}\" },\n { type: 'text', key: 'ragflow_default_dataset', label: 'Default dataset id',\n required: false,\n description: 'Used when a KnowledgeSource does not specify its own RAGFlow dataset.',\n visible: \"${data.adapter === 'ragflow'}\" },\n\n // ── Indexing defaults ─────────────────────────────────────────\n { type: 'group', id: 'indexing', label: 'Indexing defaults', required: false,\n description: 'Per-source values on KnowledgeSource.adapterConfig take precedence.',\n visible: \"${data.adapter !== 'memory'}\" },\n { type: 'number', key: 'chunk_target', label: 'Target chunk size (chars)',\n required: false, default: 800, min: 64, max: 8192,\n description: 'Soft cap on chunk size in characters before token-aware splitting kicks in.',\n visible: \"${data.adapter !== 'memory'}\" },\n { type: 'number', key: 'chunk_overlap', label: 'Chunk overlap (chars)',\n required: false, default: 80, min: 0, max: 2048,\n description: 'Characters retained from the previous chunk so context survives the boundary.',\n visible: \"${data.adapter !== 'memory'}\" },\n { type: 'number', key: 'over_fetch', label: 'Over-fetch multiplier',\n required: false, default: 4, min: 1, max: 20,\n description: 'Internal `topK * overFetch` candidates fetched so JS-side metadata filtering still has rows to return.',\n visible: \"${data.adapter === 'turso'}\" },\n\n // ── Permissions ───────────────────────────────────────────────\n { type: 'group', id: 'permissions', label: 'Permissions', required: false },\n { type: 'toggle', key: 'enforce_rls', label: 'Enforce RLS on search',\n required: false, default: true,\n description:\n 'Re-check every hit against the caller\\'s record-level permissions via IDataEngine. ' +\n '⚠ Disabling skips the platform\\'s unique safeguard against vector-store data leakage — leave on in production.' },\n\n // ── Probe ─────────────────────────────────────────────────────\n { type: 'action_button', id: 'test', label: 'Test connection',\n required: false, icon: 'Plug',\n handler: { kind: 'http', method: 'POST', url: '/api/settings/knowledge/test' } },\n ],\n};\n\n/** Knowledge — RAG vector-store backend configuration. */\nexport const knowledgeSettingsManifest = manifest as unknown as SettingsManifest;\n\n/**\n * Built-in fallback handler for `knowledge/test`. The real probe with\n * a live `healthCheck()` round-trip lives in `@objectstack/service-knowledge`\n * and overrides this stub at runtime (mirrors the AI / storage patterns).\n *\n * This fallback only validates form completeness so the button is\n * usable when no knowledge adapter plugin is mounted.\n */\nexport const knowledgeTestActionHandler: SettingsActionHandler = async ({ values, payload }) => {\n const overrides = extractOverrides(payload);\n const merged: Record<string, unknown> = { ...values, ...overrides };\n const adapter = String(merged.adapter ?? 'memory');\n\n if (adapter === 'memory') {\n return {\n ok: true,\n severity: 'warning',\n message: 'In-memory adapter — no external service to probe. Indices are wiped on restart; do not use in production.',\n };\n }\n\n if (adapter === 'turso') {\n const url = merged.turso_url;\n if (!url) {\n return {\n ok: true,\n severity: 'info',\n message: 'No URL configured — adapter will reuse the tenant\\'s primary libSQL connection at runtime.',\n };\n }\n const u = String(url);\n if (u.startsWith('libsql://') && !merged.turso_auth_token) {\n return {\n ok: false,\n severity: 'error',\n message: 'Managed Turso URL requires an auth token.',\n };\n }\n return {\n ok: true,\n severity: 'info',\n message: `Turso adapter configured (${u}). Mount @objectstack/knowledge-turso to exercise live calls.`,\n };\n }\n\n if (adapter === 'ragflow') {\n if (!merged.ragflow_base_url) {\n return { ok: false, severity: 'error', message: 'RAGFlow requires a Base URL.' };\n }\n if (!merged.ragflow_api_key) {\n return { ok: false, severity: 'error', message: 'RAGFlow requires an API key.' };\n }\n return {\n ok: true,\n severity: 'info',\n message: `RAGFlow adapter configured (${merged.ragflow_base_url}). Mount @objectstack/knowledge-ragflow to exercise live calls.`,\n };\n }\n\n return { ok: false, severity: 'error', message: `Unknown adapter: ${adapter}` };\n};\n\nfunction extractOverrides(payload: unknown): Record<string, unknown> {\n if (!payload || typeof payload !== 'object') return {};\n const p = payload as Record<string, unknown>;\n if (p.values && typeof p.values === 'object' && p.values !== null) {\n return p.values as Record<string, unknown>;\n }\n return p;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { SettingsManifest } from '@objectstack/spec/system';\n\n/**\n * Localization — workspace-wide regional defaults (ADR-0053 Phase 2 follow-up).\n *\n * The single source of truth for the platform's reference timezone, language,\n * currency, and display formats. `resolveExecutionContext` reads `timezone`\n * and `locale` from here (cascade: platform default → global → tenant) onto\n * every `ExecutionContext`, so formulas (`today()`), analytics date bucketing,\n * and rendered `datetime` instants all resolve against the org's region.\n *\n * Scope is `tenant`: one org per physical tenant (ADR-0002) sets its regional\n * defaults; the manifest `default` of each key is the platform built-in, and a\n * `global` row (or `OS_LOCALIZATION_*` env) can pin a deployment-wide value.\n * Per-user overrides are intentionally out of scope for v1.\n */\nexport const localizationSettingsManifest: SettingsManifest = {\n namespace: 'localization',\n version: 1,\n label: 'Localization',\n icon: 'Globe',\n description: 'Default timezone, language, currency, and date/number formats.',\n scope: 'tenant',\n readPermission: 'setup.access',\n writePermission: 'setup.write',\n category: 'Workspace',\n order: 2,\n specifiers: [\n // ── Region ────────────────────────────────────────────────────────────\n { type: 'group', id: 'region', label: 'Region', required: false },\n {\n type: 'select', key: 'timezone', label: 'Default timezone', required: false, default: 'UTC',\n description: 'IANA zone used to resolve today()/daysFromNow, analytics date buckets, and rendered datetimes.',\n options: [\n { value: 'UTC', label: 'UTC' },\n { value: 'America/Los_Angeles', label: '(UTC−08/−07) Los Angeles' },\n { value: 'America/Denver', label: '(UTC−07/−06) Denver' },\n { value: 'America/Chicago', label: '(UTC−06/−05) Chicago' },\n { value: 'America/New_York', label: '(UTC−05/−04) New York' },\n { value: 'America/Sao_Paulo', label: '(UTC−03) São Paulo' },\n { value: 'Europe/London', label: '(UTC±00/+01) London' },\n { value: 'Europe/Paris', label: '(UTC+01/+02) Paris' },\n { value: 'Europe/Berlin', label: '(UTC+01/+02) Berlin' },\n { value: 'Europe/Moscow', label: '(UTC+03) Moscow' },\n { value: 'Asia/Dubai', label: '(UTC+04) Dubai' },\n { value: 'Asia/Kolkata', label: '(UTC+05:30) Kolkata' },\n { value: 'Asia/Singapore', label: '(UTC+08) Singapore' },\n { value: 'Asia/Shanghai', label: '(UTC+08) Shanghai' },\n { value: 'Asia/Tokyo', label: '(UTC+09) Tokyo' },\n { value: 'Australia/Sydney', label: '(UTC+10/+11) Sydney' },\n { value: 'Pacific/Auckland', label: '(UTC+12/+13) Auckland' },\n ],\n },\n {\n type: 'select', key: 'locale', label: 'Default language', required: false, default: 'en-US',\n description: 'BCP-47 locale for message catalogs and number/date formatting.',\n options: [\n { value: 'en-US', label: 'English (US)' },\n { value: 'zh-CN', label: '简体中文' },\n { value: 'ja-JP', label: '日本語' },\n { value: 'es-ES', label: 'Español (España)' },\n ],\n },\n {\n type: 'text', key: 'default_country', label: 'Default country', required: false, default: 'US',\n description: 'ISO 3166-1 alpha-2 code (e.g. US, GB, CN). Used for address and phone defaults.',\n pattern: '^[A-Za-z]{2}$', minLength: 2, maxLength: 2,\n },\n\n // ── Formats ───────────────────────────────────────────────────────────\n { type: 'group', id: 'formats', label: 'Formats', required: false },\n {\n type: 'select', key: 'date_format', label: 'Date format', required: false, default: 'YYYY-MM-DD',\n options: [\n { value: 'YYYY-MM-DD', label: '2026-06-17 (ISO)' },\n { value: 'MM/DD/YYYY', label: '06/17/2026 (US)' },\n { value: 'DD/MM/YYYY', label: '17/06/2026 (EU)' },\n { value: 'DD.MM.YYYY', label: '17.06.2026' },\n { value: 'DD-MMM-YYYY', label: '17-Jun-2026' },\n ],\n },\n {\n type: 'select', key: 'time_format', label: 'Time format', required: false, default: '24h',\n options: [\n { value: '24h', label: '24-hour (14:30)' },\n { value: '12h', label: '12-hour (2:30 PM)' },\n ],\n },\n {\n type: 'select', key: 'number_format', label: 'Number format', required: false, default: '1,234.56',\n description: 'Grouping and decimal separators for displayed numbers.',\n options: [\n { value: '1,234.56', label: '1,234.56 (comma / dot)' },\n { value: '1.234,56', label: '1.234,56 (dot / comma)' },\n { value: '1 234,56', label: '1 234,56 (space / comma)' },\n { value: '1,23,456.78', label: '1,23,456.78 (Indian)' },\n ],\n },\n {\n type: 'select', key: 'first_day_of_week', label: 'First day of week', required: false, default: 'monday',\n description: 'Anchors weekly analytics buckets and calendar grids.',\n options: [\n { value: 'monday', label: 'Monday (ISO)' },\n { value: 'sunday', label: 'Sunday' },\n { value: 'saturday', label: 'Saturday' },\n ],\n },\n\n // ── Finance ───────────────────────────────────────────────────────────\n { type: 'group', id: 'finance', label: 'Finance', required: false },\n {\n type: 'select', key: 'currency', label: 'Default currency', required: false, default: 'USD',\n description: 'ISO 4217 code applied when a currency field omits its own.',\n options: [\n { value: 'USD', label: 'USD — US Dollar' },\n { value: 'EUR', label: 'EUR — Euro' },\n { value: 'GBP', label: 'GBP — British Pound' },\n { value: 'JPY', label: 'JPY — Japanese Yen' },\n { value: 'CNY', label: 'CNY — Chinese Yuan' },\n { value: 'INR', label: 'INR — Indian Rupee' },\n { value: 'AUD', label: 'AUD — Australian Dollar' },\n { value: 'CAD', label: 'CAD — Canadian Dollar' },\n { value: 'BRL', label: 'BRL — Brazilian Real' },\n ],\n },\n {\n type: 'select', key: 'fiscal_year_start', label: 'Fiscal year start', required: false, default: 'january',\n description: 'First month of the fiscal year — drives \"this quarter / fiscal year\" in reports.',\n options: [\n { value: 'january', label: 'January' },\n { value: 'february', label: 'February' },\n { value: 'march', label: 'March' },\n { value: 'april', label: 'April' },\n { value: 'may', label: 'May' },\n { value: 'june', label: 'June' },\n { value: 'july', label: 'July' },\n { value: 'august', label: 'August' },\n { value: 'september', label: 'September' },\n { value: 'october', label: 'October' },\n { value: 'november', label: 'November' },\n { value: 'december', label: 'December' },\n ],\n },\n ],\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { SettingsManifest } from '@objectstack/spec/system';\n\n/**\n * Company — the workspace's legal organization identity.\n *\n * Distinct from `branding` (the public-facing workspace name / logo / theme):\n * this is the **legal entity** — registered name, address, tax IDs, and the\n * primary contact. Downstream consumers are invoices/receipts, email footers\n * (CAN-SPAM requires a physical postal address), contracts, and compliance\n * exports. Benchmarked against Salesforce \"Company Information\" and Stripe's\n * business profile.\n *\n * Scope is `tenant`: one org per physical tenant (ADR-0002).\n */\nexport const companySettingsManifest: SettingsManifest = {\n namespace: 'company',\n version: 1,\n label: 'Company',\n icon: 'Building2',\n description: 'Legal entity identity — registered name, address, tax IDs, and primary contact.',\n scope: 'tenant',\n readPermission: 'setup.access',\n writePermission: 'setup.write',\n category: 'Workspace',\n order: 3,\n specifiers: [\n // ── Identity ──────────────────────────────────────────────────────────\n { type: 'group', id: 'identity', label: 'Identity', required: false },\n {\n type: 'text', key: 'legal_name', label: 'Legal name', required: false,\n description: 'Registered legal name of the organization (may differ from the workspace name).',\n maxLength: 200,\n },\n {\n type: 'text', key: 'registration_number', label: 'Registration number', required: false,\n description: 'Company registration / incorporation number (e.g. EIN, company no.).',\n maxLength: 80,\n },\n {\n type: 'text', key: 'tax_id', label: 'Tax / VAT ID', required: false,\n description: 'Tax identifier shown on invoices (e.g. VAT, GST, ABN).',\n maxLength: 80,\n },\n\n // ── Registered address ────────────────────────────────────────────────\n { type: 'group', id: 'address', label: 'Registered address', required: false },\n { type: 'text', key: 'address_line1', label: 'Address line 1', required: false, maxLength: 200 },\n { type: 'text', key: 'address_line2', label: 'Address line 2', required: false, maxLength: 200 },\n { type: 'text', key: 'city', label: 'City', required: false, maxLength: 120 },\n { type: 'text', key: 'state', label: 'State / Province', required: false, maxLength: 120 },\n { type: 'text', key: 'postal_code', label: 'Postal code', required: false, maxLength: 32 },\n {\n type: 'text', key: 'country', label: 'Country', required: false,\n description: 'ISO 3166-1 alpha-2 code (e.g. US, GB, CN).',\n pattern: '^[A-Za-z]{2}$', minLength: 2, maxLength: 2,\n },\n\n // ── Contact ───────────────────────────────────────────────────────────\n { type: 'group', id: 'contact', label: 'Contact', required: false },\n {\n type: 'text', key: 'phone', label: 'Phone', required: false,\n description: 'Primary business phone (E.164 recommended, e.g. +1 415 555 0100).',\n maxLength: 40,\n },\n {\n type: 'url', key: 'website', label: 'Website', required: false,\n description: 'Example: https://example.com',\n },\n { type: 'text', key: 'primary_contact_name', label: 'Primary contact name', required: false, maxLength: 120 },\n {\n type: 'email', key: 'primary_contact_email', label: 'Primary contact email', required: false,\n description: 'Example: ops@example.com',\n },\n ],\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/** Reference manifests bundled with service-settings. */\nexport { authSettingsManifest } from './auth.manifest.js';\nexport { mailSettingsManifest, mailTestActionHandler } from './mail.manifest.js';\nexport { brandingSettingsManifest } from './branding.manifest.js';\nexport { featureFlagsSettingsManifest } from './feature-flags.manifest.js';\nexport { storageSettingsManifest, storageTestActionHandler } from './storage.manifest.js';\nexport {\n aiSettingsManifest,\n aiTestActionHandler,\n aiTestEmbedderActionHandler,\n} from './ai.manifest.js';\nexport { knowledgeSettingsManifest, knowledgeTestActionHandler } from './knowledge.manifest.js';\nexport { localizationSettingsManifest } from './localization.manifest.js';\nexport { companySettingsManifest } from './company.manifest.js';\n\nimport { authSettingsManifest } from './auth.manifest.js';\nimport { mailSettingsManifest } from './mail.manifest.js';\nimport { brandingSettingsManifest } from './branding.manifest.js';\nimport { featureFlagsSettingsManifest } from './feature-flags.manifest.js';\nimport { storageSettingsManifest } from './storage.manifest.js';\nimport { aiSettingsManifest } from './ai.manifest.js';\nimport { knowledgeSettingsManifest } from './knowledge.manifest.js';\nimport { localizationSettingsManifest } from './localization.manifest.js';\nimport { companySettingsManifest } from './company.manifest.js';\n\n/** Convenience aggregate — pass to `SettingsServicePlugin({ manifests })`. */\nexport const builtinSettingsManifests = [\n brandingSettingsManifest,\n companySettingsManifest,\n localizationSettingsManifest,\n authSettingsManifest,\n mailSettingsManifest,\n storageSettingsManifest,\n aiSettingsManifest,\n knowledgeSettingsManifest,\n featureFlagsSettingsManifest,\n];\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { TranslationData } from '@objectstack/spec/system';\n\n/**\n * English (en) — built-in settings manifest translations.\n *\n * Mirrors literals in `manifests/{mail,branding,feature-flags,storage}.manifest.ts`.\n * Keeping them explicit here lets the resolver chain (locale → fallback → literal)\n * always have at least an English entry to fall back to.\n */\nexport const en: TranslationData = {\n settingsCommon: {\n sourceLabels: {\n env: 'Env',\n global: 'Global',\n tenant: 'Tenant',\n user: 'User',\n default: 'Default',\n },\n },\n settings: {\n mail: {\n title: 'Mail Delivery',\n description: 'SMTP and transactional email provider configuration.',\n groups: {\n provider: { title: 'Provider', description: 'Choose how this workspace sends outbound email.' },\n smtp: { title: 'SMTP' },\n api_key: { title: 'API key' },\n from_address: { title: 'From address' },\n },\n keys: {\n provider: {\n label: 'Provider',\n options: {\n smtp: 'SMTP',\n sendgrid: 'SendGrid',\n ses: 'Amazon SES',\n postmark: 'Postmark',\n },\n },\n smtp_host: { label: 'Host', help: 'Example: smtp.example.com' },\n smtp_port: { label: 'Port' },\n smtp_secure: { label: 'Use TLS' },\n smtp_user: { label: 'Username' },\n smtp_password: { label: 'Password' },\n api_key: { label: 'API key' },\n from_email: { label: 'From email', help: 'Example: no-reply@example.com' },\n from_name: { label: 'From name' },\n },\n actions: {\n test: { label: 'Send test email' },\n },\n },\n\n branding: {\n title: 'Branding',\n description: 'Workspace name, logo, and accent colour.',\n groups: {\n identity: { title: 'Identity' },\n appearance: { title: 'Appearance' },\n },\n keys: {\n workspace_name: { label: 'Workspace name' },\n support_email: { label: 'Support email', help: 'Example: support@example.com' },\n theme_mode: {\n label: 'Default theme',\n options: { light: 'Light', dark: 'Dark', system: 'Match system' },\n },\n accent_color: { label: 'Accent colour' },\n logo_url: { label: 'Logo URL', help: 'Example: https://…/logo.svg' },\n },\n },\n\n company: {\n title: 'Company',\n description: 'Legal entity identity — registered name, address, tax IDs, and primary contact.',\n groups: {\n identity: { title: 'Identity' },\n address: { title: 'Registered address' },\n contact: { title: 'Contact' },\n },\n keys: {\n legal_name: { label: 'Legal name', help: 'Registered legal name (may differ from the workspace name).' },\n registration_number: { label: 'Registration number', help: 'Company registration / incorporation number (e.g. EIN).' },\n tax_id: { label: 'Tax / VAT ID', help: 'Shown on invoices (e.g. VAT, GST, ABN).' },\n address_line1: { label: 'Address line 1' },\n address_line2: { label: 'Address line 2' },\n city: { label: 'City' },\n state: { label: 'State / Province' },\n postal_code: { label: 'Postal code' },\n country: { label: 'Country', help: 'ISO 3166-1 alpha-2 code (e.g. US, GB, CN).' },\n phone: { label: 'Phone', help: 'E.164 recommended, e.g. +1 415 555 0100.' },\n website: { label: 'Website', help: 'Example: https://example.com' },\n primary_contact_name: { label: 'Primary contact name' },\n primary_contact_email: { label: 'Primary contact email', help: 'Example: ops@example.com' },\n },\n },\n\n localization: {\n title: 'Localization',\n description: 'Default timezone, language, currency, and date/number formats.',\n groups: {\n region: { title: 'Region' },\n formats: { title: 'Formats' },\n finance: { title: 'Finance' },\n },\n keys: {\n timezone: { label: 'Default timezone', help: 'IANA zone for today()/daysFromNow, analytics date buckets, and rendered datetimes.' },\n locale: { label: 'Default language', help: 'BCP-47 locale for message catalogs and number/date formatting.' },\n default_country: { label: 'Default country', help: 'ISO 3166-1 alpha-2 code (e.g. US, GB, CN).' },\n date_format: { label: 'Date format' },\n time_format: { label: 'Time format', options: { '24h': '24-hour (14:30)', '12h': '12-hour (2:30 PM)' } },\n number_format: { label: 'Number format' },\n first_day_of_week: { label: 'First day of week', options: { monday: 'Monday (ISO)', sunday: 'Sunday', saturday: 'Saturday' } },\n currency: { label: 'Default currency' },\n fiscal_year_start: { label: 'Fiscal year start' },\n },\n },\n\n auth: {\n title: 'Authentication',\n description: 'Sign-in, registration, and built-in auth feature controls.',\n groups: {\n email_password: {\n title: 'Email and password',\n description: 'Control local email/password sign-in and self-service registration.',\n },\n password_policy: {\n title: 'Password policy',\n description: 'Length bounds enforced by the auth provider on sign-up and password reset.',\n },\n sessions: {\n title: 'Sessions',\n description: 'How long a signed-in session stays valid.',\n },\n social: {\n title: 'Social sign-in',\n description:\n 'Configure the built-in Google sign-in provider. Deployment env vars still win.',\n },\n },\n keys: {\n email_password_enabled: { label: 'Enable email/password login' },\n signup_enabled: { label: 'Allow self-service registration' },\n require_email_verification: { label: 'Require email verification' },\n password_min_length: { label: 'Minimum password length' },\n password_max_length: { label: 'Maximum password length', help: 'Guards against denial-of-service via very long password hashing.' },\n session_expiry_days: { label: 'Session lifetime (days)', help: 'A session expires this many days after sign-in.' },\n session_refresh_days: { label: 'Refresh threshold (days)', help: 'An active session is extended when it is older than this.' },\n google_enabled: {\n label: 'Enable Google login',\n help: 'Requires a Google OAuth client ID and secret from Google Cloud Console.',\n },\n google_client_id: {\n label: 'Google client ID',\n help: 'OAuth client ID from Google Cloud Console. GOOGLE_CLIENT_ID can also be set on the server.',\n },\n google_client_secret: {\n label: 'Google client secret',\n help: 'Stored encrypted at rest. GOOGLE_CLIENT_SECRET can also be set on the server.',\n },\n },\n },\n\n feature_flags: {\n title: 'Feature Flags',\n description: 'Toggle experimental and beta features for this workspace.',\n groups: {\n productivity: { title: 'Productivity' },\n collaboration: { title: 'Collaboration' },\n },\n keys: {\n ai_enabled: {\n label: 'AI Assistant',\n help: 'Enables the in-app AI assistant panel.',\n },\n kanban_swimlanes: { label: 'Kanban swimlanes' },\n realtime_cursors: { label: 'Realtime cursors' },\n inline_comments: { label: 'Inline comments' },\n },\n },\n\n storage: {\n title: 'File Storage',\n description:\n 'Backend used for attachments, exports, and user uploads. ' +\n '⚠ Switching adapter does not migrate existing files — files ' +\n 'uploaded under the previous adapter become unreachable through ' +\n 'the new one.',\n groups: {\n adapter: { title: 'Backend', description: 'Choose where uploaded files are stored.' },\n local: { title: 'Local' },\n s3: { title: 'S3' },\n limits: { title: 'Limits' },\n },\n keys: {\n adapter: {\n label: 'Adapter',\n options: { local: 'Local filesystem', s3: 'S3 / S3-compatible' },\n },\n local_root: { label: 'Root directory',\n help: 'Filesystem path under which files are stored. Relative paths resolve from the server CWD.' },\n s3_bucket: { label: 'Bucket',\n help: 'Shared host bucket. Per-environment files are namespaced via the projects/<environmentId>/ prefix.' },\n s3_region: { label: 'Region', help: 'Example: us-east-1' },\n s3_endpoint: { label: 'Endpoint',\n help: 'Custom endpoint for S3-compatible providers (R2, MinIO, Wasabi). Leave blank for AWS S3.' },\n s3_access_key_id: { label: 'Access key ID' },\n s3_secret_access_key: { label: 'Secret access key' },\n s3_force_path_style: { label: 'Force path-style URLs',\n help: 'Enable for MinIO and most S3-compatible providers; disable for AWS S3.' },\n presigned_ttl: { label: 'Presigned URL TTL (seconds)' },\n session_ttl: { label: 'Upload session TTL (seconds)',\n help: 'How long a chunked-upload session stays resumable.' },\n max_upload_mb: { label: 'Max upload size (MB)' },\n },\n actions: {\n test: { label: 'Test connection' },\n },\n },\n\n ai: {\n title: 'AI & Embedder',\n description:\n 'LLM provider, model, credentials, and embedder configuration used by ' +\n 'the platform AI and knowledge services.',\n groups: {\n provider: { title: 'Provider',\n description: 'Choose the LLM backend. Memory mode echoes input — useful for tests but never for production.' },\n gateway: { title: 'Vercel AI Gateway',\n description: 'Multi-provider router. The model spec follows `provider/model`, e.g. `openai/gpt-4o`.' },\n openai: { title: 'OpenAI' },\n anthropic: { title: 'Anthropic' },\n google: { title: 'Google' },\n defaults: { title: 'Generation defaults',\n description: 'Applied when an agent or chat request does not specify its own value.' },\n observability: { title: 'Observability' },\n embedder: { title: 'Embedder',\n description:\n 'Text → vector provider used by knowledge sources and RAG. ' +\n 'Independent from the chat provider above.' },\n },\n keys: {\n provider: {\n label: 'Provider',\n options: {\n memory: 'Memory (echo — testing only)',\n gateway: 'Vercel AI Gateway',\n openai: 'OpenAI',\n anthropic: 'Anthropic',\n google: 'Google Generative AI',\n },\n },\n gateway_model: { label: 'Gateway model',\n help: 'Forwarded as AI_GATEWAY_MODEL. Example: openai/gpt-4o' },\n gateway_api_key: { label: 'Gateway API key',\n help: 'Optional — required only if the gateway enforces auth.' },\n openai_api_key: { label: 'OpenAI API key',\n help: 'Forwarded as OPENAI_API_KEY. Stored encrypted at rest.' },\n openai_model: { label: 'Model',\n help: 'Default model id. Per-agent overrides take precedence.' },\n openai_base_url: { label: 'Base URL',\n help: 'Override for Azure OpenAI or self-hosted gateways. Leave blank for api.openai.com.' },\n anthropic_api_key: { label: 'Anthropic API key',\n help: 'Forwarded as ANTHROPIC_API_KEY. Stored encrypted at rest.' },\n anthropic_model: { label: 'Model' },\n google_api_key: { label: 'Google API key',\n help: 'Forwarded as GOOGLE_GENERATIVE_AI_API_KEY. Stored encrypted at rest.' },\n google_model: { label: 'Model' },\n temperature: { label: 'Temperature',\n help: '0 = deterministic, 2 = highly creative.' },\n max_tokens: { label: 'Max output tokens',\n help: 'Hard cap on tokens generated per response.' },\n request_timeout_ms: { label: 'Request timeout (ms)' },\n trace_enabled: { label: 'Record traces',\n help: 'Persist prompt/response traces to sys_ai_trace for debugging and replay.' },\n log_prompts: { label: 'Log full prompts',\n help: 'Include rendered prompts (not just metadata) in trace rows. ⚠ May leak PII — disable in regulated environments.' },\n embedder_provider: {\n label: 'Provider',\n options: {\n none: 'Disabled (no embeddings)',\n openai: 'OpenAI',\n azure: 'Azure OpenAI',\n dashscope: '阿里通义 DashScope',\n zhipu: '智谱 BigModel',\n siliconflow: '硅基流动 SiliconFlow',\n doubao: '火山引擎 Doubao',\n minimax: 'MiniMax',\n ollama: 'Ollama (local)',\n custom: 'Custom (OpenAI-compatible)',\n },\n },\n embedder_api_key: { label: 'Embedder API key',\n help: 'Bearer token sent as Authorization header. For Ollama any non-empty value works.' },\n embedder_model: { label: 'Model',\n help: 'Examples — OpenAI: text-embedding-3-small · 阿里通义: text-embedding-v3 · 智谱: embedding-3 · 硅基流动: BAAI/bge-m3 · Ollama: bge-m3' },\n embedder_base_url: { label: 'Base URL',\n help: 'Endpoint root (without /embeddings). Auto-filled from preset; override for proxies or self-hosted gateways.' },\n embedder_dimensions: { label: 'Dimensions',\n help: 'Override output dimensionality (Matryoshka models only). Leave blank to use the model default.' },\n embedder_batch_size: { label: 'Batch size',\n help: 'Chunks per embed() call. Reduce if hitting provider rate / size limits.' },\n },\n actions: {\n test: { label: 'Test connection' },\n test_embedder: { label: 'Test embedder' },\n },\n },\n\n knowledge: {\n title: 'Knowledge',\n description:\n 'Vector-store backend for RAG / knowledge sources. ' +\n '⚠ Switching adapter does NOT migrate existing indices.',\n groups: {\n adapter: { title: 'Backend',\n description: 'Choose where document chunks and their vectors are stored.' },\n turso: { title: 'Turso / libSQL',\n description: 'Works against managed Turso, local file, or in-memory.' },\n ragflow: { title: 'RAGFlow',\n description: 'External RAGFlow deployment. See https://ragflow.io for self-host instructions.' },\n indexing: { title: 'Indexing defaults',\n description: 'Per-source values on KnowledgeSource.adapterConfig take precedence.' },\n permissions: { title: 'Permissions' },\n },\n keys: {\n adapter: {\n label: 'Adapter',\n options: {\n memory: 'In-memory (dev / test only)',\n turso: 'Turso / libSQL (cloud or local)',\n ragflow: 'RAGFlow (external)',\n },\n },\n turso_url: { label: 'Connection URL',\n help: 'Examples: libsql://your-tenant.turso.io · file:./.objectstack/knowledge.db · :memory:' },\n turso_auth_token: { label: 'Auth token',\n help: 'Only required for managed Turso URLs.' },\n ragflow_base_url: { label: 'Base URL', help: 'Example: http://localhost:9380' },\n ragflow_api_key: { label: 'API key' },\n ragflow_default_dataset: { label: 'Default dataset id',\n help: 'Used when a KnowledgeSource does not specify its own RAGFlow dataset.' },\n chunk_target: { label: 'Target chunk size (chars)',\n help: 'Soft cap on chunk size before token-aware splitting kicks in.' },\n chunk_overlap: { label: 'Chunk overlap (chars)',\n help: 'Characters retained from the previous chunk so context survives the boundary.' },\n over_fetch: { label: 'Over-fetch multiplier',\n help: 'Internal topK × overFetch candidates fetched so JS-side metadata filtering still has rows.' },\n enforce_rls: { label: 'Enforce RLS on search',\n help: 'Re-check every hit against the caller\\'s record-level permissions. ⚠ Disabling skips the platform\\'s unique safeguard.' },\n },\n actions: {\n test: { label: 'Test connection' },\n },\n },\n },\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { TranslationData } from '@objectstack/spec/system';\n\n/**\n * 简体中文 (zh-CN) — built-in settings manifest translations.\n */\nexport const zhCN: TranslationData = {\n settingsCommon: {\n sourceLabels: {\n env: '环境变量',\n global: '全局',\n tenant: '租户',\n user: '用户',\n default: '默认',\n },\n },\n settings: {\n mail: {\n title: '邮件投递',\n description: 'SMTP 与事务性邮件服务商配置。',\n groups: {\n provider: { title: '服务商', description: '选择此工作区如何发送邮件。' },\n smtp: { title: 'SMTP' },\n api_key: { title: 'API 密钥' },\n from_address: { title: '发件地址' },\n },\n keys: {\n provider: {\n label: '服务商',\n options: {\n smtp: 'SMTP',\n sendgrid: 'SendGrid',\n ses: 'Amazon SES',\n postmark: 'Postmark',\n },\n },\n smtp_host: { label: '主机', help: '示例:smtp.example.com' },\n smtp_port: { label: '端口' },\n smtp_secure: { label: '启用 TLS' },\n smtp_user: { label: '用户名' },\n smtp_password: { label: '密码' },\n api_key: { label: 'API 密钥' },\n from_email: { label: '发件地址', help: '示例:no-reply@example.com' },\n from_name: { label: '发件人名称' },\n },\n actions: {\n test: { label: '发送测试邮件' },\n },\n },\n\n branding: {\n title: '品牌',\n description: '工作区名称、Logo 与主题色。',\n groups: {\n identity: { title: '身份' },\n appearance: { title: '外观' },\n },\n keys: {\n workspace_name: { label: '工作区名称' },\n support_email: { label: '客服邮箱', help: '示例:support@example.com' },\n theme_mode: {\n label: '默认主题',\n options: { light: '浅色', dark: '深色', system: '跟随系统' },\n },\n accent_color: { label: '主题色' },\n logo_url: { label: 'Logo 链接', help: '示例:https://…/logo.svg' },\n },\n },\n\n company: {\n title: '公司',\n description: '法律实体信息——注册名称、地址、税号及主要联系人。',\n groups: {\n identity: { title: '主体信息' },\n address: { title: '注册地址' },\n contact: { title: '联系方式' },\n },\n keys: {\n legal_name: { label: '法定名称', help: '注册的法定名称(可能与工作区名称不同)。' },\n registration_number: { label: '注册号', help: '公司注册/工商登记号(如 EIN、统一社会信用代码)。' },\n tax_id: { label: '税号 / VAT', help: '发票上显示的税务标识(如 VAT、GST、ABN)。' },\n address_line1: { label: '地址行 1' },\n address_line2: { label: '地址行 2' },\n city: { label: '城市' },\n state: { label: '省/州' },\n postal_code: { label: '邮政编码' },\n country: { label: '国家/地区', help: 'ISO 3166-1 二位代码(如 US、GB、CN)。' },\n phone: { label: '电话', help: '建议 E.164 格式,如 +86 21 5555 0100。' },\n website: { label: '网站', help: '示例:https://example.com' },\n primary_contact_name: { label: '主要联系人' },\n primary_contact_email: { label: '主要联系人邮箱', help: '示例:ops@example.com' },\n },\n },\n\n localization: {\n title: '本地化',\n description: '默认时区、语言、货币及日期/数字格式。',\n groups: {\n region: { title: '区域' },\n formats: { title: '格式' },\n finance: { title: '财务' },\n },\n keys: {\n timezone: { label: '默认时区', help: '用于 today()/daysFromNow、分析日期分桶和 datetime 渲染的 IANA 时区。' },\n locale: { label: '默认语言', help: '用于消息文案和数字/日期格式的 BCP-47 语言。' },\n default_country: { label: '默认国家/地区', help: 'ISO 3166-1 二位代码(如 US、GB、CN)。' },\n date_format: { label: '日期格式' },\n time_format: { label: '时间格式', options: { '24h': '24 小时制(14:30)', '12h': '12 小时制(2:30 PM)' } },\n number_format: { label: '数字格式', help: '用于显示数字的千分位与小数分隔符。' },\n first_day_of_week: { label: '每周起始日', help: '用作周度分析分桶与日历网格的起始基准。', options: { monday: '周一(ISO)', sunday: '周日', saturday: '周六' } },\n currency: { label: '默认货币', help: '当货币字段未指定币种时套用的 ISO 4217 代码。' },\n fiscal_year_start: { label: '财年起始月', help: '财年的起始月份——决定报表中的\"本季度/本财年\"。' },\n },\n },\n\n auth: {\n title: '认证',\n description: '登录、注册以及内置认证功能的控制项。',\n groups: {\n email_password: {\n title: '邮箱与密码',\n description: '控制本地邮箱/密码登录与自助注册。',\n },\n password_policy: {\n title: '密码策略',\n description: '由认证提供商在注册和重置密码时强制的长度限制。',\n },\n sessions: {\n title: '会话',\n description: '登录会话的有效时长。',\n },\n social: {\n title: '社交登录',\n description: '配置内置的 Google 登录提供商。部署环境变量仍优先生效。',\n },\n },\n keys: {\n email_password_enabled: { label: '启用邮箱/密码登录' },\n signup_enabled: { label: '允许自助注册' },\n require_email_verification: { label: '要求邮箱验证' },\n password_min_length: { label: '密码最小长度' },\n password_max_length: { label: '密码最大长度', help: '防止超长密码哈希导致的拒绝服务。' },\n session_expiry_days: { label: '会话有效期(天)', help: '登录后会话在此天数后过期。' },\n session_refresh_days: { label: '刷新阈值(天)', help: '活跃会话在超过此时长后自动续期。' },\n google_enabled: {\n label: '启用 Google 登录',\n help: '需要在 Google Cloud Console 中创建的 Google OAuth 客户端 ID 与密钥。',\n },\n google_client_id: {\n label: 'Google 客户端 ID',\n help: '来自 Google Cloud Console 的 OAuth 客户端 ID。也可在服务器上设置 GOOGLE_CLIENT_ID。',\n },\n google_client_secret: {\n label: 'Google 客户端密钥',\n help: '加密存储。也可在服务器上设置 GOOGLE_CLIENT_SECRET。',\n },\n },\n },\n\n feature_flags: {\n title: '功能开关',\n description: '为当前工作区开启实验性与测试功能。',\n groups: {\n productivity: { title: '生产力' },\n collaboration: { title: '协作' },\n },\n keys: {\n ai_enabled: {\n label: 'AI 助手',\n help: '启用应用内 AI 助手面板。',\n },\n kanban_swimlanes: { label: '看板泳道' },\n realtime_cursors: { label: '实时光标' },\n inline_comments: { label: '行内评论' },\n },\n },\n\n storage: {\n title: '文件存储',\n description:\n '附件、导出文件与用户上传所使用的存储后端。' +\n '⚠ 切换适配器不会迁移已有文件 —— 通过旧适配器上传的文件,在新适配器中将不可访问。',\n groups: {\n adapter: { title: '存储后端', description: '选择上传文件的存放位置。' },\n local: { title: '本地' },\n s3: { title: 'S3' },\n limits: { title: '限制' },\n },\n keys: {\n adapter: {\n label: '适配器',\n options: { local: '本地文件系统', s3: 'S3 / S3 兼容' },\n },\n local_root: { label: '根目录',\n help: '文件存放的文件系统路径。相对路径相对于服务进程的工作目录。' },\n s3_bucket: { label: 'Bucket',\n help: '共享主机 Bucket。各项目的文件通过 projects/<environmentId>/ 前缀进行隔离。' },\n s3_region: { label: '区域', help: '示例:us-east-1' },\n s3_endpoint: { label: 'Endpoint',\n help: 'S3 兼容服务(R2、MinIO、Wasabi)的自定义 Endpoint;AWS S3 请留空。' },\n s3_access_key_id: { label: 'Access Key ID' },\n s3_secret_access_key: { label: 'Secret Access Key' },\n s3_force_path_style: { label: '强制路径风格 URL',\n help: 'MinIO 与大多数 S3 兼容服务请开启;AWS S3 请关闭。' },\n presigned_ttl: { label: '预签名 URL 有效期(秒)' },\n session_ttl: { label: '分片上传会话有效期(秒)',\n help: '分片上传会话保持可续传的时长。' },\n max_upload_mb: { label: '单文件最大上传(MB)' },\n },\n actions: {\n test: { label: '测试连接' },\n },\n },\n\n ai: {\n title: 'AI 与 Embedder',\n description: '平台 AI 与知识库服务使用的 LLM 提供商、模型、凭据与向量化配置。',\n groups: {\n provider: { title: '提供商', description: '选择 LLM 后端。Memory 模式仅原样回显输入,仅用于测试,严禁用于生产。' },\n gateway: { title: 'Vercel AI Gateway', description: '多提供商路由器。模型规格遵循 `provider/model` 格式,例如 `openai/gpt-4o`。' },\n openai: { title: 'OpenAI' },\n anthropic: { title: 'Anthropic' },\n google: { title: 'Google' },\n defaults: { title: '生成默认值', description: '当 Agent 或聊天请求未指定时使用。' },\n observability: { title: '可观测性' },\n embedder: { title: 'Embedder', description: '知识库和 RAG 使用的文本→向量提供商,与上方聊天提供商相互独立。' },\n },\n keys: {\n provider: {\n label: '提供商',\n options: {\n memory: 'Memory(回显 — 仅测试)',\n gateway: 'Vercel AI Gateway',\n openai: 'OpenAI',\n anthropic: 'Anthropic',\n google: 'Google Generative AI',\n },\n },\n gateway_model: { label: 'Gateway 模型', help: '作为 AI_GATEWAY_MODEL 转发。示例:openai/gpt-4o' },\n gateway_api_key: { label: 'Gateway API Key', help: '可选 —— 仅当 Gateway 强制鉴权时需要。' },\n openai_api_key: { label: 'OpenAI API Key', help: '作为 OPENAI_API_KEY 转发,加密存储。' },\n openai_model: { label: '模型', help: '默认模型 ID。Agent 级覆盖优先生效。' },\n openai_base_url: { label: 'Base URL', help: '用于 Azure OpenAI 或自建网关。留空走 api.openai.com。' },\n anthropic_api_key: { label: 'Anthropic API Key', help: '作为 ANTHROPIC_API_KEY 转发,加密存储。' },\n anthropic_model: { label: '模型' },\n google_api_key: { label: 'Google API Key', help: '作为 GOOGLE_GENERATIVE_AI_API_KEY 转发,加密存储。' },\n google_model: { label: '模型' },\n temperature: { label: '温度', help: '0 = 确定性,2 = 高度发散。' },\n max_tokens: { label: '最大输出 tokens', help: '单次响应生成的硬上限。' },\n request_timeout_ms: { label: '请求超时(毫秒)' },\n trace_enabled: { label: '记录 Trace', help: '将 prompt/response 落入 sys_ai_trace,便于调试与回放。' },\n log_prompts: { label: '记录完整 Prompt', help: '在 trace 行中包含完整 prompt 而非仅元数据。⚠ 可能泄露 PII,合规场景请关闭。' },\n embedder_provider: {\n label: '提供商',\n options: {\n none: '禁用(不做向量化)',\n openai: 'OpenAI',\n azure: 'Azure OpenAI',\n dashscope: '阿里通义 DashScope',\n zhipu: '智谱 BigModel',\n siliconflow: '硅基流动 SiliconFlow',\n doubao: '火山引擎 Doubao',\n minimax: 'MiniMax',\n ollama: 'Ollama(本地)',\n custom: '自定义(OpenAI 兼容)',\n },\n },\n embedder_api_key: { label: 'Embedder API Key', help: '作为 Authorization Bearer 发送。Ollama 任意非空值均可。' },\n embedder_model: { label: '模型', help: '示例 — OpenAI: text-embedding-3-small · 阿里通义: text-embedding-v3 · 智谱: embedding-3 · 硅基流动: BAAI/bge-m3 · Ollama: bge-m3' },\n embedder_base_url: { label: 'Base URL', help: '端点根路径(不含 /embeddings)。预设会自动填充,可覆盖为代理或自建网关。' },\n embedder_dimensions: { label: '维度', help: '覆盖输出维度(仅 Matryoshka 模型支持)。留空使用模型默认值。' },\n embedder_batch_size: { label: '批量大小', help: '单次 embed() 调用的 chunk 数。命中速率/大小限制时调小。' },\n },\n actions: {\n test: { label: '测试连接' },\n test_embedder: { label: '测试 Embedder' },\n },\n },\n\n knowledge: {\n title: '知识库',\n description: 'RAG / 知识源使用的向量存储后端。⚠ 切换适配器不会迁移已有索引。',\n groups: {\n adapter: { title: '后端', description: '选择文档分块及其向量的存储位置。' },\n turso: { title: 'Turso / libSQL', description: '支持托管 Turso、本地文件、内存三种模式。' },\n ragflow: { title: 'RAGFlow', description: '外部 RAGFlow 部署。自部署文档见 https://ragflow.io 。' },\n indexing: { title: '索引默认值', description: 'KnowledgeSource.adapterConfig 上的逐源覆盖优先生效。' },\n permissions: { title: '权限' },\n },\n keys: {\n adapter: {\n label: '适配器',\n options: {\n memory: '内存(仅开发/测试)',\n turso: 'Turso / libSQL(云端或本地)',\n ragflow: 'RAGFlow(外部)',\n },\n },\n turso_url: { label: '连接 URL', help: '示例:libsql://your-tenant.turso.io · file:./.objectstack/knowledge.db · :memory:' },\n turso_auth_token: { label: 'Auth Token', help: '仅托管 Turso URL 需要。' },\n ragflow_base_url: { label: 'Base URL', help: '示例:http://localhost:9380' },\n ragflow_api_key: { label: 'API Key' },\n ragflow_default_dataset: { label: '默认 Dataset ID', help: 'KnowledgeSource 未指定时使用。' },\n chunk_target: { label: '目标 chunk 大小(字符)', help: '在按 token 切分之前的软上限。' },\n chunk_overlap: { label: 'Chunk 重叠(字符)', help: '保留上一个 chunk 末尾的字符,以保证跨界上下文。' },\n over_fetch: { label: '过取倍数', help: '内部按 topK × overFetch 拉取候选,以便 JS 端元数据过滤仍有行可返回。' },\n enforce_rls: { label: '搜索时强制 RLS', help: '对每条命中通过 IDataEngine 再次校验调用方的行级权限。⚠ 关闭将跳过平台对向量存储数据外泄的独有防护。' },\n },\n actions: {\n test: { label: '测试连接' },\n },\n },\n },\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { TranslationData } from '@objectstack/spec/system';\n\n/**\n * 日本語 (ja-JP) — built-in settings manifest translations.\n */\nexport const jaJP: TranslationData = {\n settingsCommon: {\n sourceLabels: {\n env: '環境変数',\n global: 'グローバル',\n tenant: 'テナント',\n user: 'ユーザー',\n default: 'デフォルト',\n },\n },\n settings: {\n mail: {\n title: 'メール配信',\n description: 'SMTP およびトランザクションメールプロバイダー設定。',\n groups: {\n provider: { title: 'プロバイダー', description: 'このワークスペースの送信方法を選択します。' },\n smtp: { title: 'SMTP' },\n api_key: { title: 'API キー' },\n from_address: { title: '差出人アドレス' },\n },\n keys: {\n provider: {\n label: 'プロバイダー',\n options: {\n smtp: 'SMTP',\n sendgrid: 'SendGrid',\n ses: 'Amazon SES',\n postmark: 'Postmark',\n },\n },\n smtp_host: { label: 'ホスト', help: '例: smtp.example.com' },\n smtp_port: { label: 'ポート' },\n smtp_secure: { label: 'TLS を使用' },\n smtp_user: { label: 'ユーザー名' },\n smtp_password: { label: 'パスワード' },\n api_key: { label: 'API キー' },\n from_email: { label: '差出人アドレス', help: '例: no-reply@example.com' },\n from_name: { label: '差出人名' },\n },\n actions: {\n test: { label: 'テストメール送信' },\n },\n },\n\n branding: {\n title: 'ブランディング',\n description: 'ワークスペース名・ロゴ・アクセントカラー。',\n groups: {\n identity: { title: 'アイデンティティ' },\n appearance: { title: '外観' },\n },\n keys: {\n workspace_name: { label: 'ワークスペース名' },\n support_email: { label: 'サポートメール', help: '例: support@example.com' },\n theme_mode: {\n label: 'デフォルトテーマ',\n options: { light: 'ライト', dark: 'ダーク', system: 'システムに従う' },\n },\n accent_color: { label: 'アクセントカラー' },\n logo_url: { label: 'ロゴ URL', help: '例: https://…/logo.svg' },\n },\n },\n\n auth: {\n title: '認証',\n description: 'サインイン、登録、組み込み認証機能の制御。',\n groups: {\n email_password: {\n title: 'メールとパスワード',\n description: 'ローカルのメール/パスワードサインインとセルフサービス登録を制御します。',\n },\n social: {\n title: 'ソーシャルサインイン',\n description:\n '組み込みの Google サインインプロバイダーを設定します。デプロイの環境変数が優先されます。',\n },\n },\n keys: {\n email_password_enabled: { label: 'メール/パスワードログインを有効化' },\n signup_enabled: { label: 'セルフサービス登録を許可' },\n require_email_verification: { label: 'メール確認を必須にする' },\n google_enabled: {\n label: 'Google ログインを有効化',\n help: 'Google Cloud Console の Google OAuth クライアント ID とシークレットが必要です。',\n },\n google_client_id: {\n label: 'Google クライアント ID',\n help: 'Google Cloud Console の OAuth クライアント ID。サーバー側で GOOGLE_CLIENT_ID を設定することもできます。',\n },\n google_client_secret: {\n label: 'Google クライアントシークレット',\n help: '保存時に暗号化されます。サーバー側で GOOGLE_CLIENT_SECRET を設定することもできます。',\n },\n },\n },\n\n feature_flags: {\n title: '機能フラグ',\n description: 'このワークスペースで実験的・ベータ機能を切替えます。',\n groups: {\n productivity: { title: '生産性' },\n collaboration: { title: 'コラボレーション' },\n },\n keys: {\n ai_enabled: {\n label: 'AI アシスタント',\n help: 'アプリ内 AI アシスタントパネルを有効化します。',\n },\n kanban_swimlanes: { label: 'カンバンのスイムレーン' },\n realtime_cursors: { label: 'リアルタイムカーソル' },\n inline_comments: { label: 'インラインコメント' },\n },\n },\n\n storage: {\n title: 'ファイルストレージ',\n description:\n '添付ファイル・エクスポート・ユーザーアップロードに使用するバックエンド。' +\n '⚠ アダプターを切替えても既存ファイルは移行されません。以前のアダプターでアップロードされたファイルは新しいアダプターからアクセスできなくなります。',\n groups: {\n adapter: { title: 'バックエンド', description: 'アップロードファイルの保存先を選択します。' },\n local: { title: 'ローカル' },\n s3: { title: 'S3' },\n limits: { title: '制限' },\n },\n keys: {\n adapter: {\n label: 'アダプター',\n options: { local: 'ローカルファイルシステム', s3: 'S3 / S3 互換' },\n },\n local_root: { label: 'ルートディレクトリ',\n help: 'ファイルを保存するファイルシステムパス。相対パスはサーバーの CWD から解決されます。' },\n s3_bucket: { label: 'バケット',\n help: '共有ホストバケット。プロジェクト毎のファイルは projects/<environmentId>/ プレフィックスで分離されます。' },\n s3_region: { label: 'リージョン', help: '例: us-east-1' },\n s3_endpoint: { label: 'エンドポイント',\n help: 'S3 互換プロバイダ (R2, MinIO, Wasabi) のカスタムエンドポイント。AWS S3 の場合は空欄。' },\n s3_access_key_id: { label: 'アクセスキー ID' },\n s3_secret_access_key: { label: 'シークレットアクセスキー' },\n s3_force_path_style: { label: 'パススタイル URL を強制',\n help: 'MinIO や多くの S3 互換プロバイダで有効化。AWS S3 では無効化。' },\n presigned_ttl: { label: '署名付き URL の有効期間 (秒)' },\n session_ttl: { label: 'アップロードセッション TTL (秒)',\n help: 'チャンクアップロードの再開可能期間。' },\n max_upload_mb: { label: '最大アップロードサイズ (MB)' },\n },\n actions: {\n test: { label: '接続テスト' },\n },\n },\n\n ai: {\n title: 'AI と Embedder',\n description:\n 'プラットフォームの AI およびナレッジサービスが使用する LLM プロバイダー、モデル、認証情報、Embedder 設定。',\n groups: {\n provider: { title: 'プロバイダー',\n description: 'LLM バックエンドを選択します。Memory モードは入力をそのまま返します。テスト用であり、本番では使用しないでください。' },\n gateway: { title: 'Vercel AI Gateway',\n description: 'マルチプロバイダールーター。モデル指定は `provider/model` 形式に従います(例: `openai/gpt-4o`)。' },\n openai: { title: 'OpenAI' },\n anthropic: { title: 'Anthropic' },\n google: { title: 'Google' },\n defaults: { title: '生成のデフォルト値',\n description: 'エージェントまたはチャットリクエストが独自の値を指定しない場合に適用されます。' },\n observability: { title: '可観測性' },\n embedder: { title: 'Embedder',\n description:\n 'ナレッジソースと RAG が使用するテキスト → ベクトルプロバイダー。' +\n '上記のチャットプロバイダーとは独立しています。' },\n },\n keys: {\n provider: {\n label: 'プロバイダー',\n options: {\n memory: 'Memory(エコー — テスト専用)',\n gateway: 'Vercel AI Gateway',\n openai: 'OpenAI',\n anthropic: 'Anthropic',\n google: 'Google Generative AI',\n },\n },\n gateway_model: { label: 'Gateway モデル',\n help: 'AI_GATEWAY_MODEL として転送されます。例: openai/gpt-4o' },\n gateway_api_key: { label: 'Gateway API キー',\n help: '任意 — Gateway が認証を要求する場合のみ必要です。' },\n openai_api_key: { label: 'OpenAI API キー',\n help: 'OPENAI_API_KEY として転送されます。保存時に暗号化されます。' },\n openai_model: { label: 'モデル',\n help: 'デフォルトのモデル ID。エージェント単位の上書きが優先されます。' },\n openai_base_url: { label: 'Base URL',\n help: 'Azure OpenAI や自己ホスト型ゲートウェイ用の上書き。api.openai.com の場合は空欄にします。' },\n anthropic_api_key: { label: 'Anthropic API キー',\n help: 'ANTHROPIC_API_KEY として転送されます。保存時に暗号化されます。' },\n anthropic_model: { label: 'モデル' },\n google_api_key: { label: 'Google API キー',\n help: 'GOOGLE_GENERATIVE_AI_API_KEY として転送されます。保存時に暗号化されます。' },\n google_model: { label: 'モデル' },\n temperature: { label: 'Temperature',\n help: '0 = 決定的、2 = 非常に創造的。' },\n max_tokens: { label: '最大出力トークン数',\n help: 'レスポンスごとに生成されるトークンの上限。' },\n request_timeout_ms: { label: 'リクエストタイムアウト (ms)' },\n trace_enabled: { label: 'トレースを記録',\n help: 'デバッグと再生のため prompt/response トレースを sys_ai_trace に保存します。' },\n log_prompts: { label: '完全なプロンプトを記録',\n help: 'メタデータだけでなくレンダリングされたプロンプトをトレース行に含めます。⚠ PII が漏えいする可能性があります。規制環境では無効にしてください。' },\n embedder_provider: {\n label: 'プロバイダー',\n options: {\n none: '無効(埋め込みなし)',\n openai: 'OpenAI',\n azure: 'Azure OpenAI',\n dashscope: '阿里通义 DashScope',\n zhipu: '智谱 BigModel',\n siliconflow: '硅基流动 SiliconFlow',\n doubao: '火山引擎 Doubao',\n minimax: 'MiniMax',\n ollama: 'Ollama(ローカル)',\n custom: 'カスタム(OpenAI 互換)',\n },\n },\n embedder_api_key: { label: 'Embedder API キー',\n help: 'Authorization ヘッダーとして送信される Bearer トークン。Ollama では空でない任意の値で動作します。' },\n embedder_model: { label: 'モデル',\n help: '例 — OpenAI: text-embedding-3-small · 阿里通义: text-embedding-v3 · 智谱: embedding-3 · 硅基流动: BAAI/bge-m3 · Ollama: bge-m3' },\n embedder_base_url: { label: 'Base URL',\n help: 'エンドポイントのルート(/embeddings を含まない)。プリセットから自動入力されます。プロキシや自己ホスト型ゲートウェイ用に上書きできます。' },\n embedder_dimensions: { label: '次元数',\n help: '出力次元数を上書きします(Matryoshka モデルのみ)。空欄の場合はモデルのデフォルトを使用します。' },\n embedder_batch_size: { label: 'バッチサイズ',\n help: 'embed() 呼び出しごとのチャンク数。プロバイダーのレート/サイズ制限に達する場合は減らします。' },\n },\n actions: {\n test: { label: '接続テスト' },\n test_embedder: { label: 'Embedder をテスト' },\n },\n },\n\n knowledge: {\n title: 'ナレッジ',\n description:\n 'RAG / ナレッジソース用のベクトルストアバックエンド。' +\n '⚠ アダプターを切替えても既存のインデックスは移行されません。',\n groups: {\n adapter: { title: 'バックエンド',\n description: 'ドキュメントチャンクとそのベクトルの保存先を選択します。' },\n turso: { title: 'Turso / libSQL',\n description: 'マネージド Turso、ローカルファイル、インメモリのいずれでも動作します。' },\n ragflow: { title: 'RAGFlow',\n description: '外部 RAGFlow デプロイ。セルフホストの手順は https://ragflow.io を参照してください。' },\n indexing: { title: 'インデックスのデフォルト値',\n description: 'KnowledgeSource.adapterConfig のソース単位の値が優先されます。' },\n permissions: { title: '権限' },\n },\n keys: {\n adapter: {\n label: 'アダプター',\n options: {\n memory: 'インメモリ(開発/テスト専用)',\n turso: 'Turso / libSQL(クラウドまたはローカル)',\n ragflow: 'RAGFlow(外部)',\n },\n },\n turso_url: { label: '接続 URL',\n help: '例: libsql://your-tenant.turso.io · file:./.objectstack/knowledge.db · :memory:' },\n turso_auth_token: { label: '認証トークン',\n help: 'マネージド Turso URL の場合のみ必要です。' },\n ragflow_base_url: { label: 'Base URL', help: '例: http://localhost:9380' },\n ragflow_api_key: { label: 'API キー' },\n ragflow_default_dataset: { label: 'デフォルトデータセット ID',\n help: 'KnowledgeSource が独自の RAGFlow データセットを指定しない場合に使用されます。' },\n chunk_target: { label: '目標チャンクサイズ(文字数)',\n help: 'トークン単位の分割が行われる前のチャンクサイズのソフト上限。' },\n chunk_overlap: { label: 'チャンクの重なり(文字数)',\n help: '境界を越えてコンテキストを維持するため、前のチャンクから保持する文字数。' },\n over_fetch: { label: 'オーバーフェッチ倍率',\n help: 'JS 側のメタデータフィルタリングでも行が残るよう、内部で topK × overFetch 件の候補を取得します。' },\n enforce_rls: { label: '検索時に RLS を強制',\n help: '各ヒットを呼び出し元のレコードレベル権限に対して再確認します。⚠ 無効化するとプラットフォーム固有のセーフガードがスキップされます。' },\n },\n actions: {\n test: { label: '接続テスト' },\n },\n },\n },\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { TranslationData } from '@objectstack/spec/system';\n\n/**\n * Español (es-ES) — built-in settings manifest translations.\n */\nexport const esES: TranslationData = {\n settingsCommon: {\n sourceLabels: {\n env: 'Entorno',\n global: 'Global',\n tenant: 'Inquilino',\n user: 'Usuario',\n default: 'Predeterminado',\n },\n },\n settings: {\n mail: {\n title: 'Envío de correo',\n description: 'Configuración de SMTP y del proveedor de correo transaccional.',\n groups: {\n provider: { title: 'Proveedor', description: 'Elige cómo envía correo saliente este espacio de trabajo.' },\n smtp: { title: 'SMTP' },\n api_key: { title: 'Clave de API' },\n from_address: { title: 'Dirección de remitente' },\n },\n keys: {\n provider: {\n label: 'Proveedor',\n options: {\n smtp: 'SMTP',\n sendgrid: 'SendGrid',\n ses: 'Amazon SES',\n postmark: 'Postmark',\n },\n },\n smtp_host: { label: 'Host', help: 'Ejemplo: smtp.example.com' },\n smtp_port: { label: 'Puerto' },\n smtp_secure: { label: 'Usar TLS' },\n smtp_user: { label: 'Usuario' },\n smtp_password: { label: 'Contraseña' },\n api_key: { label: 'Clave de API' },\n from_email: { label: 'Correo del remitente', help: 'Ejemplo: no-reply@example.com' },\n from_name: { label: 'Nombre del remitente' },\n },\n actions: {\n test: { label: 'Enviar correo de prueba' },\n },\n },\n\n branding: {\n title: 'Marca',\n description: 'Nombre del espacio de trabajo, logotipo y color de acento.',\n groups: {\n identity: { title: 'Identidad' },\n appearance: { title: 'Apariencia' },\n },\n keys: {\n workspace_name: { label: 'Nombre del espacio de trabajo' },\n support_email: { label: 'Correo de soporte', help: 'Ejemplo: support@example.com' },\n theme_mode: {\n label: 'Tema predeterminado',\n options: { light: 'Claro', dark: 'Oscuro', system: 'Según el sistema' },\n },\n accent_color: { label: 'Color de acento' },\n logo_url: { label: 'URL del logotipo', help: 'Ejemplo: https://…/logo.svg' },\n },\n },\n\n auth: {\n title: 'Autenticación',\n description: 'Inicio de sesión, registro y controles de las funciones de autenticación integradas.',\n groups: {\n email_password: {\n title: 'Correo y contraseña',\n description: 'Controla el inicio de sesión local con correo/contraseña y el registro de autoservicio.',\n },\n social: {\n title: 'Inicio de sesión social',\n description:\n 'Configura el proveedor de inicio de sesión de Google integrado. Las variables de entorno del despliegue siguen teniendo prioridad.',\n },\n },\n keys: {\n email_password_enabled: { label: 'Habilitar inicio de sesión con correo/contraseña' },\n signup_enabled: { label: 'Permitir registro de autoservicio' },\n require_email_verification: { label: 'Requerir verificación de correo' },\n google_enabled: {\n label: 'Habilitar inicio de sesión con Google',\n help: 'Requiere un ID de cliente y un secreto de OAuth de Google desde Google Cloud Console.',\n },\n google_client_id: {\n label: 'ID de cliente de Google',\n help: 'ID de cliente de OAuth desde Google Cloud Console. También se puede definir GOOGLE_CLIENT_ID en el servidor.',\n },\n google_client_secret: {\n label: 'Secreto de cliente de Google',\n help: 'Se almacena cifrado en reposo. También se puede definir GOOGLE_CLIENT_SECRET en el servidor.',\n },\n },\n },\n\n feature_flags: {\n title: 'Indicadores de función',\n description: 'Activa funciones experimentales y en beta para este espacio de trabajo.',\n groups: {\n productivity: { title: 'Productividad' },\n collaboration: { title: 'Colaboración' },\n },\n keys: {\n ai_enabled: {\n label: 'Asistente de IA',\n help: 'Habilita el panel del asistente de IA dentro de la aplicación.',\n },\n kanban_swimlanes: { label: 'Carriles de Kanban' },\n realtime_cursors: { label: 'Cursores en tiempo real' },\n inline_comments: { label: 'Comentarios en línea' },\n },\n },\n\n storage: {\n title: 'Almacenamiento de archivos',\n description:\n 'Backend usado para adjuntos, exportaciones y subidas de usuarios. ' +\n '⚠ Cambiar de adaptador no migra los archivos existentes: los archivos ' +\n 'subidos con el adaptador anterior dejan de ser accesibles a través ' +\n 'del nuevo.',\n groups: {\n adapter: { title: 'Backend', description: 'Elige dónde se almacenan los archivos subidos.' },\n local: { title: 'Local' },\n s3: { title: 'S3' },\n limits: { title: 'Límites' },\n },\n keys: {\n adapter: {\n label: 'Adaptador',\n options: { local: 'Sistema de archivos local', s3: 'S3 / compatible con S3' },\n },\n local_root: { label: 'Directorio raíz',\n help: 'Ruta del sistema de archivos donde se almacenan los archivos. Las rutas relativas se resuelven desde el directorio de trabajo del servidor.' },\n s3_bucket: { label: 'Bucket',\n help: 'Bucket compartido del host. Los archivos de cada entorno se aíslan mediante el prefijo projects/<environmentId>/.' },\n s3_region: { label: 'Región', help: 'Ejemplo: us-east-1' },\n s3_endpoint: { label: 'Endpoint',\n help: 'Endpoint personalizado para proveedores compatibles con S3 (R2, MinIO, Wasabi). Déjalo en blanco para AWS S3.' },\n s3_access_key_id: { label: 'Access Key ID' },\n s3_secret_access_key: { label: 'Secret Access Key' },\n s3_force_path_style: { label: 'Forzar URLs de tipo path',\n help: 'Actívalo para MinIO y la mayoría de proveedores compatibles con S3; desactívalo para AWS S3.' },\n presigned_ttl: { label: 'TTL de URL prefirmada (segundos)' },\n session_ttl: { label: 'TTL de sesión de subida (segundos)',\n help: 'Tiempo durante el cual una sesión de subida por fragmentos sigue siendo reanudable.' },\n max_upload_mb: { label: 'Tamaño máximo de subida (MB)' },\n },\n actions: {\n test: { label: 'Probar conexión' },\n },\n },\n\n ai: {\n title: 'IA y Embedder',\n description:\n 'Proveedor de LLM, modelo, credenciales y configuración del embedder usados por ' +\n 'los servicios de IA y de conocimiento de la plataforma.',\n groups: {\n provider: { title: 'Proveedor',\n description: 'Elige el backend de LLM. El modo Memory repite la entrada: útil para pruebas, nunca para producción.' },\n gateway: { title: 'Vercel AI Gateway',\n description: 'Enrutador multiproveedor. La especificación del modelo sigue `provider/model`, p. ej. `openai/gpt-4o`.' },\n openai: { title: 'OpenAI' },\n anthropic: { title: 'Anthropic' },\n google: { title: 'Google' },\n defaults: { title: 'Valores predeterminados de generación',\n description: 'Se aplican cuando un agente o una solicitud de chat no especifica su propio valor.' },\n observability: { title: 'Observabilidad' },\n embedder: { title: 'Embedder',\n description:\n 'Proveedor de texto → vector usado por las fuentes de conocimiento y RAG. ' +\n 'Independiente del proveedor de chat anterior.' },\n },\n keys: {\n provider: {\n label: 'Proveedor',\n options: {\n memory: 'Memory (eco — solo pruebas)',\n gateway: 'Vercel AI Gateway',\n openai: 'OpenAI',\n anthropic: 'Anthropic',\n google: 'Google Generative AI',\n },\n },\n gateway_model: { label: 'Modelo de Gateway',\n help: 'Se reenvía como AI_GATEWAY_MODEL. Ejemplo: openai/gpt-4o' },\n gateway_api_key: { label: 'Clave de API de Gateway',\n help: 'Opcional: solo se requiere si el gateway exige autenticación.' },\n openai_api_key: { label: 'Clave de API de OpenAI',\n help: 'Se reenvía como OPENAI_API_KEY. Se almacena cifrada en reposo.' },\n openai_model: { label: 'Modelo',\n help: 'ID de modelo predeterminado. Las anulaciones por agente tienen prioridad.' },\n openai_base_url: { label: 'Base URL',\n help: 'Anulación para Azure OpenAI o gateways autoalojados. Déjalo en blanco para api.openai.com.' },\n anthropic_api_key: { label: 'Clave de API de Anthropic',\n help: 'Se reenvía como ANTHROPIC_API_KEY. Se almacena cifrada en reposo.' },\n anthropic_model: { label: 'Modelo' },\n google_api_key: { label: 'Clave de API de Google',\n help: 'Se reenvía como GOOGLE_GENERATIVE_AI_API_KEY. Se almacena cifrada en reposo.' },\n google_model: { label: 'Modelo' },\n temperature: { label: 'Temperatura',\n help: '0 = determinista, 2 = muy creativo.' },\n max_tokens: { label: 'Máximo de tokens de salida',\n help: 'Límite estricto de tokens generados por respuesta.' },\n request_timeout_ms: { label: 'Tiempo de espera de la solicitud (ms)' },\n trace_enabled: { label: 'Registrar trazas',\n help: 'Persiste las trazas de prompt/respuesta en sys_ai_trace para depuración y reproducción.' },\n log_prompts: { label: 'Registrar prompts completos',\n help: 'Incluye los prompts renderizados (no solo metadatos) en las filas de traza. ⚠ Puede filtrar PII: desactívalo en entornos regulados.' },\n embedder_provider: {\n label: 'Proveedor',\n options: {\n none: 'Deshabilitado (sin embeddings)',\n openai: 'OpenAI',\n azure: 'Azure OpenAI',\n dashscope: '阿里通义 DashScope',\n zhipu: '智谱 BigModel',\n siliconflow: '硅基流动 SiliconFlow',\n doubao: '火山引擎 Doubao',\n minimax: 'MiniMax',\n ollama: 'Ollama (local)',\n custom: 'Personalizado (compatible con OpenAI)',\n },\n },\n embedder_api_key: { label: 'Clave de API del embedder',\n help: 'Token bearer enviado en la cabecera Authorization. Para Ollama sirve cualquier valor no vacío.' },\n embedder_model: { label: 'Modelo',\n help: 'Ejemplos — OpenAI: text-embedding-3-small · 阿里通义: text-embedding-v3 · 智谱: embedding-3 · 硅基流动: BAAI/bge-m3 · Ollama: bge-m3' },\n embedder_base_url: { label: 'Base URL',\n help: 'Raíz del endpoint (sin /embeddings). Se autocompleta desde el preset; anúlalo para proxys o gateways autoalojados.' },\n embedder_dimensions: { label: 'Dimensiones',\n help: 'Anula la dimensionalidad de salida (solo modelos Matryoshka). Déjalo en blanco para usar el valor predeterminado del modelo.' },\n embedder_batch_size: { label: 'Tamaño de lote',\n help: 'Fragmentos por llamada a embed(). Redúcelo si alcanzas los límites de tasa o tamaño del proveedor.' },\n },\n actions: {\n test: { label: 'Probar conexión' },\n test_embedder: { label: 'Probar embedder' },\n },\n },\n\n knowledge: {\n title: 'Conocimiento',\n description:\n 'Backend de almacén de vectores para RAG / fuentes de conocimiento. ' +\n '⚠ Cambiar de adaptador NO migra los índices existentes.',\n groups: {\n adapter: { title: 'Backend',\n description: 'Elige dónde se almacenan los fragmentos de documento y sus vectores.' },\n turso: { title: 'Turso / libSQL',\n description: 'Funciona con Turso gestionado, archivo local o en memoria.' },\n ragflow: { title: 'RAGFlow',\n description: 'Despliegue externo de RAGFlow. Consulta https://ragflow.io para instrucciones de autoalojamiento.' },\n indexing: { title: 'Valores predeterminados de indexación',\n description: 'Los valores por fuente en KnowledgeSource.adapterConfig tienen prioridad.' },\n permissions: { title: 'Permisos' },\n },\n keys: {\n adapter: {\n label: 'Adaptador',\n options: {\n memory: 'En memoria (solo desarrollo / pruebas)',\n turso: 'Turso / libSQL (nube o local)',\n ragflow: 'RAGFlow (externo)',\n },\n },\n turso_url: { label: 'URL de conexión',\n help: 'Ejemplos: libsql://your-tenant.turso.io · file:./.objectstack/knowledge.db · :memory:' },\n turso_auth_token: { label: 'Token de autenticación',\n help: 'Solo se requiere para URLs de Turso gestionado.' },\n ragflow_base_url: { label: 'Base URL', help: 'Ejemplo: http://localhost:9380' },\n ragflow_api_key: { label: 'Clave de API' },\n ragflow_default_dataset: { label: 'ID de dataset predeterminado',\n help: 'Se usa cuando una KnowledgeSource no especifica su propio dataset de RAGFlow.' },\n chunk_target: { label: 'Tamaño objetivo de fragmento (caracteres)',\n help: 'Límite flexible del tamaño de fragmento antes de que actúe la división consciente de tokens.' },\n chunk_overlap: { label: 'Solapamiento de fragmentos (caracteres)',\n help: 'Caracteres conservados del fragmento anterior para que el contexto sobreviva al límite.' },\n over_fetch: { label: 'Multiplicador de sobre-obtención',\n help: 'Se obtienen topK × overFetch candidatos internos para que el filtrado de metadatos en JS siga teniendo filas.' },\n enforce_rls: { label: 'Aplicar RLS en la búsqueda',\n help: 'Vuelve a comprobar cada resultado contra los permisos a nivel de registro del solicitante. ⚠ Desactivarlo omite la salvaguarda exclusiva de la plataforma.' },\n },\n actions: {\n test: { label: 'Probar conexión' },\n },\n },\n },\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Built-in Settings translations.\n *\n * Mirrors the CRM example's `src/translations/{en,zh-CN,ja-JP}.ts` convention —\n * one file per locale, aggregated into a `TranslationBundle` here.\n *\n * Hosts merge `settingsBuiltinTranslations` into the i18next resource tree\n * under whatever namespace makes sense (the console wires it as `system`),\n * making keys resolvable as `<ns>.settings.<namespace>.{title,description,...}`.\n */\n\nimport type { TranslationBundle } from '@objectstack/spec/system';\nimport { en } from './en.js';\nimport { zhCN } from './zh-CN.js';\nimport { jaJP } from './ja-JP.js';\nimport { esES } from './es-ES.js';\n\nexport { en, zhCN, jaJP, esES };\n\nexport const settingsBuiltinTranslations: TranslationBundle = {\n en,\n 'zh-CN': zhCN,\n 'ja-JP': jaJP,\n 'es-ES': esES,\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Plugin, PluginContext } from '@objectstack/core';\nimport type { IHttpServer, IDataEngine } from '@objectstack/spec/contracts';\nimport type { SettingsManifest } from '@objectstack/spec/system';\nimport { SettingsService } from './settings-service.js';\nimport type { ICryptoProvider } from '@objectstack/spec/contracts';\nimport type { SettingsAuditWriter, SettingsEngine, SettingsSecretStore } from './settings-service.types.js';\nimport type { CryptoAdapter } from './crypto-adapter.js';\nimport { LocalCryptoProvider } from './local-crypto-provider.js';\nimport { registerSettingsRoutes } from './settings-routes.js';\nimport {\n settingsObjects,\n settingsPluginManifestHeader,\n SETTINGS_PLUGIN_ID,\n SETTINGS_PLUGIN_VERSION,\n} from './manifest.js';\nimport {\n builtinSettingsManifests,\n mailTestActionHandler,\n storageTestActionHandler,\n aiTestActionHandler,\n} from './manifests/index.js';\nimport { settingsBuiltinTranslations } from './translations/index.js';\n\n/** Configuration options for the SettingsServicePlugin. */\nexport interface SettingsServicePluginOptions {\n /**\n * Pre-register these manifests at boot. When omitted, the bundled\n * builtin manifests (mail / branding / feature_flags) are loaded so\n * a host gets a working Settings hub out of the box. Pass an empty\n * array to opt out entirely.\n */\n manifests?: SettingsManifest[];\n /** Override the default crypto adapter. */\n crypto?: CryptoAdapter;\n\n /**\n * Phase 3 KMS hook. When provided, encrypted specifier values are\n * routed through this provider into `sys_secret`; `sys_setting.value_enc`\n * holds the handle id only. Defaults to `LocalCryptoProvider`, an\n * AES-256-GCM provider keyed off `OS_SECRET_KEY` (or a persisted dev key).\n * In production it refuses to boot without a stable key rather than\n * silently minting an ephemeral one. Swap in an AWS / GCP / Vault\n * KMS-backed implementation for managed custody and per-tenant keys.\n */\n cryptoProvider?: ICryptoProvider;\n /** Override the default base path (`/api/settings`). */\n basePath?: string;\n /** Disable REST route registration. */\n registerRoutes?: boolean;\n /** Override the env source. Defaults to `process.env`. */\n env?: Record<string, string | undefined>;\n /**\n * Action handlers to register at boot, keyed by namespace and action\n * id. The bundled `mail.test` handler is registered automatically\n * unless this object is provided.\n */\n actionHandlers?: Record<string, Record<string, import('./settings-service.types.js').SettingsActionHandler>>;\n}\n\n/**\n * SettingsServicePlugin — wires the SettingsService into the kernel.\n *\n * 1. `init`: instantiate the service, register it under `'settings'`,\n * and ship `sys_setting` to the manifest service so the engine\n * auto-provisions the table.\n * 2. `start` → `kernel:ready`: bind the data engine (when present),\n * wire the audit sink (when present), mount REST routes.\n */\nexport class SettingsServicePlugin implements Plugin {\n name = SETTINGS_PLUGIN_ID;\n version = SETTINGS_PLUGIN_VERSION;\n type = 'standard' as const;\n\n private readonly opts: SettingsServicePluginOptions;\n private service: SettingsService | null = null;\n\n constructor(opts: SettingsServicePluginOptions = {}) {\n this.opts = {\n ...opts,\n manifests: opts.manifests ?? builtinSettingsManifests,\n actionHandlers: opts.actionHandlers ?? {\n mail: { test: mailTestActionHandler },\n storage: { test: storageTestActionHandler },\n ai: { test: aiTestActionHandler },\n },\n };\n }\n\n async init(ctx: PluginContext): Promise<void> {\n this.service = new SettingsService({\n crypto: this.opts.crypto,\n env: this.opts.env,\n });\n for (const m of this.opts.manifests ?? []) this.service.registerManifest(m);\n for (const [ns, handlers] of Object.entries(this.opts.actionHandlers ?? {})) {\n for (const [id, fn] of Object.entries(handlers)) {\n this.service.registerAction(ns, id, fn);\n }\n }\n\n ctx.registerService('settings', this.service);\n ctx.logger?.info?.(\n `SettingsServicePlugin: registered (manifests=${this.opts.manifests?.length ?? 0})`,\n );\n\n // Register the K/V object so the engine creates the table.\n try {\n ctx.getService<{ register(m: any): void }>('manifest').register({\n ...settingsPluginManifestHeader,\n objects: settingsObjects,\n });\n } catch {\n // manifest service is optional — skip in lean test kernels.\n }\n }\n\n async start(ctx: PluginContext): Promise<void> {\n if (!this.service) return;\n\n ctx.hook('kernel:ready', async () => {\n // Contribute built-in settings translations into the i18n service.\n // Done in `kernel:ready` (not `init`) because the i18n service plugin\n // is typically registered AFTER capability-loaded service plugins.\n try {\n const i18n = ctx.getService<{\n loadTranslations: (locale: string, data: Record<string, unknown>) => void;\n }>('i18n');\n let loaded = 0;\n for (const [locale, data] of Object.entries(settingsBuiltinTranslations)) {\n if (data && typeof data === 'object') {\n try {\n i18n.loadTranslations(locale, data as Record<string, unknown>);\n loaded++;\n } catch (err: any) {\n ctx.logger?.warn?.(\n `SettingsServicePlugin: failed to load translations for '${locale}': ${err?.message ?? err}`,\n );\n }\n }\n }\n if (loaded > 0) {\n ctx.logger?.info?.(\n `SettingsServicePlugin: contributed built-in translations (${loaded} locale${loaded > 1 ? 's' : ''})`,\n );\n }\n } catch {\n // i18n service not registered — manifest literals remain authoritative.\n }\n\n // Late-bind the data engine.\n let engine: IDataEngine | null = null;\n try {\n engine = ctx.getService<IDataEngine>('objectql');\n } catch {\n // ok — fall back to in-memory.\n }\n if (engine) {\n // Late-bind the engine + audit sink on the existing service\n // instance. We avoid re-registering the service because the\n // kernel disallows `registerService` for an already-registered\n // name.\n //\n // SettingsEngine and IDataEngine have *different* update\n // signatures — SettingsEngine bundles `{ where, data }` into a\n // single opts object, while IDataEngine takes\n // `(object, data, options?)` and extracts the row id from\n // `data.id` or `options.where.id`. A force-cast leaves runtime\n // calls to `update(object, { where, data })` reaching the real\n // engine as a malformed payload with no id, which then throws\n // \"Update requires an ID or options.multi=true\". The adapter\n // below performs the translation so SettingsService can keep\n // its narrow, bundled signature.\n this.service!.bindEngine(\n wrapEngineAsSettingsEngine(engine),\n undefined,\n {\n secretStore: this.buildSecretStore(engine),\n auditWriter: this.buildAuditWriter(ctx, engine),\n cryptoProvider: this.opts.cryptoProvider ?? new LocalCryptoProvider(),\n },\n );\n }\n\n if (this.opts.registerRoutes === false) return;\n\n let http: IHttpServer | null = null;\n try {\n http = ctx.getService<IHttpServer>('http-server');\n } catch {\n // ok — no HTTP server in this deployment.\n }\n if (!http) {\n ctx.logger?.warn?.(\n 'SettingsServicePlugin: no HTTP server available — REST routes not registered. ' +\n 'SettingsService is still reachable via kernel.getService(\"settings\").',\n );\n return;\n }\n registerSettingsRoutes(http, this.service!, { basePath: this.opts.basePath });\n ctx.logger?.info?.(\n 'SettingsServicePlugin: REST routes registered at ' + (this.opts.basePath ?? '/api/settings'),\n );\n });\n }\n\n /**\n * Phase 3: build a `sys_secret`-backed implementation of\n * `SettingsSecretStore`. The store bypasses the tenant audit\n * warning because secrets are scoped through their owning\n * `sys_setting` row (which already carries the tenant context).\n */\n private buildSecretStore(engine: IDataEngine): SettingsSecretStore {\n const eng: any = engine;\n return {\n async insert(row) {\n await eng.insert('sys_secret', row, { bypassTenantAudit: true });\n return { id: row.id };\n },\n async get(id) {\n const rows = await eng.find('sys_secret', {\n where: { id },\n limit: 1,\n bypassTenantAudit: true,\n });\n const row = Array.isArray(rows) ? rows[0] : rows?.data?.[0];\n return row ?? null;\n },\n async update(id, patch) {\n // IDataEngine.update signature is `(object, data, options?)`\n // and extracts the record id from `data.id` (or\n // `options.where.id`). Passing `{ where, data, ... }` as the\n // data argument left id=undefined and tripped\n // \"Update requires an ID or options.multi=true\".\n await eng.update(\n 'sys_secret',\n { id, ...patch },\n { bypassTenantAudit: true },\n );\n },\n };\n }\n\n /**\n * Phase 3: append-only writer for `sys_setting_audit`. Failures here\n * MUST NOT abort the settings write, so all calls are wrapped in a\n * try/catch and reported through the plugin logger.\n */\n private buildAuditWriter(ctx: PluginContext, engine: IDataEngine): SettingsAuditWriter {\n const eng: any = engine;\n return {\n write: async (entry) => {\n try {\n await eng.insert('sys_setting_audit', {\n namespace: entry.namespace,\n key: entry.key,\n scope: entry.scope,\n action: entry.action,\n source: entry.source ?? 'api',\n actor_id: entry.actorId ?? null,\n old_hash: entry.oldHash ?? null,\n new_hash: entry.newHash ?? null,\n encrypted: !!entry.encrypted,\n request_id: entry.requestId ?? null,\n reason: entry.reason ?? null,\n created_at: new Date().toISOString(),\n }, { bypassTenantAudit: true });\n } catch (err: any) {\n ctx.logger?.warn?.('SettingsServicePlugin: setting-audit write failed: ' + (err?.message ?? err));\n }\n },\n };\n }\n}\n\n/**\n * Translate an `IDataEngine` instance into the narrower `SettingsEngine`\n * surface used inside `SettingsService`. The two interfaces diverge on\n * `update`:\n *\n * - SettingsEngine: `update(object, { where, data, bypassTenantAudit })`\n * - IDataEngine: `update(object, data, options?)` — id comes from\n * `data.id` or `options.where.id`; otherwise the engine throws\n * \"Update requires an ID or options.multi=true\".\n *\n * The adapter resolves the row id from `where.id` when present and\n * forwards everything in IDataEngine's positional form. When the caller\n * supplies a non-id where clause (composite-key tables), we fall back\n * to `multi: true` so the engine routes through `driver.updateMany`\n * instead of throwing.\n */\nfunction wrapEngineAsSettingsEngine(engine: IDataEngine): SettingsEngine {\n const eng: any = engine;\n return {\n async find(objectName, opts) {\n return eng.find(objectName, opts);\n },\n async insert(objectName, data, opts) {\n return eng.insert(objectName, data, opts);\n },\n async update(objectName, opts) {\n const { where, data, bypassTenantAudit } = opts as {\n where: Record<string, unknown>;\n data: Record<string, unknown>;\n bypassTenantAudit?: boolean;\n };\n const driverOpts = bypassTenantAudit ? { bypassTenantAudit: true } : undefined;\n const id = (where as any)?.id;\n if (id !== undefined && id !== null) {\n return eng.update(objectName, { id, ...data }, driverOpts);\n }\n return eng.update(objectName, data, {\n where,\n multi: true,\n ...(driverOpts ?? {}),\n });\n },\n };\n}\n"],"mappings":"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","names":["manifest","def","persisted","manifest","manifest","manifest","model","manifest"]}