arkgate 2.12.0 → 2.13.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.
- package/CHANGELOG.md +83 -0
- package/README.md +55 -31
- package/bin/ark-check.mjs +95 -36
- package/bin/ark-mcp.mjs +11 -5
- package/bin/ark-shared.mjs +88 -56
- package/bin/ark.mjs +45 -10
- package/bin/lib/agent-gates.mjs +12 -0
- package/bin/lib/architecture-scan.mjs +8 -0
- package/bin/lib/ci-and-commands.mjs +9 -3
- package/bin/lib/codex-home.mjs +7 -0
- package/bin/lib/config-contract.mjs +331 -0
- package/bin/lib/doctor-plan.mjs +43 -16
- package/bin/lib/enforcement-profiles.mjs +97 -0
- package/bin/lib/host-support-matrix.mjs +77 -0
- package/bin/lib/install-migrate.mjs +45 -14
- package/bin/lib/mcp-adoption.mjs +35 -3
- package/bin/lib/open-html.mjs +75 -0
- package/bin/lib/presets.mjs +3 -2
- package/bin/lib/safety-diagnostics.mjs +31 -11
- package/bin/lib/skill-install.mjs +64 -0
- package/bin/lib/ts-resolve.mjs +2 -1
- package/bin/lib/weakest-link.mjs +417 -0
- package/bin/lib/write-path-capabilities.mjs +182 -0
- package/bin/lib/write-path-detect.mjs +62 -99
- package/dist/configContract-iBLxx5Tz.d.cts +53 -0
- package/dist/configContract-iBLxx5Tz.d.ts +53 -0
- package/dist/eslint/index.cjs +375 -13
- package/dist/eslint/index.cjs.map +1 -1
- package/dist/eslint/index.d.cts +30 -20
- package/dist/eslint/index.d.ts +30 -20
- package/dist/eslint/index.js +375 -13
- package/dist/eslint/index.js.map +1 -1
- package/dist/index.cjs +723 -61
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +95 -5
- package/dist/index.d.ts +95 -5
- package/dist/index.js +716 -61
- package/dist/index.js.map +1 -1
- package/dist/nestjs/index.cjs +150 -42
- package/dist/nestjs/index.cjs.map +1 -1
- package/dist/nestjs/index.d.cts +2 -1
- package/dist/nestjs/index.d.ts +2 -1
- package/dist/nestjs/index.js +150 -42
- package/dist/nestjs/index.js.map +1 -1
- package/dist/runtime/index.cjs +723 -61
- package/dist/runtime/index.cjs.map +1 -1
- package/dist/runtime/index.d.cts +3 -2
- package/dist/runtime/index.d.ts +3 -2
- package/dist/runtime/index.js +716 -61
- package/dist/runtime/index.js.map +1 -1
- package/dist/{types-BZ17b9i5.d.cts → types-BxBwnBpC.d.cts} +9 -36
- package/dist/{types-BZ17b9i5.d.ts → types-Wcs_l1_J.d.ts} +9 -36
- package/docs/agent-guide.md +32 -20
- package/docs/ai-gates.md +53 -18
- package/docs/configuration.md +97 -0
- package/docs/enthusiast/README.md +3 -3
- package/docs/enthusiast/how-to-agent-gates.md +7 -3
- package/docs/migrate-from-ark-runtime-kernel.md +3 -0
- package/docs/package-surface.md +14 -9
- package/docs/production-hardening.md +15 -2
- package/docs/threat-model.md +65 -0
- package/docs/typescript-support.md +3 -3
- package/package.json +15 -2
- package/schemas/ark.config.schema.json +750 -0
- package/server.json +2 -2
- package/templates/hooks/pre-commit-ark +37 -0
- package/templates/skills/ark-coverage.md +2 -2
- package/templates/skills/ark-runtime.md +8 -5
- package/templates/skills/ark-upgrade.md +36 -16
- package/tests/fixtures/ts-consumer/ark.config.json +2 -0
package/dist/eslint/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/eslint/index.ts","../../src/domain/layerMatch.ts"],"sourcesContent":["/**\n * arkgate/eslint — editor-side architecture gate.\n *\n * Layer / import / forbidden-globals rules load `ark.config.json` from the linted\n * project (walk-up from the file) and use the same glob specificity + edge semantics\n * as ark-check. Matching primitives come from the canonical\n * `src/domain/layerMatch.ts` (CLI loads the generated `bin/ark-layer-match.mjs`) —\n * no Kernel imports.\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport {\n globToRegExp,\n patternSpecificity,\n layerForRelativePath,\n isEdgeDenied,\n} from '../domain/layerMatch';\n\nexport { globToRegExp, patternSpecificity, layerForRelativePath, isEdgeDenied };\n\ntype RuleContext = {\n report(descriptor: Record<string, unknown>): void;\n /** ESLint 9+ / 10: preferred path on the context object. */\n filename?: string;\n /** ESLint 8-style physical path when linting with processors / virtual files. */\n physicalFilename?: string;\n /** ESLint ≤8 API — still present on some hosts; removed in ESLint 10. */\n getFilename?: () => string;\n options?: unknown[];\n};\n\n/** Resolve the file path being linted across ESLint 8–10 context shapes. */\nfunction lintedFilename(context: RuleContext): string {\n if (typeof context.physicalFilename === 'string' && context.physicalFilename.length > 0) {\n return context.physicalFilename;\n }\n if (typeof context.filename === 'string' && context.filename.length > 0) {\n return context.filename;\n }\n if (typeof context.getFilename === 'function') {\n try {\n const name = context.getFilename();\n if (typeof name === 'string' && name.length > 0) return name;\n } catch {\n /* ignore */\n }\n }\n return '';\n}\n\ntype RuleListener = Record<string, (node: AstNode) => void>;\n\ntype AstNode = {\n type?: string;\n name?: string;\n value?: unknown;\n source?: AstNode;\n callee?: AstNode;\n object?: AstNode;\n property?: AstNode;\n key?: AstNode;\n arguments?: AstNode[];\n properties?: AstNode[];\n importKind?: string;\n specifiers?: AstNode[];\n};\n\ntype ArkRule = {\n meta: {\n type: 'problem';\n docs: { description: string };\n messages: Record<string, string>;\n schema: unknown[];\n };\n create(context: RuleContext): RuleListener;\n};\n\ntype ArkEslintPlugin = {\n rules: Record<string, ArkRule>;\n configs?: Record<string, unknown>;\n};\n\ntype LayerConfig = {\n name: string;\n patterns?: string[];\n exclude?: string[];\n forbiddenGlobals?: string[];\n};\n\ntype EdgeRule = { from: string; to: string; allowed?: boolean };\n\ntype ArkConfig = {\n layers?: LayerConfig[];\n rules?: EdgeRule[];\n};\n\n// ── Config I/O (editor-only; matching primitives come from ark-layer-match.mjs) ──\n\nexport function findConfigPath(startFile: string): string | null {\n if (!startFile || startFile === '<input>' || startFile.startsWith('stdin')) return null;\n let dir = path.dirname(path.resolve(startFile));\n for (;;) {\n const candidate = path.join(dir, 'ark.config.json');\n if (fs.existsSync(candidate)) return candidate;\n const parent = path.dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n}\n\nconst _configCache = new Map<string, ArkConfig | null>();\n\nexport function loadArkConfig(configPath: string): ArkConfig | null {\n if (_configCache.has(configPath)) return _configCache.get(configPath) ?? null;\n try {\n const raw = JSON.parse(fs.readFileSync(configPath, 'utf8')) as ArkConfig;\n _configCache.set(configPath, raw);\n return raw;\n } catch {\n _configCache.set(configPath, null);\n return null;\n }\n}\n\n/** Resolve relative import specifier to an absolute path candidate (TS-oriented). */\nexport function resolveRelativeImport(fromFile: string, specifier: string): string | null {\n if (!specifier.startsWith('.')) return null;\n const base = path.resolve(path.dirname(fromFile), specifier);\n const candidates = [\n base,\n `${base}.ts`,\n `${base}.tsx`,\n `${base}.mts`,\n `${base}.cts`,\n `${base}.js`,\n `${base}.jsx`,\n path.join(base, 'index.ts'),\n path.join(base, 'index.tsx'),\n path.join(base, 'index.js'),\n ];\n for (const c of candidates) {\n try {\n if (fs.existsSync(c) && fs.statSync(c).isFile()) return c;\n } catch {\n /* continue */\n }\n }\n // Prefer .ts for layer matching when the target is not on disk yet (editor typing).\n return `${base}.ts`;\n}\n\n// ── AST helpers ────────────────────────────────────────────────────────────\n\nfunction stringValue(node: AstNode | undefined): string | undefined {\n return typeof node?.value === 'string' ? node.value : undefined;\n}\n\nfunction propertyName(node: AstNode | undefined): string | undefined {\n return node?.name ?? stringValue(node);\n}\n\nfunction calleePropertyName(node: AstNode): string | undefined {\n return propertyName(node.callee?.property);\n}\n\nfunction objectProperty(node: AstNode | undefined, name: string): AstNode | undefined {\n return node?.properties?.find((property) => propertyName(property.key) === name);\n}\n\nfunction objectHasProperty(node: AstNode | undefined, name: string): boolean {\n return objectProperty(node, name) !== undefined;\n}\n\nfunction objectHasMetadataSource(node: AstNode | undefined): boolean {\n const metadata = objectProperty(node, 'metadata')?.value as AstNode | undefined;\n return objectHasProperty(metadata, 'source');\n}\n\nfunction looksLikeIntent(value: string): boolean {\n return /^(Domain|Application|Adapter|Workflow|Job|Presentation|Reporting|Metadata|Security|Audit|Observability|Kernel)\\.[A-Za-z0-9_.]+$/.test(\n value\n );\n}\n\nfunction isPublishCall(node: AstNode): boolean {\n return calleePropertyName(node) === 'publish';\n}\n\n/** Heuristic fallback when no ark.config.json (pre-contract projects). */\nfunction isDomainFileHeuristic(filename: string): boolean {\n const normalized = filename.split('\\\\').join('/').toLowerCase();\n return normalized.includes('/domain/') || normalized.endsWith('/domain.ts');\n}\n\nfunction isInfraImportHeuristic(specifier: string): boolean {\n const normalized = specifier.toLowerCase();\n return [\n 'adapter',\n 'adapters',\n 'infrastructure',\n 'persistence',\n 'repository',\n 'repositories',\n 'integration',\n 'database',\n 'db',\n ].some((token) => normalized.includes(token));\n}\n\nconst DEFAULT_FORBIDDEN_GLOBALS = ['fetch', 'process', 'Date.now', 'Math.random'];\n\n// ── Rules ──────────────────────────────────────────────────────────────────\n\n/**\n * Config-driven layer import boundary (primary editor gate).\n * Replaces path-token domain/infra heuristics when ark.config.json is present.\n * Rule id kept as `no-domain-infra-imports` for recommended-config / upgrade stability.\n */\nexport const noDomainInfraImports: ArkRule = {\n meta: {\n type: 'problem',\n docs: {\n description:\n 'Disallow imports that violate ark.config.json layer rules (same contract as arkgate-check). Falls back to domain→infra path heuristics when no config is found.',\n },\n messages: {\n forbiddenImport:\n 'Architecture: {{fromLayer}} must not import {{toLayer}} (ark.config.json). Specifier: {{specifier}}',\n forbiddenImportHeuristic:\n 'Domain code must not import infrastructure, adapters, repositories, or database modules.',\n },\n schema: [],\n },\n create(context) {\n const filename = lintedFilename(context);\n const configPath = findConfigPath(filename);\n const config = configPath ? loadArkConfig(configPath) : null;\n const root = configPath ? path.dirname(configPath) : null;\n\n const check = (node: AstNode) => {\n const source = stringValue(node.source);\n if (!source) return;\n\n if (config && root && filename) {\n const absFile = path.isAbsolute(filename) ? filename : path.resolve(filename);\n const relFile = path.relative(root, absFile).split(path.sep).join('/');\n const fromLayer = layerForRelativePath(relFile, config.layers);\n if (!fromLayer) return;\n\n const targetAbs = resolveRelativeImport(absFile, source);\n if (!targetAbs) return; // package import — CI resolves via TS; editor skips non-relative\n\n const relTarget = path.relative(root, targetAbs).split(path.sep).join('/');\n // Outside project or up-and-out: skip\n if (relTarget.startsWith('..')) return;\n\n const toLayer = layerForRelativePath(relTarget, config.layers);\n if (!toLayer) return;\n if (\n isEdgeDenied(config.rules, fromLayer, toLayer, {\n fromPath: relFile,\n toPath: relTarget,\n layers: config.layers,\n })\n ) {\n context.report({\n node,\n messageId: 'forbiddenImport',\n data: { fromLayer, toLayer, specifier: source },\n });\n }\n return;\n }\n\n // No contract: legacy heuristic so bare domain folders still get a signal.\n if (isDomainFileHeuristic(filename) && isInfraImportHeuristic(source)) {\n context.report({ node, messageId: 'forbiddenImportHeuristic' });\n }\n };\n\n return {\n ImportDeclaration: check,\n ExportNamedDeclaration: check,\n ExportAllDeclaration: check,\n };\n },\n};\n\nexport const noRawEventPublish: ArkRule = {\n meta: {\n type: 'problem',\n docs: {\n description:\n 'Require event bus publish calls to use registered intent creators instead of raw event objects or intent strings.',\n },\n messages: {\n rawPublish:\n 'Publish through a registered intent creator; raw event objects or intent strings bypass Ark contracts.',\n },\n schema: [],\n },\n create(context) {\n return {\n CallExpression(node) {\n if (!isPublishCall(node)) return;\n const firstArg = node.arguments?.[0];\n const firstValue = stringValue(firstArg);\n if ((firstValue && looksLikeIntent(firstValue)) || objectHasProperty(firstArg, 'intent')) {\n context.report({ node, messageId: 'rawPublish' });\n }\n },\n };\n },\n};\n\nexport const requirePublishSource: ArkRule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'Require event bus publish calls to include source metadata.',\n },\n messages: {\n missingSource: 'Strict Ark publish calls must include metadata.source.',\n },\n schema: [],\n },\n create(context) {\n return {\n CallExpression(node) {\n if (!isPublishCall(node)) return;\n const firstArg = node.arguments?.[0];\n const metadataArg = node.arguments?.[2];\n if (objectHasMetadataSource(firstArg) || objectHasProperty(metadataArg, 'source')) {\n return;\n }\n context.report({ node, messageId: 'missingSource' });\n },\n };\n },\n};\n\nexport const noForbiddenGlobals: ArkRule = {\n meta: {\n type: 'problem',\n docs: {\n description:\n 'Disallow ambient globals from the layer’s forbiddenGlobals in ark.config.json (same purity surface as arkgate-check). Option `globals` overrides. Without config, defaults apply only on domain-like paths.',\n },\n messages: {\n forbiddenGlobal:\n 'Ambient global \"{{name}}\" is forbidden in {{layer}} (ark.config.json); inject the capability through a port instead.',\n forbiddenGlobalDefault:\n 'Ambient global \"{{name}}\" is forbidden here; inject the capability through a port instead.',\n },\n schema: [\n {\n type: 'object',\n properties: {\n globals: { type: 'array', items: { type: 'string' } },\n },\n additionalProperties: false,\n },\n ],\n },\n create(context) {\n const filename = lintedFilename(context);\n const option = context.options?.[0] as { globals?: string[] } | undefined;\n const configPath = findConfigPath(filename);\n const config = configPath ? loadArkConfig(configPath) : null;\n const root = configPath ? path.dirname(configPath) : null;\n\n let globals: Set<string> | null = null;\n let layerName = 'this layer';\n\n if (option?.globals) {\n globals = new Set(option.globals);\n } else if (config && root && filename) {\n const absFile = path.isAbsolute(filename) ? filename : path.resolve(filename);\n const relFile = path.relative(root, absFile).split(path.sep).join('/');\n const layer = config.layers?.find(\n (l) => l.name === layerForRelativePath(relFile, config.layers)\n );\n if (layer?.forbiddenGlobals?.length) {\n globals = new Set(layer.forbiddenGlobals);\n layerName = layer.name;\n } else {\n // Layer has no purity list — do not invent defaults (matches CI).\n globals = null;\n }\n } else if (isDomainFileHeuristic(filename)) {\n globals = new Set(DEFAULT_FORBIDDEN_GLOBALS);\n }\n\n if (!globals) {\n return {} as RuleListener;\n }\n\n const report = (node: AstNode, name: string) =>\n context.report({\n node,\n messageId: config ? 'forbiddenGlobal' : 'forbiddenGlobalDefault',\n data: { name, layer: layerName },\n });\n\n return {\n MemberExpression(node) {\n const base = node.object?.type === 'Identifier' ? node.object.name : undefined;\n if (!base) return;\n const dotted = `${base}.${propertyName(node.property) ?? ''}`;\n if (globals!.has(dotted)) report(node, dotted);\n else if (globals!.has(base)) report(node, base);\n },\n CallExpression(node) {\n const callee = node.callee?.type === 'Identifier' ? node.callee.name : undefined;\n if (callee && globals!.has(callee)) report(node, callee);\n },\n NewExpression(node) {\n const callee = node.callee?.type === 'Identifier' ? node.callee.name : undefined;\n if (callee && globals!.has(callee)) report(node, callee);\n },\n };\n },\n};\n\nconst rules = {\n 'no-domain-infra-imports': noDomainInfraImports,\n 'no-raw-event-publish': noRawEventPublish,\n 'require-publish-source': requirePublishSource,\n 'no-forbidden-globals': noForbiddenGlobals,\n};\n\nconst plugin: ArkEslintPlugin = { rules };\n\nplugin.configs = {\n recommended: {\n plugins: { ark: plugin },\n rules: {\n 'ark/no-domain-infra-imports': 'error',\n 'ark/no-raw-event-publish': 'error',\n 'ark/require-publish-source': 'error',\n 'ark/no-forbidden-globals': 'error',\n },\n },\n};\n\nexport { plugin };\nexport default plugin;\n","/**\n * Pure layer-glob matching for ark.config.json.\n *\n * **Canonical algorithm** for CLI, ESLint, and library consumers.\n * The CLI load path uses the generated `bin/ark-layer-match.mjs`\n * (`npm run generate:layer-match` / `npm run check:layer-match`).\n * Behavioral parity tests remain a safety net.\n */\n\nexport type LayerConfig = {\n name: string;\n patterns?: string[];\n exclude?: string[];\n forbiddenGlobals?: string[];\n};\n\n/**\n * Layer-to-layer dependency rule from ark.config.json.\n *\n * - Classic: `{ from, to, allowed: false }` denies **cross-layer** edges only.\n * Same-layer is always allowed without peerIsolation (historical short-circuit).\n * - `peerIsolation: true` + `allowed: false`: deny only when slice ids differ\n * (same **or** cross layer). Same-slice → allow. Needs fromPath/toPath; missing\n * paths/slices → fail-open.\n */\nexport type EdgeRule = {\n from: string;\n to: string;\n allowed?: boolean;\n /**\n * When true with `allowed: false`: deny only when importer and importee resolve\n * to different slice ids (parent/name, e.g. features/auth). Works same-layer\n * and cross-layer. See findDeniedEdgeRule.\n */\n peerIsolation?: boolean;\n /**\n * Path segment names that own the slice id as the *next* segment\n * (e.g. `[\"features\"]` → `src/features/auth/...` has slice `auth`).\n * When omitted, inferred from the layer's glob patterns (segment before `**`/`*`).\n */\n sliceFolders?: string[];\n /** Optional override message for scanners / write-gate. */\n message?: string;\n};\n\n/** Options for path-aware edge checks (peer isolation). */\nexport type EdgeCheckOptions = {\n /** Repo-relative path of the importing file. */\n fromPath?: string;\n /** Repo-relative path of the imported module. */\n toPath?: string;\n /** Layer configs — used to infer sliceFolders when the rule omits them. */\n layers?: LayerConfig[];\n};\n\nconst regexpCache = new Map<string, RegExp>();\n\nfunction escapeLiteral(ch: string): string {\n return /[.*+?^${}()|[\\]\\\\]/.test(ch) ? `\\\\${ch}` : ch;\n}\n\n/**\n * Normalize path separators to `/` without destroying glob escape sequences.\n * `src\\domain\\x` → `src/domain/x` (Windows paths); `src/\\{legacy\\}/**` keeps `\\{` / `\\}`.\n * A plain `pattern.split('\\\\').join('/')` would eat those escapes.\n */\nfunction normalizeGlobSeparators(pattern: string): string {\n let out = '';\n for (let i = 0; i < pattern.length; i += 1) {\n const c = pattern[i];\n if (c === '\\\\' && i + 1 < pattern.length) {\n const next = pattern[i + 1];\n // Keep escapes for glob metacharacters (and escaped backslash).\n if ('*?{}[],'.includes(next) || next === '\\\\') {\n out += '\\\\' + next;\n i += 1;\n continue;\n }\n // Otherwise treat `\\` as a path separator (Windows).\n out += '/';\n continue;\n }\n out += c;\n }\n return out;\n}\n\nfunction bracesBalanced(glob: string): boolean {\n let depth = 0;\n for (let i = 0; i < glob.length; i += 1) {\n const c = glob[i];\n if (c === '\\\\') {\n i += 1;\n continue;\n }\n if (c === '{') depth += 1;\n else if (c === '}') {\n depth -= 1;\n if (depth < 0) return false;\n }\n }\n return depth === 0;\n}\n\nexport function globToRegExp(pattern: string): RegExp {\n const cached = regexpCache.get(pattern);\n if (cached) return cached;\n\n const glob = normalizeGlobSeparators(pattern);\n const useBraces = bracesBalanced(glob);\n let out = '';\n let braceDepth = 0;\n for (let i = 0; i < glob.length; i += 1) {\n const c = glob[i];\n if (c === '\\\\' && i + 1 < glob.length) {\n out += escapeLiteral(glob[i + 1]);\n i += 1;\n } else if (c === '*') {\n if (glob[i + 1] === '*') {\n if (glob[i + 2] === '/') {\n out += '(?:.*/)?';\n i += 2;\n } else {\n out += '.*';\n i += 1;\n }\n } else {\n out += '[^/]*';\n }\n } else if (c === '?') {\n out += '[^/]';\n } else if (c === '{' && useBraces) {\n out += '(?:';\n braceDepth += 1;\n } else if (c === '}' && useBraces && braceDepth > 0) {\n out += ')';\n braceDepth -= 1;\n } else if (c === ',' && useBraces && braceDepth > 0) {\n out += '|';\n } else {\n out += escapeLiteral(c);\n }\n }\n const re = new RegExp(`^${out}$`);\n regexpCache.set(pattern, re);\n return re;\n}\n\nexport function patternSpecificity(pattern: string): number {\n const glob = normalizeGlobSeparators(String(pattern));\n const beforeWildcard = glob.split('*')[0];\n const literalSegments = beforeWildcard.split('/').filter(Boolean).length;\n const literalLength = glob.replace(/\\*/g, '').length;\n return literalSegments * 10000 + literalLength;\n}\n\nexport function layerForRelativePath(\n relPath: string,\n layers: LayerConfig[] | undefined\n): string | undefined {\n // File paths (not globs): any OS separator → posix relative.\n const rel = String(relPath).split(/[/\\\\]/).join('/');\n let bestName: string | undefined;\n let bestScore = -1;\n for (const layer of layers ?? []) {\n if ((layer.exclude ?? []).some((pattern) => globToRegExp(pattern).test(rel))) {\n continue;\n }\n for (const pattern of layer.patterns ?? []) {\n if (globToRegExp(pattern).test(rel)) {\n const score = patternSpecificity(pattern);\n if (score > bestScore) {\n bestScore = score;\n bestName = layer.name;\n }\n }\n }\n }\n return bestName;\n}\n\n/**\n * Extract the slice id under a known folder name.\n * Includes the parent folder so `features/auth` ≠ `modules/auth`.\n * `src/features/auth/api.ts` + folders `[\"features\"]` → `\"features/auth\"`.\n */\nexport function sliceIdForPath(\n relPath: string,\n sliceFolders: string[] | undefined\n): string | undefined {\n if (!sliceFolders?.length) return undefined;\n const parts = String(relPath)\n .split(/[/\\\\]/)\n .filter(Boolean);\n const folders = new Set(sliceFolders.map((s) => String(s).toLowerCase()));\n for (let i = 0; i < parts.length - 1; i += 1) {\n if (folders.has(parts[i].toLowerCase())) {\n return `${parts[i]}/${parts[i + 1]}`;\n }\n }\n return undefined;\n}\n\n/**\n * Infer slice parent folders from layer globs: the path segment immediately\n * before a `*` or `**` wildcard (e.g. `src/features/**` → `features`).\n */\nexport function inferSliceFoldersFromPatterns(\n patterns: string[] | undefined\n): string[] {\n const out = new Set<string>();\n for (const pattern of patterns ?? []) {\n const glob = normalizeGlobSeparators(String(pattern));\n const parts = glob.split('/').filter(Boolean);\n for (let i = 0; i < parts.length; i += 1) {\n const part = parts[i];\n if ((part === '**' || part === '*') && i > 0) {\n const prev = parts[i - 1];\n if (prev && !prev.includes('*') && !prev.includes('{') && !prev.includes('}')) {\n out.add(prev);\n }\n }\n }\n }\n return [...out];\n}\n\nfunction resolveSliceFolders(\n rule: EdgeRule,\n layerName: string,\n layers: LayerConfig[] | undefined\n): string[] {\n if (Array.isArray(rule.sliceFolders) && rule.sliceFolders.length > 0) {\n return rule.sliceFolders.filter((s) => typeof s === 'string' && s.length > 0);\n }\n const layer = (layers ?? []).find((l) => l.name === layerName);\n return inferSliceFoldersFromPatterns(layer?.patterns);\n}\n\n/**\n * Find the first denying rule for a layer edge.\n *\n * Semantics (locked):\n * - Classic (`allowed: false`, no peerIsolation): deny cross-layer edges only.\n * Same-layer is always allowed (historical short-circuit).\n * - `peerIsolation: true` + `allowed: false`: deny only when importer and importee\n * resolve to **different** slice ids (same or cross layer). Same-slice → allow.\n * Missing paths or unclassifiable slices → fail-open (do not deny).\n */\nexport function findDeniedEdgeRule(\n rules: EdgeRule[] | undefined,\n from: string,\n to: string,\n options?: EdgeCheckOptions\n): EdgeRule | undefined {\n for (const rule of rules ?? []) {\n if (rule.from !== from || rule.to !== to) continue;\n if (rule.allowed !== false) continue;\n\n if (rule.peerIsolation) {\n const fromPath = options?.fromPath;\n const toPath = options?.toPath;\n if (!fromPath || !toPath) continue;\n\n const folders = resolveSliceFolders(rule, from, options?.layers);\n if (folders.length === 0) continue;\n\n const fromSlice = sliceIdForPath(fromPath, folders);\n const toSlice = sliceIdForPath(toPath, folders);\n if (!fromSlice || !toSlice) continue;\n if (fromSlice !== toSlice) return rule;\n continue; // same slice: this peerIsolation rule does not deny\n }\n\n // Classic deny — same-layer always allowed without peerIsolation\n if (from === to) continue;\n return rule;\n }\n return undefined;\n}\n\nexport function isEdgeDenied(\n rules: EdgeRule[] | undefined,\n from: string,\n to: string,\n options?: EdgeCheckOptions\n): boolean {\n return findDeniedEdgeRule(rules, from, to, options) !== undefined;\n}\n\n/** Codegen globs skipped by default scan (emitted into the CLI derived matcher). */\nexport const DEFAULT_GENERATED_FILE_GLOBS = [\n '**/*.gen.ts',\n '**/*.gen.tsx',\n '**/*.generated.ts',\n '**/*.generated.tsx',\n];\n\nexport type ScanExcludeConfig = {\n exclude?: string[];\n excludeGenerated?: boolean;\n};\n\nexport function scanExcludePatterns(config?: ScanExcludeConfig | null): string[] {\n const custom = Array.isArray(config?.exclude)\n ? config!.exclude!.filter((p) => typeof p === 'string')\n : [];\n const generated =\n config?.excludeGenerated === false ? [] : DEFAULT_GENERATED_FILE_GLOBS;\n return [...generated, ...custom];\n}\n\nexport function isScanExcludedRelative(\n relPath: string,\n config?: ScanExcludeConfig | null\n): boolean {\n const rel = String(relPath).split(/[/\\\\]/).join('/');\n return scanExcludePatterns(config).some((pattern) => globToRegExp(pattern).test(rel));\n}\n"],"mappings":"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","names":["rules"]}
|
|
1
|
+
{"version":3,"sources":["../../src/eslint/index.ts","../../src/domain/layerMatch.ts","../../src/domain/configContract.ts"],"sourcesContent":["/**\n * arkgate/eslint — editor-side architecture gate.\n *\n * Layer / import / forbidden-globals rules load `ark.config.json` from the linted\n * project (walk-up from the file) and use the same glob specificity + edge semantics\n * as ark-check. Matching primitives come from the canonical\n * `src/domain/layerMatch.ts` (CLI loads the generated `bin/ark-layer-match.mjs`) —\n * no Kernel imports.\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport {\n globToRegExp,\n patternSpecificity,\n layerForRelativePath,\n isEdgeDenied,\n} from '../domain/layerMatch';\nimport { parseArkConfigJson, type ArkConfig } from '../domain/configContract';\n\nexport { globToRegExp, patternSpecificity, layerForRelativePath, isEdgeDenied };\n\ntype RuleContext = {\n report(descriptor: Record<string, unknown>): void;\n /** ESLint 9+ / 10: preferred path on the context object. */\n filename?: string;\n /** ESLint 8-style physical path when linting with processors / virtual files. */\n physicalFilename?: string;\n /** ESLint ≤8 API — still present on some hosts; removed in ESLint 10. */\n getFilename?: () => string;\n /** ESLint 9+ source/scope API. */\n sourceCode?: SourceCode;\n /** ESLint ≤8 source/scope API. */\n getSourceCode?: () => SourceCode;\n options?: unknown[];\n};\n\ntype ScopeVariable = { defs?: unknown[] };\ntype ScopeReference = {\n identifier?: AstNode;\n resolved?: ScopeVariable | null;\n isValueReference?: boolean;\n};\ntype Scope = {\n set?: Map<string, ScopeVariable>;\n references?: ScopeReference[];\n upper?: Scope | null;\n};\ntype SourceCode = { getScope?: (node: AstNode) => Scope };\n\n/** Resolve the file path being linted across ESLint 8–10 context shapes. */\nfunction lintedFilename(context: RuleContext): string {\n if (typeof context.physicalFilename === 'string' && context.physicalFilename.length > 0) {\n return context.physicalFilename;\n }\n if (typeof context.filename === 'string' && context.filename.length > 0) {\n return context.filename;\n }\n if (typeof context.getFilename === 'function') {\n try {\n const name = context.getFilename();\n if (typeof name === 'string' && name.length > 0) return name;\n } catch {\n /* ignore */\n }\n }\n return '';\n}\n\ntype RuleListener = Record<string, (node: AstNode) => void>;\n\ntype AstNode = {\n type?: string;\n name?: string;\n value?: unknown;\n source?: AstNode;\n callee?: AstNode;\n object?: AstNode;\n property?: AstNode;\n key?: AstNode;\n arguments?: AstNode[];\n properties?: AstNode[];\n importKind?: string;\n specifiers?: AstNode[];\n parent?: AstNode;\n init?: AstNode;\n computed?: boolean;\n};\n\ntype ArkRule = {\n meta: {\n type: 'problem';\n docs: { description: string };\n messages: Record<string, string>;\n schema: unknown[];\n };\n create(context: RuleContext): RuleListener;\n};\n\ntype ArkEslintPlugin = {\n rules: Record<string, ArkRule>;\n configs?: Record<string, unknown>;\n};\n\n// ── Config I/O (editor-only; matching primitives come from ark-layer-match.mjs) ──\n\nexport function findConfigPath(startFile: string): string | null {\n if (!startFile || startFile === '<input>' || startFile.startsWith('stdin')) return null;\n let dir = path.dirname(path.resolve(startFile));\n for (;;) {\n const candidate = path.join(dir, 'ark.config.json');\n if (fs.existsSync(candidate)) return candidate;\n const parent = path.dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n}\n\nconst _configCache = new Map<string, ArkConfig | null>();\n\nexport function loadArkConfig(configPath: string): ArkConfig | null {\n if (_configCache.has(configPath)) return _configCache.get(configPath) ?? null;\n if (!fs.existsSync(configPath)) return null;\n const config = parseArkConfigJson(fs.readFileSync(configPath, 'utf8'), configPath).config;\n _configCache.set(configPath, config);\n return config;\n}\n\n/** Resolve relative import specifier to an absolute path candidate (TS-oriented). */\nexport function resolveRelativeImport(fromFile: string, specifier: string): string | null {\n if (!specifier.startsWith('.')) return null;\n const base = path.resolve(path.dirname(fromFile), specifier);\n const candidates = [\n base,\n `${base}.ts`,\n `${base}.tsx`,\n `${base}.mts`,\n `${base}.cts`,\n `${base}.js`,\n `${base}.jsx`,\n path.join(base, 'index.ts'),\n path.join(base, 'index.tsx'),\n path.join(base, 'index.js'),\n ];\n for (const c of candidates) {\n try {\n if (fs.existsSync(c) && fs.statSync(c).isFile()) return c;\n } catch {\n /* continue */\n }\n }\n // Prefer .ts for layer matching when the target is not on disk yet (editor typing).\n return `${base}.ts`;\n}\n\n// ── AST helpers ────────────────────────────────────────────────────────────\n\nfunction stringValue(node: AstNode | undefined): string | undefined {\n return typeof node?.value === 'string' ? node.value : undefined;\n}\n\nfunction propertyName(node: AstNode | undefined): string | undefined {\n return node?.name ?? stringValue(node);\n}\n\nfunction sourceCodeFor(context: RuleContext): SourceCode | undefined {\n return context.sourceCode ?? context.getSourceCode?.();\n}\n\nfunction referenceFor(context: RuleContext, node: AstNode): ScopeReference | undefined {\n let scope = sourceCodeFor(context)?.getScope?.(node);\n while (scope) {\n const reference = scope.references?.find((candidate) => candidate.identifier === node);\n if (reference) return reference;\n scope = scope.upper ?? undefined;\n }\n return undefined;\n}\n\nfunction isLocallyBound(context: RuleContext, node: AstNode, name: string): boolean {\n const reference = referenceFor(context, node);\n if (reference?.resolved) return (reference.resolved.defs?.length ?? 0) > 0;\n\n let scope = sourceCodeFor(context)?.getScope?.(node);\n while (scope) {\n const variable = scope.set?.get(name);\n if (variable) return (variable.defs?.length ?? 0) > 0;\n scope = scope.upper ?? undefined;\n }\n return false;\n}\n\nfunction isValueIdentifierReference(context: RuleContext, node: AstNode): boolean {\n const reference = referenceFor(context, node);\n if (reference) return reference.isValueReference !== false;\n return node.parent?.type === 'VariableDeclarator' && node.parent.init === node;\n}\n\nfunction memberExpressionPath(\n node: AstNode | undefined\n): { root: AstNode; segments: string[] } | undefined {\n if (node?.type === 'Identifier' && node.name) {\n return { root: node, segments: [node.name] };\n }\n if (!node) return undefined;\n const memberLike =\n node.type === 'MemberExpression' || Boolean(node.object && node.property);\n if (!memberLike || node.computed === true) return undefined;\n const base = memberExpressionPath(node.object);\n const property = propertyName(node.property);\n if (!base || !property) return undefined;\n return { root: base.root, segments: [...base.segments, property] };\n}\n\nfunction calleePropertyName(node: AstNode): string | undefined {\n return propertyName(node.callee?.property);\n}\n\nfunction objectProperty(node: AstNode | undefined, name: string): AstNode | undefined {\n return node?.properties?.find((property) => propertyName(property.key) === name);\n}\n\nfunction objectHasProperty(node: AstNode | undefined, name: string): boolean {\n return objectProperty(node, name) !== undefined;\n}\n\nfunction objectHasMetadataSource(node: AstNode | undefined): boolean {\n const metadata = objectProperty(node, 'metadata')?.value as AstNode | undefined;\n return objectHasProperty(metadata, 'source');\n}\n\nfunction looksLikeIntent(value: string): boolean {\n return /^(Domain|Application|Adapter|Workflow|Job|Presentation|Reporting|Metadata|Security|Audit|Observability|Kernel)\\.[A-Za-z0-9_.]+$/.test(\n value\n );\n}\n\nfunction isPublishCall(node: AstNode): boolean {\n return calleePropertyName(node) === 'publish';\n}\n\n/** Heuristic fallback when no ark.config.json (pre-contract projects). */\nfunction isDomainFileHeuristic(filename: string): boolean {\n const normalized = filename.split('\\\\').join('/').toLowerCase();\n return normalized.includes('/domain/') || normalized.endsWith('/domain.ts');\n}\n\nfunction isInfraImportHeuristic(specifier: string): boolean {\n const normalized = specifier.toLowerCase();\n return [\n 'adapter',\n 'adapters',\n 'infrastructure',\n 'persistence',\n 'repository',\n 'repositories',\n 'integration',\n 'database',\n 'db',\n ].some((token) => normalized.includes(token));\n}\n\nconst DEFAULT_FORBIDDEN_GLOBALS = ['fetch', 'process', 'Date.now', 'Math.random'];\n\n// ── Rules ──────────────────────────────────────────────────────────────────\n\n/**\n * Config-driven layer import boundary (primary editor gate).\n * Replaces path-token domain/infra heuristics when ark.config.json is present.\n * Rule id kept as `no-domain-infra-imports` for recommended-config / upgrade stability.\n */\nexport const noDomainInfraImports: ArkRule = {\n meta: {\n type: 'problem',\n docs: {\n description:\n 'Disallow imports that violate ark.config.json layer rules (same contract as arkgate-check). Falls back to domain→infra path heuristics when no config is found.',\n },\n messages: {\n forbiddenImport:\n 'Architecture: {{fromLayer}} must not import {{toLayer}} (ark.config.json). Specifier: {{specifier}}',\n forbiddenImportHeuristic:\n 'Domain code must not import infrastructure, adapters, repositories, or database modules.',\n },\n schema: [],\n },\n create(context) {\n const filename = lintedFilename(context);\n const configPath = findConfigPath(filename);\n const config = configPath ? loadArkConfig(configPath) : null;\n const root = configPath ? path.dirname(configPath) : null;\n\n const check = (node: AstNode) => {\n const source = stringValue(node.source);\n if (!source) return;\n\n if (config && root && filename) {\n const absFile = path.isAbsolute(filename) ? filename : path.resolve(filename);\n const relFile = path.relative(root, absFile).split(path.sep).join('/');\n const fromLayer = layerForRelativePath(relFile, config.layers);\n if (!fromLayer) return;\n\n const targetAbs = resolveRelativeImport(absFile, source);\n if (!targetAbs) return; // package import — CI resolves via TS; editor skips non-relative\n\n const relTarget = path.relative(root, targetAbs).split(path.sep).join('/');\n // Outside project or up-and-out: skip\n if (relTarget.startsWith('..')) return;\n\n const toLayer = layerForRelativePath(relTarget, config.layers);\n if (!toLayer) return;\n if (\n isEdgeDenied(config.rules, fromLayer, toLayer, {\n fromPath: relFile,\n toPath: relTarget,\n layers: config.layers,\n })\n ) {\n context.report({\n node,\n messageId: 'forbiddenImport',\n data: { fromLayer, toLayer, specifier: source },\n });\n }\n return;\n }\n\n // No contract: legacy heuristic so bare domain folders still get a signal.\n if (isDomainFileHeuristic(filename) && isInfraImportHeuristic(source)) {\n context.report({ node, messageId: 'forbiddenImportHeuristic' });\n }\n };\n\n return {\n ImportDeclaration: check,\n ExportNamedDeclaration: check,\n ExportAllDeclaration: check,\n };\n },\n};\n\nexport const noRawEventPublish: ArkRule = {\n meta: {\n type: 'problem',\n docs: {\n description:\n 'Require event bus publish calls to use registered intent creators instead of raw event objects or intent strings.',\n },\n messages: {\n rawPublish:\n 'Publish through a registered intent creator; raw event objects or intent strings bypass Ark contracts.',\n },\n schema: [],\n },\n create(context) {\n return {\n CallExpression(node) {\n if (!isPublishCall(node)) return;\n const firstArg = node.arguments?.[0];\n const firstValue = stringValue(firstArg);\n if ((firstValue && looksLikeIntent(firstValue)) || objectHasProperty(firstArg, 'intent')) {\n context.report({ node, messageId: 'rawPublish' });\n }\n },\n };\n },\n};\n\nexport const requirePublishSource: ArkRule = {\n meta: {\n type: 'problem',\n docs: {\n description: 'Require event bus publish calls to include source metadata.',\n },\n messages: {\n missingSource: 'Strict Ark publish calls must include metadata.source.',\n },\n schema: [],\n },\n create(context) {\n return {\n CallExpression(node) {\n if (!isPublishCall(node)) return;\n const firstArg = node.arguments?.[0];\n const metadataArg = node.arguments?.[2];\n if (objectHasMetadataSource(firstArg) || objectHasProperty(metadataArg, 'source')) {\n return;\n }\n context.report({ node, messageId: 'missingSource' });\n },\n };\n },\n};\n\nexport const noForbiddenGlobals: ArkRule = {\n meta: {\n type: 'problem',\n docs: {\n description:\n 'Disallow ambient globals from the layer’s forbiddenGlobals in ark.config.json (same purity surface as arkgate-check). Option `globals` overrides. Without config, defaults apply only on domain-like paths.',\n },\n messages: {\n forbiddenGlobal:\n 'Ambient global \"{{name}}\" is forbidden in {{layer}} (ark.config.json); inject the capability through a port instead.',\n forbiddenGlobalDefault:\n 'Ambient global \"{{name}}\" is forbidden here; inject the capability through a port instead.',\n },\n schema: [\n {\n type: 'object',\n properties: {\n globals: { type: 'array', items: { type: 'string' } },\n },\n additionalProperties: false,\n },\n ],\n },\n create(context) {\n const filename = lintedFilename(context);\n const option = context.options?.[0] as { globals?: string[] } | undefined;\n const configPath = findConfigPath(filename);\n const config = configPath ? loadArkConfig(configPath) : null;\n const root = configPath ? path.dirname(configPath) : null;\n\n let globals: Set<string> | null = null;\n let layerName = 'this layer';\n\n if (option?.globals) {\n globals = new Set(option.globals);\n } else if (config && root && filename) {\n const absFile = path.isAbsolute(filename) ? filename : path.resolve(filename);\n const relFile = path.relative(root, absFile).split(path.sep).join('/');\n const layer = config.layers?.find(\n (l) => l.name === layerForRelativePath(relFile, config.layers)\n );\n if (layer?.forbiddenGlobals?.length) {\n globals = new Set(layer.forbiddenGlobals);\n layerName = layer.name;\n } else {\n // Layer has no purity list — do not invent defaults (matches CI).\n globals = null;\n }\n } else if (isDomainFileHeuristic(filename)) {\n globals = new Set(DEFAULT_FORBIDDEN_GLOBALS);\n }\n\n if (!globals) {\n return {} as RuleListener;\n }\n\n const scopeAware = typeof sourceCodeFor(context)?.getScope === 'function';\n\n const report = (node: AstNode, name: string) =>\n context.report({\n node,\n messageId: config ? 'forbiddenGlobal' : 'forbiddenGlobalDefault',\n data: { name, layer: layerName },\n });\n\n return {\n MemberExpression(node) {\n if (node.parent?.type === 'MemberExpression' && node.parent.object === node) return;\n const path = memberExpressionPath(node);\n if (!path || isLocallyBound(context, path.root, path.segments[0])) return;\n const explicitGlobalThis = path.segments[0] === 'globalThis';\n const normalized = explicitGlobalThis ? path.segments.slice(1) : path.segments;\n let match: string | undefined;\n for (let length = normalized.length; length >= (explicitGlobalThis ? 1 : 2); length -= 1) {\n const candidate = normalized.slice(0, length).join('.');\n if (globals!.has(candidate)) {\n match = candidate;\n break;\n }\n }\n if (match) report(node, match);\n else if (!scopeAware && globals!.has(path.segments[0])) {\n report(node, path.segments[0]);\n }\n },\n CallExpression(node) {\n if (scopeAware) return;\n const callee = node.callee?.type === 'Identifier' ? node.callee.name : undefined;\n if (callee && globals!.has(callee)) report(node, callee);\n },\n NewExpression(node) {\n if (scopeAware) return;\n const callee = node.callee?.type === 'Identifier' ? node.callee.name : undefined;\n if (callee && globals!.has(callee)) report(node, callee);\n },\n Identifier(node) {\n if (\n !scopeAware ||\n !node.name ||\n !globals!.has(node.name) ||\n !isValueIdentifierReference(context, node) ||\n isLocallyBound(context, node, node.name)\n ) {\n return;\n }\n report(node, node.name);\n },\n };\n },\n};\n\nconst rules = {\n 'no-domain-infra-imports': noDomainInfraImports,\n 'no-raw-event-publish': noRawEventPublish,\n 'require-publish-source': requirePublishSource,\n 'no-forbidden-globals': noForbiddenGlobals,\n};\n\nconst plugin: ArkEslintPlugin = { rules };\n\nplugin.configs = {\n recommended: {\n plugins: { ark: plugin },\n rules: {\n 'ark/no-domain-infra-imports': 'error',\n 'ark/no-raw-event-publish': 'error',\n 'ark/require-publish-source': 'error',\n 'ark/no-forbidden-globals': 'error',\n },\n },\n};\n\nexport { plugin };\nexport default plugin;\n","/**\n * Pure layer-glob matching for ark.config.json.\n *\n * **Canonical algorithm** for CLI, ESLint, and library consumers.\n * The CLI load path uses the generated `bin/ark-layer-match.mjs`\n * (`npm run generate:layer-match` / `npm run check:layer-match`).\n * Behavioral parity tests remain a safety net.\n */\n\nexport type LayerConfig = {\n name: string;\n patterns?: string[];\n exclude?: string[];\n forbiddenGlobals?: string[];\n};\n\n/**\n * Layer-to-layer dependency rule from ark.config.json.\n *\n * - Classic: `{ from, to, allowed: false }` denies **cross-layer** edges only.\n * Same-layer is always allowed without peerIsolation (historical short-circuit).\n * - `peerIsolation: true` + `allowed: false`: deny only when slice ids differ\n * (same **or** cross layer). Same-slice → allow. Needs fromPath/toPath; missing\n * paths/slices → fail-open.\n */\nexport type EdgeRule = {\n from: string;\n to: string;\n allowed?: boolean;\n /**\n * When true with `allowed: false`: deny only when importer and importee resolve\n * to different slice ids (parent/name, e.g. features/auth). Works same-layer\n * and cross-layer. See findDeniedEdgeRule.\n */\n peerIsolation?: boolean;\n /**\n * Path segment names that own the slice id as the *next* segment\n * (e.g. `[\"features\"]` → `src/features/auth/...` has slice `auth`).\n * When omitted, inferred from the layer's glob patterns (segment before `**`/`*`).\n */\n sliceFolders?: string[];\n /** Optional override message for scanners / write-gate. */\n message?: string;\n};\n\n/** Options for path-aware edge checks (peer isolation). */\nexport type EdgeCheckOptions = {\n /** Repo-relative path of the importing file. */\n fromPath?: string;\n /** Repo-relative path of the imported module. */\n toPath?: string;\n /** Layer configs — used to infer sliceFolders when the rule omits them. */\n layers?: LayerConfig[];\n};\n\nconst regexpCache = new Map<string, RegExp>();\n\nfunction escapeLiteral(ch: string): string {\n return /[.*+?^${}()|[\\]\\\\]/.test(ch) ? `\\\\${ch}` : ch;\n}\n\n/**\n * Normalize path separators to `/` without destroying glob escape sequences.\n * `src\\domain\\x` → `src/domain/x` (Windows paths); `src/\\{legacy\\}/**` keeps `\\{` / `\\}`.\n * A plain `pattern.split('\\\\').join('/')` would eat those escapes.\n */\nfunction normalizeGlobSeparators(pattern: string): string {\n let out = '';\n for (let i = 0; i < pattern.length; i += 1) {\n const c = pattern[i];\n if (c === '\\\\' && i + 1 < pattern.length) {\n const next = pattern[i + 1];\n // Keep escapes for glob metacharacters (and escaped backslash).\n if ('*?{}[],'.includes(next) || next === '\\\\') {\n out += '\\\\' + next;\n i += 1;\n continue;\n }\n // Otherwise treat `\\` as a path separator (Windows).\n out += '/';\n continue;\n }\n out += c;\n }\n return out;\n}\n\nfunction bracesBalanced(glob: string): boolean {\n let depth = 0;\n for (let i = 0; i < glob.length; i += 1) {\n const c = glob[i];\n if (c === '\\\\') {\n i += 1;\n continue;\n }\n if (c === '{') depth += 1;\n else if (c === '}') {\n depth -= 1;\n if (depth < 0) return false;\n }\n }\n return depth === 0;\n}\n\nexport function globToRegExp(pattern: string): RegExp {\n const cached = regexpCache.get(pattern);\n if (cached) return cached;\n\n const glob = normalizeGlobSeparators(pattern);\n const useBraces = bracesBalanced(glob);\n let out = '';\n let braceDepth = 0;\n for (let i = 0; i < glob.length; i += 1) {\n const c = glob[i];\n if (c === '\\\\' && i + 1 < glob.length) {\n out += escapeLiteral(glob[i + 1]);\n i += 1;\n } else if (c === '*') {\n if (glob[i + 1] === '*') {\n if (glob[i + 2] === '/') {\n out += '(?:.*/)?';\n i += 2;\n } else {\n out += '.*';\n i += 1;\n }\n } else {\n out += '[^/]*';\n }\n } else if (c === '?') {\n out += '[^/]';\n } else if (c === '{' && useBraces) {\n out += '(?:';\n braceDepth += 1;\n } else if (c === '}' && useBraces && braceDepth > 0) {\n out += ')';\n braceDepth -= 1;\n } else if (c === ',' && useBraces && braceDepth > 0) {\n out += '|';\n } else {\n out += escapeLiteral(c);\n }\n }\n const re = new RegExp(`^${out}$`);\n regexpCache.set(pattern, re);\n return re;\n}\n\nexport function patternSpecificity(pattern: string): number {\n const glob = normalizeGlobSeparators(String(pattern));\n const beforeWildcard = glob.split('*')[0];\n const literalSegments = beforeWildcard.split('/').filter(Boolean).length;\n const literalLength = glob.replace(/\\*/g, '').length;\n return literalSegments * 10000 + literalLength;\n}\n\nexport function layerForRelativePath(\n relPath: string,\n layers: LayerConfig[] | undefined\n): string | undefined {\n // File paths (not globs): any OS separator → posix relative.\n const rel = String(relPath).split(/[/\\\\]/).join('/');\n let bestName: string | undefined;\n let bestScore = -1;\n for (const layer of layers ?? []) {\n if ((layer.exclude ?? []).some((pattern) => globToRegExp(pattern).test(rel))) {\n continue;\n }\n for (const pattern of layer.patterns ?? []) {\n if (globToRegExp(pattern).test(rel)) {\n const score = patternSpecificity(pattern);\n if (score > bestScore) {\n bestScore = score;\n bestName = layer.name;\n }\n }\n }\n }\n return bestName;\n}\n\n/**\n * Extract the slice id under a known folder name.\n * Includes the parent folder so `features/auth` ≠ `modules/auth`.\n * `src/features/auth/api.ts` + folders `[\"features\"]` → `\"features/auth\"`.\n */\nexport function sliceIdForPath(\n relPath: string,\n sliceFolders: string[] | undefined\n): string | undefined {\n if (!sliceFolders?.length) return undefined;\n const parts = String(relPath)\n .split(/[/\\\\]/)\n .filter(Boolean);\n const folders = new Set(sliceFolders.map((s) => String(s).toLowerCase()));\n for (let i = 0; i < parts.length - 1; i += 1) {\n if (folders.has(parts[i].toLowerCase())) {\n return `${parts[i]}/${parts[i + 1]}`;\n }\n }\n return undefined;\n}\n\n/**\n * Infer slice parent folders from layer globs: the path segment immediately\n * before a `*` or `**` wildcard (e.g. `src/features/**` → `features`).\n */\nexport function inferSliceFoldersFromPatterns(\n patterns: string[] | undefined\n): string[] {\n const out = new Set<string>();\n for (const pattern of patterns ?? []) {\n const glob = normalizeGlobSeparators(String(pattern));\n const parts = glob.split('/').filter(Boolean);\n for (let i = 0; i < parts.length; i += 1) {\n const part = parts[i];\n if ((part === '**' || part === '*') && i > 0) {\n const prev = parts[i - 1];\n if (prev && !prev.includes('*') && !prev.includes('{') && !prev.includes('}')) {\n out.add(prev);\n }\n }\n }\n }\n return [...out];\n}\n\nfunction resolveSliceFolders(\n rule: EdgeRule,\n layerName: string,\n layers: LayerConfig[] | undefined\n): string[] {\n if (Array.isArray(rule.sliceFolders) && rule.sliceFolders.length > 0) {\n return rule.sliceFolders.filter((s) => typeof s === 'string' && s.length > 0);\n }\n const layer = (layers ?? []).find((l) => l.name === layerName);\n return inferSliceFoldersFromPatterns(layer?.patterns);\n}\n\n/**\n * Find the first denying rule for a layer edge.\n *\n * Semantics (locked):\n * - Classic (`allowed: false`, no peerIsolation): deny cross-layer edges only.\n * Same-layer is always allowed (historical short-circuit).\n * - `peerIsolation: true` + `allowed: false`: deny only when importer and importee\n * resolve to **different** slice ids (same or cross layer). Same-slice → allow.\n * Missing paths or unclassifiable slices → fail-open (do not deny).\n */\nexport function findDeniedEdgeRule(\n rules: EdgeRule[] | undefined,\n from: string,\n to: string,\n options?: EdgeCheckOptions\n): EdgeRule | undefined {\n for (const rule of rules ?? []) {\n if (rule.from !== from || rule.to !== to) continue;\n if (rule.allowed !== false) continue;\n\n if (rule.peerIsolation) {\n const fromPath = options?.fromPath;\n const toPath = options?.toPath;\n if (!fromPath || !toPath) continue;\n\n const folders = resolveSliceFolders(rule, from, options?.layers);\n if (folders.length === 0) continue;\n\n const fromSlice = sliceIdForPath(fromPath, folders);\n const toSlice = sliceIdForPath(toPath, folders);\n if (!fromSlice || !toSlice) continue;\n if (fromSlice !== toSlice) return rule;\n continue; // same slice: this peerIsolation rule does not deny\n }\n\n // Classic deny — same-layer always allowed without peerIsolation\n if (from === to) continue;\n return rule;\n }\n return undefined;\n}\n\nexport function isEdgeDenied(\n rules: EdgeRule[] | undefined,\n from: string,\n to: string,\n options?: EdgeCheckOptions\n): boolean {\n return findDeniedEdgeRule(rules, from, to, options) !== undefined;\n}\n\n/** Codegen globs skipped by default scan (emitted into the CLI derived matcher). */\nexport const DEFAULT_GENERATED_FILE_GLOBS = [\n '**/*.gen.ts',\n '**/*.gen.tsx',\n '**/*.generated.ts',\n '**/*.generated.tsx',\n];\n\nexport type ScanExcludeConfig = {\n exclude?: string[];\n excludeGenerated?: boolean;\n};\n\nexport function scanExcludePatterns(config?: ScanExcludeConfig | null): string[] {\n const custom = Array.isArray(config?.exclude)\n ? config!.exclude!.filter((p) => typeof p === 'string')\n : [];\n const generated =\n config?.excludeGenerated === false ? [] : DEFAULT_GENERATED_FILE_GLOBS;\n return [...generated, ...custom];\n}\n\nexport function isScanExcludedRelative(\n relPath: string,\n config?: ScanExcludeConfig | null\n): boolean {\n const rel = String(relPath).split(/[/\\\\]/).join('/');\n return scanExcludePatterns(config).some((pattern) => globToRegExp(pattern).test(rel));\n}\n","/**\n * Canonical, pure contract for ark.config.json.\n *\n * Tooling adapters own filesystem I/O; this module owns JSON parsing, deterministic\n * migration, defaults, validation, diagnostics, and the published JSON Schema.\n * The standalone CLI artifact is generated into bin/lib/config-contract.mjs.\n */\n\nexport const ARK_CONFIG_SCHEMA_VERSION = '1.0' as const;\nexport const ARK_CONFIG_SCHEMA_URL =\n 'https://unpkg.com/arkgate@2/schemas/ark.config.schema.json';\n\nexport type ArkConfigCyclePolicy = 'strict' | 'soft' | 'framework-soft' | 'off';\n\nexport type ArkConfigLayer = {\n name: string;\n patterns: string[];\n exclude?: string[];\n intentPrefixes?: string[];\n description?: string;\n forbiddenGlobals?: string[];\n mayImportInfrastructure?: boolean;\n optional?: boolean;\n};\n\nexport type ArkConfigRule = {\n from: string;\n to: string;\n allowed: boolean;\n message?: string;\n peerIsolation?: boolean;\n sliceFolders?: string[];\n};\n\nexport type ArkConfigSafety = {\n maxTsSuppressions?: number;\n maxAnyCasts?: number;\n allowInMemory?: boolean;\n allowDisabledPeerIsolation?: boolean;\n};\n\nexport type ArkConfig = {\n $schema: string;\n schemaVersion: typeof ARK_CONFIG_SCHEMA_VERSION;\n name?: string;\n include: string[];\n exclude?: string[];\n excludeGenerated?: boolean;\n frameworkOverlay?: string;\n layers: ArkConfigLayer[];\n rules: ArkConfigRule[];\n cyclePolicy?: ArkConfigCyclePolicy;\n dynamicImportAllowlist?: string[];\n safety?: ArkConfigSafety;\n};\n\nconst DEFAULT_LAYER_NAMES = [\n 'DomainModel',\n 'ApplicationOrchestration',\n 'PersistenceAdapters',\n 'IntegrationAdapters',\n 'WorkflowSagaEngine',\n 'BackgroundJobsScheduling',\n 'PresentationAdapters',\n 'ReportingReadModels',\n 'ExtensibilityMetadata',\n 'SecurityAuditObservability',\n 'Kernel',\n] as const;\n\nconst DEFAULT_ALLOWED_FLOWS = new Set([\n 'PresentationAdapters->ApplicationOrchestration',\n 'ApplicationOrchestration->DomainModel',\n 'WorkflowSagaEngine->ApplicationOrchestration',\n 'WorkflowSagaEngine->DomainModel',\n 'BackgroundJobsScheduling->ApplicationOrchestration',\n]);\n\nfunction createDefaultRules(): ArkConfigRule[] {\n const rules: ArkConfigRule[] = [];\n for (const from of DEFAULT_LAYER_NAMES) {\n for (const to of DEFAULT_LAYER_NAMES) {\n if (from === to || DEFAULT_ALLOWED_FLOWS.has(`${from}->${to}`)) continue;\n rules.push({ from, to, allowed: false });\n }\n }\n return rules;\n}\n\nexport const DEFAULT_ARK_CONFIG_RULES = createDefaultRules();\n\nexport const ARK_CONFIG_MIGRATIONS = [\n { from: 'unversioned', to: ARK_CONFIG_SCHEMA_VERSION },\n] as const;\n\nconst stringArraySchema = {\n type: 'array',\n items: { type: 'string', minLength: 1 },\n uniqueItems: true,\n} as const;\n\nexport const ARK_CONFIG_SCHEMA = {\n $schema: 'https://json-schema.org/draft/2020-12/schema',\n $id: ARK_CONFIG_SCHEMA_URL,\n title: 'ArkGate architecture contract',\n description: 'Versioned contract consumed identically by ArkGate CLI, MCP, and ESLint surfaces.',\n type: 'object',\n additionalProperties: false,\n required: ['$schema', 'schemaVersion', 'include', 'layers', 'rules'],\n properties: {\n $schema: {\n type: 'string',\n minLength: 1,\n default: ARK_CONFIG_SCHEMA_URL,\n description: 'Editor-facing URL or local path for this JSON Schema.',\n },\n schemaVersion: {\n type: 'string',\n const: ARK_CONFIG_SCHEMA_VERSION,\n default: ARK_CONFIG_SCHEMA_VERSION,\n },\n name: { type: 'string', minLength: 1 },\n include: { ...stringArraySchema, minItems: 1, default: ['src'] },\n exclude: { ...stringArraySchema, default: [] },\n excludeGenerated: { type: 'boolean', default: true },\n frameworkOverlay: { type: 'string', minLength: 1 },\n layers: {\n type: 'array',\n default: [],\n items: { $ref: '#/$defs/layer' },\n },\n rules: {\n type: 'array',\n default: DEFAULT_ARK_CONFIG_RULES,\n items: { $ref: '#/$defs/rule' },\n },\n cyclePolicy: {\n type: 'string',\n enum: ['strict', 'soft', 'framework-soft', 'off'],\n default: 'strict',\n },\n dynamicImportAllowlist: { ...stringArraySchema, default: [] },\n safety: {\n $ref: '#/$defs/safety',\n default: {\n maxTsSuppressions: 0,\n maxAnyCasts: 0,\n allowInMemory: false,\n allowDisabledPeerIsolation: false,\n },\n },\n },\n $defs: {\n layer: {\n type: 'object',\n additionalProperties: false,\n required: ['name', 'patterns'],\n properties: {\n name: { type: 'string', minLength: 1 },\n patterns: { ...stringArraySchema, minItems: 1 },\n exclude: stringArraySchema,\n intentPrefixes: stringArraySchema,\n description: { type: 'string', minLength: 1 },\n forbiddenGlobals: stringArraySchema,\n mayImportInfrastructure: { type: 'boolean' },\n optional: { type: 'boolean' },\n },\n },\n rule: {\n type: 'object',\n additionalProperties: false,\n required: ['from', 'to', 'allowed'],\n properties: {\n from: { type: 'string', minLength: 1 },\n to: { type: 'string', minLength: 1 },\n allowed: { type: 'boolean' },\n message: { type: 'string', minLength: 1 },\n peerIsolation: { type: 'boolean' },\n sliceFolders: { ...stringArraySchema, minItems: 1 },\n },\n },\n safety: {\n type: 'object',\n additionalProperties: false,\n properties: {\n maxTsSuppressions: { type: 'integer', minimum: 0, default: 0 },\n maxAnyCasts: { type: 'integer', minimum: 0, default: 0 },\n allowInMemory: { type: 'boolean', default: false },\n allowDisabledPeerIsolation: { type: 'boolean', default: false },\n },\n },\n },\n} as const;\n\ntype SchemaNode = {\n $ref?: string;\n type?: 'object' | 'array' | 'string' | 'boolean' | 'integer';\n const?: unknown;\n enum?: readonly unknown[];\n required?: readonly string[];\n properties?: Readonly<Record<string, SchemaNode>>;\n additionalProperties?: boolean;\n items?: SchemaNode;\n minItems?: number;\n uniqueItems?: boolean;\n minLength?: number;\n minimum?: number;\n default?: unknown;\n};\n\ntype SchemaRoot = SchemaNode & {\n $defs: Readonly<Record<string, SchemaNode>>;\n};\n\nexport type ArkConfigIssue = {\n path: string;\n message: string;\n};\n\nexport class ArkConfigValidationError extends Error {\n readonly issues: ArkConfigIssue[];\n readonly source: string;\n\n constructor(source: string, issues: ArkConfigIssue[]) {\n super(\n `Invalid ArkGate config (${source}):\\n${issues\n .map((issue) => `- ${issue.path}: ${issue.message}`)\n .join('\\n')}`\n );\n this.name = 'ArkConfigValidationError';\n this.source = source;\n this.issues = issues;\n }\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction propertyPath(parent: string, key: string): string {\n return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)\n ? `${parent}.${key}`\n : `${parent}[${JSON.stringify(key)}]`;\n}\n\nfunction valueType(value: unknown): string {\n if (value === null) return 'null';\n if (Array.isArray(value)) return 'array';\n return typeof value;\n}\n\nfunction resolveSchemaRef(ref: string, root: SchemaRoot): SchemaNode | undefined {\n const prefix = '#/$defs/';\n if (!ref.startsWith(prefix)) return undefined;\n return root.$defs[ref.slice(prefix.length)];\n}\n\nfunction validateNode(\n value: unknown,\n schema: SchemaNode,\n path: string,\n root: SchemaRoot,\n issues: ArkConfigIssue[]\n): void {\n if (schema.$ref) {\n const referenced = resolveSchemaRef(schema.$ref, root);\n if (!referenced) {\n issues.push({ path, message: `schema reference ${schema.$ref} cannot be resolved` });\n return;\n }\n validateNode(value, referenced, path, root, issues);\n return;\n }\n\n if (schema.const !== undefined && !Object.is(value, schema.const)) {\n issues.push({ path, message: `must equal ${JSON.stringify(schema.const)}` });\n return;\n }\n if (schema.enum && !schema.enum.some((candidate) => Object.is(candidate, value))) {\n issues.push({ path, message: `must be one of ${schema.enum.map(String).join(', ')}` });\n return;\n }\n\n if (schema.type === 'object') {\n if (!isObject(value)) {\n issues.push({ path, message: `must be an object; received ${valueType(value)}` });\n return;\n }\n const properties = schema.properties ?? {};\n for (const key of schema.required ?? []) {\n if (value[key] === undefined) {\n issues.push({ path: propertyPath(path, key), message: 'is required' });\n }\n }\n if (schema.additionalProperties === false) {\n for (const key of Object.keys(value)) {\n if (!(key in properties)) {\n issues.push({ path: propertyPath(path, key), message: 'unknown field' });\n }\n }\n }\n for (const [key, childSchema] of Object.entries(properties)) {\n if (value[key] !== undefined) {\n validateNode(value[key], childSchema, propertyPath(path, key), root, issues);\n }\n }\n return;\n }\n\n if (schema.type === 'array') {\n if (!Array.isArray(value)) {\n issues.push({ path, message: `must be an array; received ${valueType(value)}` });\n return;\n }\n if (schema.minItems !== undefined && value.length < schema.minItems) {\n issues.push({ path, message: `must contain at least ${schema.minItems} item(s)` });\n }\n if (schema.uniqueItems) {\n const serialized = value.map((entry) => JSON.stringify(entry));\n if (new Set(serialized).size !== serialized.length) {\n issues.push({ path, message: 'must not contain duplicate items' });\n }\n }\n if (schema.items) {\n value.forEach((entry, index) =>\n validateNode(entry, schema.items!, `${path}[${index}]`, root, issues)\n );\n }\n return;\n }\n\n if (schema.type === 'string') {\n if (typeof value !== 'string') {\n issues.push({ path, message: `must be a string; received ${valueType(value)}` });\n return;\n }\n if (schema.minLength !== undefined && value.length < schema.minLength) {\n issues.push({ path, message: `must contain at least ${schema.minLength} character(s)` });\n }\n return;\n }\n\n if (schema.type === 'boolean') {\n if (typeof value !== 'boolean') {\n issues.push({ path, message: `must be a boolean; received ${valueType(value)}` });\n }\n return;\n }\n\n if (schema.type === 'integer') {\n if (!Number.isInteger(value)) {\n issues.push({ path, message: `must be an integer; received ${valueType(value)}` });\n return;\n }\n if (schema.minimum !== undefined && (value as number) < schema.minimum) {\n issues.push({ path, message: `must be at least ${schema.minimum}` });\n }\n }\n}\n\nfunction defaultedConfig(input: Record<string, unknown>): Record<string, unknown> {\n return {\n ...input,\n $schema: input.$schema === undefined ? ARK_CONFIG_SCHEMA_URL : input.$schema,\n schemaVersion:\n input.schemaVersion === undefined ? ARK_CONFIG_SCHEMA_VERSION : input.schemaVersion,\n include: input.include === undefined ? ['src'] : input.include,\n layers: input.layers === undefined ? [] : input.layers,\n rules:\n input.rules === undefined\n ? DEFAULT_ARK_CONFIG_RULES.map((rule) => ({ ...rule }))\n : input.rules,\n };\n}\n\nexport type ArkConfigLoadResult = {\n config: ArkConfig;\n migratedFrom: 'unversioned' | null;\n};\n\nexport type ArkConfigMigrationResult = {\n candidate: Record<string, unknown>;\n migratedFrom: 'unversioned' | null;\n};\n\nexport function migrateArkConfig(\n input: unknown,\n source = 'ark.config.json'\n): ArkConfigMigrationResult {\n if (!isObject(input)) {\n throw new ArkConfigValidationError(source, [\n { path: '$', message: `must be an object; received ${valueType(input)}` },\n ]);\n }\n\n const migratedFrom = input.schemaVersion === undefined ? 'unversioned' : null;\n if (\n input.schemaVersion !== undefined &&\n input.schemaVersion !== ARK_CONFIG_SCHEMA_VERSION\n ) {\n throw new ArkConfigValidationError(source, [\n {\n path: '$.schemaVersion',\n message: `unsupported version ${JSON.stringify(input.schemaVersion)}; expected ${ARK_CONFIG_SCHEMA_VERSION}`,\n },\n ]);\n }\n\n return { candidate: defaultedConfig(input), migratedFrom };\n}\n\nexport function loadArkConfigContract(\n input: unknown,\n source = 'ark.config.json'\n): ArkConfigLoadResult {\n const { candidate, migratedFrom } = migrateArkConfig(input, source);\n const issues: ArkConfigIssue[] = [];\n validateNode(\n candidate,\n ARK_CONFIG_SCHEMA as unknown as SchemaRoot,\n '$',\n ARK_CONFIG_SCHEMA as unknown as SchemaRoot,\n issues\n );\n if (issues.length > 0) throw new ArkConfigValidationError(source, issues);\n\n return { config: candidate as ArkConfig, migratedFrom };\n}\n\nexport function parseArkConfigJson(\n json: string,\n source = 'ark.config.json'\n): ArkConfigLoadResult {\n let input: unknown;\n try {\n input = JSON.parse(json);\n } catch (error) {\n throw new ArkConfigValidationError(source, [\n {\n path: '$',\n message: `invalid JSON: ${error instanceof Error ? error.message : String(error)}`,\n },\n ]);\n }\n return loadArkConfigContract(input, source);\n}\n\nexport function withArkConfigMetadata<T extends Record<string, unknown>>(\n config: T\n): T & Pick<ArkConfig, '$schema' | 'schemaVersion'> {\n const result: Record<string, unknown> = {\n $schema:\n typeof config.$schema === 'string' && config.$schema.length > 0\n ? config.$schema\n : ARK_CONFIG_SCHEMA_URL,\n schemaVersion: ARK_CONFIG_SCHEMA_VERSION,\n };\n for (const [key, value] of Object.entries(config)) {\n if (key !== '$schema' && key !== 'schemaVersion') result[key] = value;\n }\n return result as T & Pick<ArkConfig, '$schema' | 'schemaVersion'>;\n}\n"],"mappings":"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","names":["rules","rules","path","path"]}
|