@fulmenhq/tsfulmen 0.2.0 → 0.2.3
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 +70 -0
- package/README.md +61 -7
- package/config/crucible-ts/agentic/roles/README.md +3 -3
- package/config/crucible-ts/library/fulencode/fixtures/README.md +18 -0
- package/config/crucible-ts/library/fulencode/fixtures/bom/bom.yaml +14 -0
- package/config/crucible-ts/library/fulencode/fixtures/detection/detection.yaml +12 -0
- package/config/crucible-ts/library/fulencode/fixtures/invalid-encodings/base64.yaml +10 -0
- package/config/crucible-ts/library/fulencode/fixtures/normalization/text-safe.yaml +10 -0
- package/config/crucible-ts/library/fulencode/fixtures/telemetry/telemetry-test-cases.yaml +24 -0
- package/config/crucible-ts/library/fulencode/fixtures/valid-encodings/base64.yaml +11 -0
- package/config/crucible-ts/taxonomy/library/platform-modules/v1.0.0/modules.yaml +2 -2
- package/config/crucible-ts/taxonomy/metrics.yaml +79 -1
- package/dist/appidentity/index.d.ts +31 -109
- package/dist/appidentity/index.js +369 -60
- package/dist/appidentity/index.js.map +1 -1
- package/dist/config/index.d.ts +46 -1
- package/dist/config/index.js +427 -62
- package/dist/config/index.js.map +1 -1
- package/dist/crucible/index.js +367 -59
- package/dist/crucible/index.js.map +1 -1
- package/dist/errors/index.d.ts +1 -1
- package/dist/errors/index.js +367 -59
- package/dist/errors/index.js.map +1 -1
- package/dist/foundry/index.d.ts +2 -1
- package/dist/foundry/index.js +368 -60
- package/dist/foundry/index.js.map +1 -1
- package/dist/fulencode/index.d.ts +102 -0
- package/dist/fulencode/index.js +806 -0
- package/dist/fulencode/index.js.map +1 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.js +370 -61
- package/dist/index.js.map +1 -1
- package/dist/pathfinder/index.d.ts +1 -1
- package/dist/pathfinder/index.js +367 -59
- package/dist/pathfinder/index.js.map +1 -1
- package/dist/reports/license-inventory.csv +31 -24
- package/dist/schema/index.d.ts +16 -3
- package/dist/schema/index.js +368 -60
- package/dist/schema/index.js.map +1 -1
- package/dist/signals/index.d.ts +483 -395
- package/dist/signals/index.js +368 -60
- package/dist/signals/index.js.map +1 -1
- package/dist/telemetry/http/index.js +368 -59
- package/dist/telemetry/http/index.js.map +1 -1
- package/dist/telemetry/index.d.ts +1 -1
- package/dist/telemetry/index.js +367 -59
- package/dist/telemetry/index.js.map +1 -1
- package/dist/telemetry/prometheus/index.d.ts +1 -1
- package/dist/telemetry/prometheus/index.js +369 -59
- package/dist/telemetry/prometheus/index.js.map +1 -1
- package/dist/{types-BJswWpQC.d.ts → types-DdoeE7F5.d.ts} +1 -1
- package/dist/types-Dv5TERCM.d.ts +108 -0
- package/package.json +13 -8
- package/schemas/crucible-ts/library/fulencode/v1.0.0/README.md +37 -0
- package/schemas/crucible-ts/library/fulencode/v1.0.0/bom-result.schema.json +48 -0
- package/schemas/crucible-ts/library/fulencode/v1.0.0/decode-options.schema.json +60 -0
- package/schemas/crucible-ts/library/fulencode/v1.0.0/decoding-result.schema.json +70 -0
- package/schemas/crucible-ts/library/fulencode/v1.0.0/detect-options.schema.json +25 -0
- package/schemas/crucible-ts/library/fulencode/v1.0.0/detection-result.schema.json +57 -0
- package/schemas/crucible-ts/library/fulencode/v1.0.0/encode-options.schema.json +71 -0
- package/schemas/crucible-ts/library/fulencode/v1.0.0/encoding-result.schema.json +57 -0
- package/schemas/crucible-ts/library/fulencode/v1.0.0/fulencode-config.schema.json +8 -4
- package/schemas/crucible-ts/library/fulencode/v1.0.0/fulencode-error.schema.json +66 -0
- package/schemas/crucible-ts/library/fulencode/v1.0.0/normalization-result.schema.json +73 -0
- package/schemas/crucible-ts/library/fulencode/v1.0.0/normalize-options.schema.json +44 -0
- package/schemas/crucible-ts/meta/README.md +38 -2
- package/schemas/crucible-ts/meta/draft-04/schema.json +222 -0
- package/schemas/crucible-ts/meta/draft-06/schema.json +218 -0
- package/schemas/crucible-ts/meta/draft-2019-09/meta/applicator.json +93 -0
- package/schemas/crucible-ts/meta/draft-2019-09/meta/content.json +21 -0
- package/schemas/crucible-ts/meta/draft-2019-09/meta/core.json +58 -0
- package/schemas/crucible-ts/meta/draft-2019-09/meta/format.json +15 -0
- package/schemas/crucible-ts/meta/draft-2019-09/meta/meta-data.json +35 -0
- package/schemas/crucible-ts/meta/draft-2019-09/meta/validation.json +119 -0
- package/schemas/crucible-ts/meta/draft-2019-09/offline.schema.json +148 -0
- package/schemas/crucible-ts/meta/draft-2019-09/schema.json +62 -0
- package/schemas/crucible-ts/meta/fixtures/draft-04-sample.json +16 -0
- package/schemas/crucible-ts/meta/fixtures/draft-06-sample.json +16 -0
- package/schemas/crucible-ts/meta/fixtures/draft-07-sample.json +34 -0
- package/schemas/crucible-ts/meta/fixtures/draft-2019-09-sample.json +21 -0
- package/schemas/crucible-ts/meta/fixtures/draft-2020-12-sample.json +21 -0
- package/schemas/crucible-ts/taxonomy/library/fulencode/normalization-profiles/v1.0.0/profiles.yaml +16 -0
- package/schemas/crucible-ts/upstream/3leaps/crucible/PROVENANCE.md +64 -0
- package/schemas/crucible-ts/upstream/3leaps/crucible/config/classifiers/dimensions/access-tier.dimension.json +103 -0
- package/schemas/crucible-ts/upstream/3leaps/crucible/config/classifiers/dimensions/retention-lifecycle.dimension.json +103 -0
- package/schemas/crucible-ts/upstream/3leaps/crucible/config/classifiers/dimensions/schema-stability.dimension.json +100 -0
- package/schemas/crucible-ts/upstream/3leaps/crucible/config/classifiers/dimensions/sensitivity.dimension.json +130 -0
- package/schemas/crucible-ts/upstream/3leaps/crucible/config/classifiers/dimensions/velocity-mode.dimension.json +79 -0
- package/schemas/crucible-ts/upstream/3leaps/crucible/config/classifiers/dimensions/volatility.dimension.json +72 -0
- package/schemas/crucible-ts/upstream/3leaps/crucible/config/classifiers/dimensions/volume-tier.dimension.json +66 -0
- package/schemas/crucible-ts/upstream/3leaps/crucible/docs/catalog/classifiers/README.md +29 -0
- package/schemas/crucible-ts/upstream/3leaps/crucible/docs/standards/access-tier-classification.md +163 -0
- package/schemas/crucible-ts/upstream/3leaps/crucible/docs/standards/classifiers-framework.md +157 -0
- package/schemas/crucible-ts/upstream/3leaps/crucible/docs/standards/data-sensitivity-classification.md +259 -0
- package/schemas/crucible-ts/upstream/3leaps/crucible/docs/standards/retention-lifecycle-classification.md +200 -0
- package/schemas/crucible-ts/upstream/3leaps/crucible/docs/standards/schema-stability-classification.md +205 -0
- package/schemas/crucible-ts/upstream/3leaps/crucible/docs/standards/velocity-mode-classification.md +222 -0
- package/schemas/crucible-ts/upstream/3leaps/crucible/docs/standards/volatility-classification.md +209 -0
- package/schemas/crucible-ts/upstream/3leaps/crucible/docs/standards/volume-tier-classification.md +200 -0
- package/schemas/crucible-ts/upstream/3leaps/crucible/schemas/ailink/v0/README.md +48 -0
- package/schemas/crucible-ts/upstream/3leaps/{ailink → crucible/schemas/ailink}/v0/prompt.schema.json +4 -18
- package/schemas/crucible-ts/upstream/3leaps/{ailink → crucible/schemas/ailink}/v0/search-response.schema.json +7 -37
- package/schemas/crucible-ts/upstream/3leaps/crucible/schemas/classifiers/v0/dimension-definition.schema.json +247 -0
- package/schemas/crucible-ts/upstream/3leaps/crucible/schemas/classifiers/v0/sensitivity-level.schema.json +67 -0
- package/schemas/crucible-ts/upstream/3leaps/crucible/schemas/foundation/v0/error-response.schema.json +59 -0
- package/schemas/crucible-ts/upstream/3leaps/crucible/schemas/foundation/v0/lifecycle-phases.data.json +102 -0
- package/schemas/crucible-ts/upstream/3leaps/crucible/schemas/foundation/v0/lifecycle-phases.schema.json +101 -0
- package/schemas/crucible-ts/upstream/3leaps/crucible/schemas/foundation/v0/release-phase.schema.json +18 -0
- package/schemas/crucible-ts/upstream/3leaps/crucible/schemas/foundation/v0/types.schema.json +177 -0
- package/schemas/crucible-ts/upstream/3leaps/PROVENANCE.md +0 -43
- /package/schemas/crucible-ts/upstream/3leaps/{agentic → crucible/schemas/agentic}/v0/role-prompt.schema.json +0 -0
package/dist/errors/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { F as FulmenError, a as FulmenErrorData, b as FulmenErrorOptions, L as LEVEL_TO_SEVERITY, S as SEVERITY_LEVELS, k as Severity, m as SeverityLevel, n as SeverityName, f as compareSeverity, e as extractErrorMessage, d as extractStackTrace, g as getDefaultSeverity, i as isFulmenError, c as isFulmenErrorData, h as isSeverityLevel, j as isSeverityName, l as levelToSeverity, s as serializeError, o as severityToLevel } from '../fulmen-error-B_kX8jSC.js';
|
|
2
|
-
import { A as AjvError } from '../types-
|
|
2
|
+
import { A as AjvError } from '../types-DdoeE7F5.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Correlation ID generation and validation for error tracking
|
package/dist/errors/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from 'crypto';
|
|
2
|
+
import addFormats from 'ajv-formats';
|
|
2
3
|
import { spawn } from 'child_process';
|
|
3
4
|
import { readFile, access, mkdir, writeFile } from 'fs/promises';
|
|
4
5
|
import { parse, stringify } from 'yaml';
|
|
@@ -6,7 +7,9 @@ import { dirname, extname, join, relative } from 'path';
|
|
|
6
7
|
import { fileURLToPath } from 'url';
|
|
7
8
|
import glob from 'fast-glob';
|
|
8
9
|
import Ajv from 'ajv';
|
|
9
|
-
import
|
|
10
|
+
import Ajv2019 from 'ajv/dist/2019';
|
|
11
|
+
import Ajv2020 from 'ajv/dist/2020';
|
|
12
|
+
import AjvDraft04 from 'ajv-draft-04';
|
|
10
13
|
import { Readable } from 'stream';
|
|
11
14
|
import picomatch from 'picomatch';
|
|
12
15
|
import { suggest as suggest$1, substringSimilarity, score as score$1, normalize as normalize$1, jaro_winkler, damerau_levenshtein, osa_distance, levenshtein } from '@3leaps/string-metrics-wasm';
|
|
@@ -170,6 +173,27 @@ var init_serialization = __esm({
|
|
|
170
173
|
init_severity();
|
|
171
174
|
}
|
|
172
175
|
});
|
|
176
|
+
function applyFulmenAjvFormats(ajv, options = {}) {
|
|
177
|
+
const mode = options.mode ?? "fast";
|
|
178
|
+
const formats = options.formats ?? DEFAULT_FORMATS;
|
|
179
|
+
addFormats(ajv, { mode, formats });
|
|
180
|
+
return ajv;
|
|
181
|
+
}
|
|
182
|
+
var DEFAULT_FORMATS;
|
|
183
|
+
var init_ajv_formats = __esm({
|
|
184
|
+
"src/schema/ajv-formats.ts"() {
|
|
185
|
+
DEFAULT_FORMATS = [
|
|
186
|
+
"date-time",
|
|
187
|
+
"email",
|
|
188
|
+
"hostname",
|
|
189
|
+
"ipv4",
|
|
190
|
+
"ipv6",
|
|
191
|
+
"uri",
|
|
192
|
+
"uri-reference",
|
|
193
|
+
"uuid"
|
|
194
|
+
];
|
|
195
|
+
}
|
|
196
|
+
});
|
|
173
197
|
|
|
174
198
|
// src/schema/errors.ts
|
|
175
199
|
var errors_exports = {};
|
|
@@ -1622,20 +1646,14 @@ async function loadMetaSchema(draft) {
|
|
|
1622
1646
|
const content = await readFile(metaSchemaPath, "utf-8");
|
|
1623
1647
|
return JSON.parse(content);
|
|
1624
1648
|
}
|
|
1625
|
-
async function loadVocabularySchemas() {
|
|
1649
|
+
async function loadVocabularySchemas(draft) {
|
|
1650
|
+
if (draft !== "draft-2019-09" && draft !== "draft-2020-12") {
|
|
1651
|
+
return [];
|
|
1652
|
+
}
|
|
1626
1653
|
const __filename3 = fileURLToPath(import.meta.url);
|
|
1627
1654
|
const __dirname4 = dirname(__filename3);
|
|
1628
|
-
const vocabDir = join(
|
|
1629
|
-
|
|
1630
|
-
"..",
|
|
1631
|
-
"..",
|
|
1632
|
-
"schemas",
|
|
1633
|
-
"crucible-ts",
|
|
1634
|
-
"meta",
|
|
1635
|
-
"draft-2020-12",
|
|
1636
|
-
"meta"
|
|
1637
|
-
);
|
|
1638
|
-
const vocabFiles = [
|
|
1655
|
+
const vocabDir = join(__dirname4, "..", "..", "schemas", "crucible-ts", "meta", draft, "meta");
|
|
1656
|
+
const vocabFiles = draft === "draft-2020-12" ? [
|
|
1639
1657
|
"core.json",
|
|
1640
1658
|
"applicator.json",
|
|
1641
1659
|
"unevaluated.json",
|
|
@@ -1643,6 +1661,13 @@ async function loadVocabularySchemas() {
|
|
|
1643
1661
|
"meta-data.json",
|
|
1644
1662
|
"format-annotation.json",
|
|
1645
1663
|
"content.json"
|
|
1664
|
+
] : [
|
|
1665
|
+
"core.json",
|
|
1666
|
+
"applicator.json",
|
|
1667
|
+
"validation.json",
|
|
1668
|
+
"meta-data.json",
|
|
1669
|
+
"format.json",
|
|
1670
|
+
"content.json"
|
|
1646
1671
|
];
|
|
1647
1672
|
const schemas = [];
|
|
1648
1673
|
for (const file of vocabFiles) {
|
|
@@ -1697,47 +1722,65 @@ async function loadReferencedSchema(uri) {
|
|
|
1697
1722
|
}
|
|
1698
1723
|
return JSON.parse(content);
|
|
1699
1724
|
}
|
|
1700
|
-
function
|
|
1701
|
-
if (!
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
}
|
|
1711
|
-
addFormats(ajvInstance, {
|
|
1712
|
-
mode: "fast",
|
|
1713
|
-
formats: ["date-time", "email", "hostname", "ipv4", "ipv6", "uri", "uri-reference"]
|
|
1714
|
-
});
|
|
1715
|
-
metaschemaReady = Promise.all([loadVocabularySchemas(), loadMetaSchema("draft-2020-12")]).then(([vocabSchemas, metaSchema]) => {
|
|
1716
|
-
if (ajvInstance) {
|
|
1717
|
-
for (const vocabSchema of vocabSchemas) {
|
|
1718
|
-
try {
|
|
1719
|
-
ajvInstance.addMetaSchema(vocabSchema);
|
|
1720
|
-
} catch {
|
|
1721
|
-
}
|
|
1722
|
-
}
|
|
1723
|
-
ajvInstance.addMetaSchema(metaSchema);
|
|
1724
|
-
}
|
|
1725
|
-
}).catch((error) => {
|
|
1726
|
-
throw new Error(`Failed to load metaschemas: ${error}`);
|
|
1727
|
-
});
|
|
1725
|
+
function detectDialect(schema) {
|
|
1726
|
+
if (schema && typeof schema === "object" && !Array.isArray(schema)) {
|
|
1727
|
+
const maybeSchema = schema;
|
|
1728
|
+
const declared = maybeSchema.$schema;
|
|
1729
|
+
if (typeof declared === "string") {
|
|
1730
|
+
if (declared.includes("draft-04")) return "draft-04";
|
|
1731
|
+
if (declared.includes("draft-06")) return "draft-06";
|
|
1732
|
+
if (declared.includes("draft-07")) return "draft-07";
|
|
1733
|
+
if (declared.includes("draft/2019-09")) return "draft-2019-09";
|
|
1734
|
+
if (declared.includes("draft/2020-12")) return "draft-2020-12";
|
|
1735
|
+
}
|
|
1728
1736
|
}
|
|
1729
|
-
return
|
|
1737
|
+
return "draft-2020-12";
|
|
1738
|
+
}
|
|
1739
|
+
function createAjv(dialect) {
|
|
1740
|
+
const AjvCtor = dialect === "draft-2020-12" ? Ajv2020 : dialect === "draft-2019-09" ? Ajv2019 : dialect === "draft-04" ? AjvDraft04 : Ajv;
|
|
1741
|
+
const ajv = new AjvCtor({
|
|
1742
|
+
strict: false,
|
|
1743
|
+
allErrors: true,
|
|
1744
|
+
verbose: true,
|
|
1745
|
+
// Allow schemas with $id to be added without replacing existing ones
|
|
1746
|
+
addUsedSchema: false,
|
|
1747
|
+
// draft-04 uses "id"; later drafts use "$id"
|
|
1748
|
+
schemaId: dialect === "draft-04" ? "id" : "$id",
|
|
1749
|
+
// Enable async schema loading for YAML references
|
|
1750
|
+
loadSchema: loadReferencedSchema
|
|
1751
|
+
});
|
|
1752
|
+
applyFulmenAjvFormats(ajv);
|
|
1753
|
+
return ajv;
|
|
1754
|
+
}
|
|
1755
|
+
async function getAjv(dialect) {
|
|
1756
|
+
const existing = ajvInstances.get(dialect);
|
|
1757
|
+
if (existing) {
|
|
1758
|
+
const ready = metaschemaReady.get(dialect);
|
|
1759
|
+
if (ready) await ready;
|
|
1760
|
+
return existing;
|
|
1761
|
+
}
|
|
1762
|
+
const ajv = createAjv(dialect);
|
|
1763
|
+
ajvInstances.set(dialect, ajv);
|
|
1764
|
+
const readyPromise = Promise.all([loadVocabularySchemas(dialect), loadMetaSchema(dialect)]).then(([vocabSchemas, metaSchema]) => {
|
|
1765
|
+
for (const vocabSchema of vocabSchemas) {
|
|
1766
|
+
try {
|
|
1767
|
+
ajv.addMetaSchema(vocabSchema);
|
|
1768
|
+
} catch {
|
|
1769
|
+
}
|
|
1770
|
+
}
|
|
1771
|
+
try {
|
|
1772
|
+
ajv.addMetaSchema(metaSchema);
|
|
1773
|
+
} catch {
|
|
1774
|
+
}
|
|
1775
|
+
}).catch((error) => {
|
|
1776
|
+
throw new Error(`Failed to load metaschemas (${dialect}): ${error}`);
|
|
1777
|
+
});
|
|
1778
|
+
metaschemaReady.set(dialect, readyPromise);
|
|
1779
|
+
await readyPromise;
|
|
1780
|
+
return ajv;
|
|
1730
1781
|
}
|
|
1731
1782
|
async function compileSchema(schema, options = {}) {
|
|
1732
|
-
const
|
|
1733
|
-
if (metaschemaReady) {
|
|
1734
|
-
await metaschemaReady;
|
|
1735
|
-
}
|
|
1736
|
-
const cacheKey = typeof schema === "string" ? schema : JSON.stringify(schema);
|
|
1737
|
-
const cached = schemaCache.get(cacheKey);
|
|
1738
|
-
if (cached !== void 0) {
|
|
1739
|
-
return cached;
|
|
1740
|
-
}
|
|
1783
|
+
const baseKey = typeof schema === "string" ? schema : JSON.stringify(schema);
|
|
1741
1784
|
let parsedSchema;
|
|
1742
1785
|
if (typeof schema === "string") {
|
|
1743
1786
|
try {
|
|
@@ -1755,18 +1798,27 @@ async function compileSchema(schema, options = {}) {
|
|
|
1755
1798
|
} else {
|
|
1756
1799
|
parsedSchema = schema;
|
|
1757
1800
|
}
|
|
1801
|
+
const dialect = detectDialect(parsedSchema);
|
|
1802
|
+
const ajv = await getAjv(dialect);
|
|
1803
|
+
const cacheKey = `${dialect}:${baseKey}`;
|
|
1804
|
+
const cached = schemaCache.get(cacheKey);
|
|
1805
|
+
if (cached !== void 0) {
|
|
1806
|
+
return cached;
|
|
1807
|
+
}
|
|
1758
1808
|
try {
|
|
1759
1809
|
if (options.aliases && options.aliases.length > 0) {
|
|
1760
1810
|
for (const alias of options.aliases) {
|
|
1761
1811
|
if (alias && ajv.getSchema(alias) === void 0) {
|
|
1762
1812
|
try {
|
|
1763
|
-
|
|
1813
|
+
if (typeof parsedSchema === "object" && parsedSchema !== null) {
|
|
1814
|
+
ajv.addSchema(parsedSchema, alias);
|
|
1815
|
+
}
|
|
1764
1816
|
} catch {
|
|
1765
1817
|
}
|
|
1766
1818
|
}
|
|
1767
1819
|
}
|
|
1768
1820
|
}
|
|
1769
|
-
const validator = await ajv.compileAsync(parsedSchema);
|
|
1821
|
+
const validator = typeof parsedSchema === "boolean" ? ajv.compile(parsedSchema) : await ajv.compileAsync(parsedSchema);
|
|
1770
1822
|
schemaCache.set(cacheKey, validator);
|
|
1771
1823
|
return validator;
|
|
1772
1824
|
} catch (error) {
|
|
@@ -1836,8 +1888,39 @@ async function validateFile(filePath, validator) {
|
|
|
1836
1888
|
}
|
|
1837
1889
|
async function validateSchema(schema) {
|
|
1838
1890
|
try {
|
|
1839
|
-
|
|
1840
|
-
|
|
1891
|
+
let parsedSchema;
|
|
1892
|
+
if (typeof schema === "string") {
|
|
1893
|
+
try {
|
|
1894
|
+
parsedSchema = JSON.parse(schema);
|
|
1895
|
+
} catch {
|
|
1896
|
+
parsedSchema = parse(schema);
|
|
1897
|
+
}
|
|
1898
|
+
} else if (Buffer.isBuffer(schema)) {
|
|
1899
|
+
const content = schema.toString("utf-8");
|
|
1900
|
+
try {
|
|
1901
|
+
parsedSchema = JSON.parse(content);
|
|
1902
|
+
} catch {
|
|
1903
|
+
parsedSchema = parse(content);
|
|
1904
|
+
}
|
|
1905
|
+
} else {
|
|
1906
|
+
parsedSchema = schema;
|
|
1907
|
+
}
|
|
1908
|
+
const dialect = detectDialect(parsedSchema);
|
|
1909
|
+
const ajv = await getAjv(dialect);
|
|
1910
|
+
const metaValid = ajv.validateSchema(parsedSchema);
|
|
1911
|
+
if (!metaValid && ajv.errors) {
|
|
1912
|
+
const diagnostics = ajv.errors.map(
|
|
1913
|
+
(error) => createDiagnostic(
|
|
1914
|
+
error.instancePath || "",
|
|
1915
|
+
error.message || "Schema meta-validation failed",
|
|
1916
|
+
error.keyword || "unknown",
|
|
1917
|
+
"ERROR",
|
|
1918
|
+
"ajv"
|
|
1919
|
+
)
|
|
1920
|
+
);
|
|
1921
|
+
return { valid: false, diagnostics, source: "ajv" };
|
|
1922
|
+
}
|
|
1923
|
+
await compileSchema(parsedSchema);
|
|
1841
1924
|
return {
|
|
1842
1925
|
valid: true,
|
|
1843
1926
|
diagnostics: [],
|
|
@@ -1908,14 +1991,16 @@ async function validateFileBySchemaId(filePath, schemaId, registryOptions) {
|
|
|
1908
1991
|
throw error;
|
|
1909
1992
|
}
|
|
1910
1993
|
}
|
|
1911
|
-
var
|
|
1994
|
+
var ajvInstances, metaschemaReady, schemaCache;
|
|
1912
1995
|
var init_validator = __esm({
|
|
1913
1996
|
"src/schema/validator.ts"() {
|
|
1914
1997
|
init_telemetry();
|
|
1998
|
+
init_ajv_formats();
|
|
1915
1999
|
init_errors();
|
|
1916
2000
|
init_registry();
|
|
1917
2001
|
init_utils();
|
|
1918
|
-
|
|
2002
|
+
ajvInstances = /* @__PURE__ */ new Map();
|
|
2003
|
+
metaschemaReady = /* @__PURE__ */ new Map();
|
|
1919
2004
|
schemaCache = /* @__PURE__ */ new Map();
|
|
1920
2005
|
}
|
|
1921
2006
|
});
|
|
@@ -3870,6 +3955,224 @@ var init_capabilities2 = __esm({
|
|
|
3870
3955
|
}
|
|
3871
3956
|
});
|
|
3872
3957
|
|
|
3958
|
+
// src/foundry/signals/config-reload-endpoint.ts
|
|
3959
|
+
function createConfigReloadEndpoint(options) {
|
|
3960
|
+
const { loader, validator, onReload: onReload2, auth, rateLimit, logger, telemetry } = options;
|
|
3961
|
+
return async (payload, req) => {
|
|
3962
|
+
const correlationId = payload.correlation_id ?? generateCorrelationId2();
|
|
3963
|
+
const authResult = await auth(req);
|
|
3964
|
+
if (!authResult.authenticated) {
|
|
3965
|
+
if (logger) {
|
|
3966
|
+
logger.warn("Config reload endpoint: authentication failed", {
|
|
3967
|
+
correlation_id: correlationId,
|
|
3968
|
+
reason: authResult.reason
|
|
3969
|
+
});
|
|
3970
|
+
}
|
|
3971
|
+
if (telemetry) {
|
|
3972
|
+
telemetry.emit("fulmen.config.http_endpoint.auth_failed", {
|
|
3973
|
+
correlation_id: correlationId
|
|
3974
|
+
});
|
|
3975
|
+
}
|
|
3976
|
+
return {
|
|
3977
|
+
status: "error",
|
|
3978
|
+
error: "authentication_failed",
|
|
3979
|
+
message: authResult.reason || "Authentication required",
|
|
3980
|
+
statusCode: 401
|
|
3981
|
+
};
|
|
3982
|
+
}
|
|
3983
|
+
const identity = authResult.identity || "unknown";
|
|
3984
|
+
if (rateLimit) {
|
|
3985
|
+
const rateLimitResult = await rateLimit(identity);
|
|
3986
|
+
if (!rateLimitResult.allowed) {
|
|
3987
|
+
if (logger) {
|
|
3988
|
+
logger.warn("Config reload endpoint: rate limit exceeded", {
|
|
3989
|
+
correlation_id: correlationId,
|
|
3990
|
+
identity
|
|
3991
|
+
});
|
|
3992
|
+
}
|
|
3993
|
+
if (telemetry) {
|
|
3994
|
+
telemetry.emit("fulmen.config.http_endpoint.rate_limited", {
|
|
3995
|
+
correlation_id: correlationId
|
|
3996
|
+
});
|
|
3997
|
+
}
|
|
3998
|
+
return {
|
|
3999
|
+
status: "error",
|
|
4000
|
+
error: "rate_limit_exceeded",
|
|
4001
|
+
message: "Rate limit exceeded. Please try again later.",
|
|
4002
|
+
statusCode: 429
|
|
4003
|
+
};
|
|
4004
|
+
}
|
|
4005
|
+
}
|
|
4006
|
+
if (telemetry) {
|
|
4007
|
+
telemetry.emit("fulmen.config.http_endpoint.reload_requested", {
|
|
4008
|
+
correlation_id: correlationId
|
|
4009
|
+
});
|
|
4010
|
+
}
|
|
4011
|
+
try {
|
|
4012
|
+
const config = await loader();
|
|
4013
|
+
if (validator) {
|
|
4014
|
+
const validation = await validator(config);
|
|
4015
|
+
if (!validation.valid) {
|
|
4016
|
+
if (logger) {
|
|
4017
|
+
logger.warn("Config reload endpoint: validation failed", {
|
|
4018
|
+
correlation_id: correlationId,
|
|
4019
|
+
error_count: validation.errors?.length ?? 0
|
|
4020
|
+
});
|
|
4021
|
+
}
|
|
4022
|
+
if (telemetry) {
|
|
4023
|
+
telemetry.emit("fulmen.config.http_endpoint.reload_rejected", {
|
|
4024
|
+
correlation_id: correlationId,
|
|
4025
|
+
reason: "validation_failed"
|
|
4026
|
+
});
|
|
4027
|
+
}
|
|
4028
|
+
return {
|
|
4029
|
+
status: "error",
|
|
4030
|
+
error: "validation_failed",
|
|
4031
|
+
message: "Configuration validation failed",
|
|
4032
|
+
validation_errors: validation.errors,
|
|
4033
|
+
statusCode: 422
|
|
4034
|
+
};
|
|
4035
|
+
}
|
|
4036
|
+
}
|
|
4037
|
+
if (onReload2) {
|
|
4038
|
+
await onReload2(config);
|
|
4039
|
+
}
|
|
4040
|
+
if (telemetry) {
|
|
4041
|
+
telemetry.emit("fulmen.config.http_endpoint.reload_accepted", {
|
|
4042
|
+
correlation_id: correlationId
|
|
4043
|
+
});
|
|
4044
|
+
}
|
|
4045
|
+
if (logger) {
|
|
4046
|
+
logger.info("Config reload endpoint: reload accepted", {
|
|
4047
|
+
correlation_id: correlationId,
|
|
4048
|
+
reason: payload.reason
|
|
4049
|
+
});
|
|
4050
|
+
}
|
|
4051
|
+
return {
|
|
4052
|
+
status: "reloaded",
|
|
4053
|
+
correlation_id: correlationId,
|
|
4054
|
+
message: "Configuration reloaded",
|
|
4055
|
+
statusCode: 200
|
|
4056
|
+
};
|
|
4057
|
+
} catch (error) {
|
|
4058
|
+
if (logger) {
|
|
4059
|
+
logger.warn("Config reload endpoint: reload failed", {
|
|
4060
|
+
correlation_id: correlationId,
|
|
4061
|
+
error: error instanceof Error ? error.message : String(error)
|
|
4062
|
+
});
|
|
4063
|
+
}
|
|
4064
|
+
if (telemetry) {
|
|
4065
|
+
telemetry.emit("fulmen.config.http_endpoint.reload_error", {
|
|
4066
|
+
correlation_id: correlationId,
|
|
4067
|
+
error_type: error instanceof Error ? error.constructor.name : "unknown"
|
|
4068
|
+
});
|
|
4069
|
+
}
|
|
4070
|
+
return {
|
|
4071
|
+
status: "error",
|
|
4072
|
+
error: "reload_failed",
|
|
4073
|
+
message: error instanceof Error ? error.message : String(error),
|
|
4074
|
+
statusCode: 500
|
|
4075
|
+
};
|
|
4076
|
+
}
|
|
4077
|
+
};
|
|
4078
|
+
}
|
|
4079
|
+
function generateCorrelationId2() {
|
|
4080
|
+
return `cfg-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
4081
|
+
}
|
|
4082
|
+
var init_config_reload_endpoint = __esm({
|
|
4083
|
+
"src/foundry/signals/config-reload-endpoint.ts"() {
|
|
4084
|
+
}
|
|
4085
|
+
});
|
|
4086
|
+
|
|
4087
|
+
// src/appidentity/runtime.ts
|
|
4088
|
+
function detectRuntime() {
|
|
4089
|
+
const versions = process.versions;
|
|
4090
|
+
if (typeof versions.bun === "string" && versions.bun.length > 0) {
|
|
4091
|
+
return { name: "bun", version: versions.bun };
|
|
4092
|
+
}
|
|
4093
|
+
if (typeof versions.node === "string" && versions.node.length > 0) {
|
|
4094
|
+
return { name: "node", version: versions.node };
|
|
4095
|
+
}
|
|
4096
|
+
return { name: "unknown" };
|
|
4097
|
+
}
|
|
4098
|
+
function buildRuntimeInfo(options = {}) {
|
|
4099
|
+
const runtime = detectRuntime();
|
|
4100
|
+
const serviceName = options.serviceName ?? options.identity?.app.binary_name ?? "unknown-service";
|
|
4101
|
+
const vendor = options.vendor ?? options.identity?.app.vendor;
|
|
4102
|
+
return {
|
|
4103
|
+
service: {
|
|
4104
|
+
name: serviceName,
|
|
4105
|
+
vendor,
|
|
4106
|
+
version: options.version
|
|
4107
|
+
},
|
|
4108
|
+
runtime,
|
|
4109
|
+
platform: {
|
|
4110
|
+
os: process.platform,
|
|
4111
|
+
arch: process.arch
|
|
4112
|
+
}
|
|
4113
|
+
};
|
|
4114
|
+
}
|
|
4115
|
+
var init_runtime = __esm({
|
|
4116
|
+
"src/appidentity/runtime.ts"() {
|
|
4117
|
+
}
|
|
4118
|
+
});
|
|
4119
|
+
|
|
4120
|
+
// src/foundry/signals/control-discovery-endpoint.ts
|
|
4121
|
+
function createControlDiscoveryEndpoint(options) {
|
|
4122
|
+
const { identity, version, endpoints, auth, authSummary, logger, telemetry } = options;
|
|
4123
|
+
return async (req) => {
|
|
4124
|
+
if (auth) {
|
|
4125
|
+
const authResult = await auth(req);
|
|
4126
|
+
if (!authResult.authenticated) {
|
|
4127
|
+
if (logger) {
|
|
4128
|
+
logger.warn("Control discovery endpoint: authentication failed", {
|
|
4129
|
+
reason: authResult.reason
|
|
4130
|
+
});
|
|
4131
|
+
}
|
|
4132
|
+
if (telemetry) {
|
|
4133
|
+
telemetry.emit("fulmen.control.discovery.auth_failed", {
|
|
4134
|
+
service: identity.app.binary_name
|
|
4135
|
+
});
|
|
4136
|
+
}
|
|
4137
|
+
return {
|
|
4138
|
+
status: "error",
|
|
4139
|
+
error: "authentication_failed",
|
|
4140
|
+
message: authResult.reason || "Authentication required",
|
|
4141
|
+
statusCode: 401
|
|
4142
|
+
};
|
|
4143
|
+
}
|
|
4144
|
+
}
|
|
4145
|
+
if (telemetry) {
|
|
4146
|
+
telemetry.emit("fulmen.control.discovery.served", {
|
|
4147
|
+
service: identity.app.binary_name
|
|
4148
|
+
});
|
|
4149
|
+
}
|
|
4150
|
+
const runtime = buildRuntimeInfo({ identity, version });
|
|
4151
|
+
return {
|
|
4152
|
+
status: "ok",
|
|
4153
|
+
service: {
|
|
4154
|
+
name: identity.app.binary_name,
|
|
4155
|
+
vendor: identity.app.vendor,
|
|
4156
|
+
version
|
|
4157
|
+
},
|
|
4158
|
+
runtime: {
|
|
4159
|
+
name: runtime.runtime.name,
|
|
4160
|
+
version: runtime.runtime.version,
|
|
4161
|
+
platform: runtime.platform.os,
|
|
4162
|
+
arch: runtime.platform.arch
|
|
4163
|
+
},
|
|
4164
|
+
auth_summary: authSummary,
|
|
4165
|
+
endpoints,
|
|
4166
|
+
statusCode: 200
|
|
4167
|
+
};
|
|
4168
|
+
};
|
|
4169
|
+
}
|
|
4170
|
+
var init_control_discovery_endpoint = __esm({
|
|
4171
|
+
"src/foundry/signals/control-discovery-endpoint.ts"() {
|
|
4172
|
+
init_runtime();
|
|
4173
|
+
}
|
|
4174
|
+
});
|
|
4175
|
+
|
|
3873
4176
|
// src/foundry/signals/convenience.ts
|
|
3874
4177
|
async function onShutdown(manager, handler, options = {}) {
|
|
3875
4178
|
await manager.register("SIGTERM", handler, options);
|
|
@@ -4129,7 +4432,7 @@ var init_guards = __esm({
|
|
|
4129
4432
|
function createSignalEndpoint(options) {
|
|
4130
4433
|
const { manager, auth, rateLimit, logger, telemetry, allowedSignals } = options;
|
|
4131
4434
|
return async (payload, req) => {
|
|
4132
|
-
const correlationId = payload.correlation_id ??
|
|
4435
|
+
const correlationId = payload.correlation_id ?? generateCorrelationId3();
|
|
4133
4436
|
const authResult = await auth(req);
|
|
4134
4437
|
if (!authResult.authenticated) {
|
|
4135
4438
|
if (logger) {
|
|
@@ -4252,7 +4555,7 @@ function normalizeSignalName(signal) {
|
|
|
4252
4555
|
}
|
|
4253
4556
|
return `SIG${upper}`;
|
|
4254
4557
|
}
|
|
4255
|
-
function
|
|
4558
|
+
function generateCorrelationId3() {
|
|
4256
4559
|
return `sig-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
4257
4560
|
}
|
|
4258
4561
|
function createBearerTokenAuth(expectedToken) {
|
|
@@ -4719,6 +5022,8 @@ var init_signals = __esm({
|
|
|
4719
5022
|
"src/foundry/signals/index.ts"() {
|
|
4720
5023
|
init_capabilities2();
|
|
4721
5024
|
init_catalog();
|
|
5025
|
+
init_config_reload_endpoint();
|
|
5026
|
+
init_control_discovery_endpoint();
|
|
4722
5027
|
init_convenience();
|
|
4723
5028
|
init_double_tap();
|
|
4724
5029
|
init_guards();
|
|
@@ -4864,7 +5169,9 @@ __export(foundry_exports, {
|
|
|
4864
5169
|
clearMimeTypeCache: () => clearMimeTypeCache,
|
|
4865
5170
|
clearPatternCache: () => clearPatternCache,
|
|
4866
5171
|
createBearerTokenAuth: () => createBearerTokenAuth,
|
|
5172
|
+
createConfigReloadEndpoint: () => createConfigReloadEndpoint,
|
|
4867
5173
|
createConfigReloadHandler: () => createConfigReloadHandler,
|
|
5174
|
+
createControlDiscoveryEndpoint: () => createControlDiscoveryEndpoint,
|
|
4868
5175
|
createDoubleTapTracker: () => createDoubleTapTracker,
|
|
4869
5176
|
createSignalEndpoint: () => createSignalEndpoint,
|
|
4870
5177
|
createSignalManager: () => createSignalManager,
|
|
@@ -5587,6 +5894,7 @@ var init_cli = __esm({
|
|
|
5587
5894
|
// src/schema/index.ts
|
|
5588
5895
|
var init_schema = __esm({
|
|
5589
5896
|
"src/schema/index.ts"() {
|
|
5897
|
+
init_ajv_formats();
|
|
5590
5898
|
init_cli();
|
|
5591
5899
|
init_errors();
|
|
5592
5900
|
init_export();
|