@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/crucible/index.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { readFile, access, mkdir, writeFile, readdir, stat } from 'fs/promises';
|
|
2
2
|
import { dirname, join, extname, relative } from 'path';
|
|
3
3
|
import { parse, stringify, parseDocument } from 'yaml';
|
|
4
|
+
import addFormats from 'ajv-formats';
|
|
4
5
|
import { spawn } from 'child_process';
|
|
5
6
|
import { fileURLToPath } from 'url';
|
|
6
7
|
import glob from 'fast-glob';
|
|
7
8
|
import Ajv from 'ajv';
|
|
8
|
-
import
|
|
9
|
+
import Ajv2019 from 'ajv/dist/2019';
|
|
10
|
+
import Ajv2020 from 'ajv/dist/2020';
|
|
11
|
+
import AjvDraft04 from 'ajv-draft-04';
|
|
9
12
|
import { Readable } from 'stream';
|
|
10
13
|
import picomatch from 'picomatch';
|
|
11
14
|
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';
|
|
@@ -727,6 +730,27 @@ var init_types = __esm({
|
|
|
727
730
|
"src/telemetry/types.ts"() {
|
|
728
731
|
}
|
|
729
732
|
});
|
|
733
|
+
function applyFulmenAjvFormats(ajv, options = {}) {
|
|
734
|
+
const mode = options.mode ?? "fast";
|
|
735
|
+
const formats = options.formats ?? DEFAULT_FORMATS;
|
|
736
|
+
addFormats(ajv, { mode, formats });
|
|
737
|
+
return ajv;
|
|
738
|
+
}
|
|
739
|
+
var DEFAULT_FORMATS;
|
|
740
|
+
var init_ajv_formats = __esm({
|
|
741
|
+
"src/schema/ajv-formats.ts"() {
|
|
742
|
+
DEFAULT_FORMATS = [
|
|
743
|
+
"date-time",
|
|
744
|
+
"email",
|
|
745
|
+
"hostname",
|
|
746
|
+
"ipv4",
|
|
747
|
+
"ipv6",
|
|
748
|
+
"uri",
|
|
749
|
+
"uri-reference",
|
|
750
|
+
"uuid"
|
|
751
|
+
];
|
|
752
|
+
}
|
|
753
|
+
});
|
|
730
754
|
|
|
731
755
|
// src/schema/errors.ts
|
|
732
756
|
var errors_exports = {};
|
|
@@ -1451,20 +1475,14 @@ async function loadMetaSchema(draft) {
|
|
|
1451
1475
|
const content = await readFile(metaSchemaPath, "utf-8");
|
|
1452
1476
|
return JSON.parse(content);
|
|
1453
1477
|
}
|
|
1454
|
-
async function loadVocabularySchemas() {
|
|
1478
|
+
async function loadVocabularySchemas(draft) {
|
|
1479
|
+
if (draft !== "draft-2019-09" && draft !== "draft-2020-12") {
|
|
1480
|
+
return [];
|
|
1481
|
+
}
|
|
1455
1482
|
const __filename3 = fileURLToPath(import.meta.url);
|
|
1456
1483
|
const __dirname4 = dirname(__filename3);
|
|
1457
|
-
const vocabDir = join(
|
|
1458
|
-
|
|
1459
|
-
"..",
|
|
1460
|
-
"..",
|
|
1461
|
-
"schemas",
|
|
1462
|
-
"crucible-ts",
|
|
1463
|
-
"meta",
|
|
1464
|
-
"draft-2020-12",
|
|
1465
|
-
"meta"
|
|
1466
|
-
);
|
|
1467
|
-
const vocabFiles = [
|
|
1484
|
+
const vocabDir = join(__dirname4, "..", "..", "schemas", "crucible-ts", "meta", draft, "meta");
|
|
1485
|
+
const vocabFiles = draft === "draft-2020-12" ? [
|
|
1468
1486
|
"core.json",
|
|
1469
1487
|
"applicator.json",
|
|
1470
1488
|
"unevaluated.json",
|
|
@@ -1472,6 +1490,13 @@ async function loadVocabularySchemas() {
|
|
|
1472
1490
|
"meta-data.json",
|
|
1473
1491
|
"format-annotation.json",
|
|
1474
1492
|
"content.json"
|
|
1493
|
+
] : [
|
|
1494
|
+
"core.json",
|
|
1495
|
+
"applicator.json",
|
|
1496
|
+
"validation.json",
|
|
1497
|
+
"meta-data.json",
|
|
1498
|
+
"format.json",
|
|
1499
|
+
"content.json"
|
|
1475
1500
|
];
|
|
1476
1501
|
const schemas = [];
|
|
1477
1502
|
for (const file of vocabFiles) {
|
|
@@ -1526,47 +1551,65 @@ async function loadReferencedSchema(uri) {
|
|
|
1526
1551
|
}
|
|
1527
1552
|
return JSON.parse(content);
|
|
1528
1553
|
}
|
|
1529
|
-
function
|
|
1530
|
-
if (!
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
}
|
|
1540
|
-
addFormats(ajvInstance, {
|
|
1541
|
-
mode: "fast",
|
|
1542
|
-
formats: ["date-time", "email", "hostname", "ipv4", "ipv6", "uri", "uri-reference"]
|
|
1543
|
-
});
|
|
1544
|
-
metaschemaReady = Promise.all([loadVocabularySchemas(), loadMetaSchema("draft-2020-12")]).then(([vocabSchemas, metaSchema]) => {
|
|
1545
|
-
if (ajvInstance) {
|
|
1546
|
-
for (const vocabSchema of vocabSchemas) {
|
|
1547
|
-
try {
|
|
1548
|
-
ajvInstance.addMetaSchema(vocabSchema);
|
|
1549
|
-
} catch {
|
|
1550
|
-
}
|
|
1551
|
-
}
|
|
1552
|
-
ajvInstance.addMetaSchema(metaSchema);
|
|
1553
|
-
}
|
|
1554
|
-
}).catch((error) => {
|
|
1555
|
-
throw new Error(`Failed to load metaschemas: ${error}`);
|
|
1556
|
-
});
|
|
1554
|
+
function detectDialect(schema) {
|
|
1555
|
+
if (schema && typeof schema === "object" && !Array.isArray(schema)) {
|
|
1556
|
+
const maybeSchema = schema;
|
|
1557
|
+
const declared = maybeSchema.$schema;
|
|
1558
|
+
if (typeof declared === "string") {
|
|
1559
|
+
if (declared.includes("draft-04")) return "draft-04";
|
|
1560
|
+
if (declared.includes("draft-06")) return "draft-06";
|
|
1561
|
+
if (declared.includes("draft-07")) return "draft-07";
|
|
1562
|
+
if (declared.includes("draft/2019-09")) return "draft-2019-09";
|
|
1563
|
+
if (declared.includes("draft/2020-12")) return "draft-2020-12";
|
|
1564
|
+
}
|
|
1557
1565
|
}
|
|
1558
|
-
return
|
|
1566
|
+
return "draft-2020-12";
|
|
1567
|
+
}
|
|
1568
|
+
function createAjv(dialect) {
|
|
1569
|
+
const AjvCtor = dialect === "draft-2020-12" ? Ajv2020 : dialect === "draft-2019-09" ? Ajv2019 : dialect === "draft-04" ? AjvDraft04 : Ajv;
|
|
1570
|
+
const ajv = new AjvCtor({
|
|
1571
|
+
strict: false,
|
|
1572
|
+
allErrors: true,
|
|
1573
|
+
verbose: true,
|
|
1574
|
+
// Allow schemas with $id to be added without replacing existing ones
|
|
1575
|
+
addUsedSchema: false,
|
|
1576
|
+
// draft-04 uses "id"; later drafts use "$id"
|
|
1577
|
+
schemaId: dialect === "draft-04" ? "id" : "$id",
|
|
1578
|
+
// Enable async schema loading for YAML references
|
|
1579
|
+
loadSchema: loadReferencedSchema
|
|
1580
|
+
});
|
|
1581
|
+
applyFulmenAjvFormats(ajv);
|
|
1582
|
+
return ajv;
|
|
1583
|
+
}
|
|
1584
|
+
async function getAjv(dialect) {
|
|
1585
|
+
const existing = ajvInstances.get(dialect);
|
|
1586
|
+
if (existing) {
|
|
1587
|
+
const ready = metaschemaReady.get(dialect);
|
|
1588
|
+
if (ready) await ready;
|
|
1589
|
+
return existing;
|
|
1590
|
+
}
|
|
1591
|
+
const ajv = createAjv(dialect);
|
|
1592
|
+
ajvInstances.set(dialect, ajv);
|
|
1593
|
+
const readyPromise = Promise.all([loadVocabularySchemas(dialect), loadMetaSchema(dialect)]).then(([vocabSchemas, metaSchema]) => {
|
|
1594
|
+
for (const vocabSchema of vocabSchemas) {
|
|
1595
|
+
try {
|
|
1596
|
+
ajv.addMetaSchema(vocabSchema);
|
|
1597
|
+
} catch {
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
try {
|
|
1601
|
+
ajv.addMetaSchema(metaSchema);
|
|
1602
|
+
} catch {
|
|
1603
|
+
}
|
|
1604
|
+
}).catch((error) => {
|
|
1605
|
+
throw new Error(`Failed to load metaschemas (${dialect}): ${error}`);
|
|
1606
|
+
});
|
|
1607
|
+
metaschemaReady.set(dialect, readyPromise);
|
|
1608
|
+
await readyPromise;
|
|
1609
|
+
return ajv;
|
|
1559
1610
|
}
|
|
1560
1611
|
async function compileSchema(schema, options = {}) {
|
|
1561
|
-
const
|
|
1562
|
-
if (metaschemaReady) {
|
|
1563
|
-
await metaschemaReady;
|
|
1564
|
-
}
|
|
1565
|
-
const cacheKey = typeof schema === "string" ? schema : JSON.stringify(schema);
|
|
1566
|
-
const cached = schemaCache.get(cacheKey);
|
|
1567
|
-
if (cached !== void 0) {
|
|
1568
|
-
return cached;
|
|
1569
|
-
}
|
|
1612
|
+
const baseKey = typeof schema === "string" ? schema : JSON.stringify(schema);
|
|
1570
1613
|
let parsedSchema;
|
|
1571
1614
|
if (typeof schema === "string") {
|
|
1572
1615
|
try {
|
|
@@ -1584,18 +1627,27 @@ async function compileSchema(schema, options = {}) {
|
|
|
1584
1627
|
} else {
|
|
1585
1628
|
parsedSchema = schema;
|
|
1586
1629
|
}
|
|
1630
|
+
const dialect = detectDialect(parsedSchema);
|
|
1631
|
+
const ajv = await getAjv(dialect);
|
|
1632
|
+
const cacheKey = `${dialect}:${baseKey}`;
|
|
1633
|
+
const cached = schemaCache.get(cacheKey);
|
|
1634
|
+
if (cached !== void 0) {
|
|
1635
|
+
return cached;
|
|
1636
|
+
}
|
|
1587
1637
|
try {
|
|
1588
1638
|
if (options.aliases && options.aliases.length > 0) {
|
|
1589
1639
|
for (const alias of options.aliases) {
|
|
1590
1640
|
if (alias && ajv.getSchema(alias) === void 0) {
|
|
1591
1641
|
try {
|
|
1592
|
-
|
|
1642
|
+
if (typeof parsedSchema === "object" && parsedSchema !== null) {
|
|
1643
|
+
ajv.addSchema(parsedSchema, alias);
|
|
1644
|
+
}
|
|
1593
1645
|
} catch {
|
|
1594
1646
|
}
|
|
1595
1647
|
}
|
|
1596
1648
|
}
|
|
1597
1649
|
}
|
|
1598
|
-
const validator = await ajv.compileAsync(parsedSchema);
|
|
1650
|
+
const validator = typeof parsedSchema === "boolean" ? ajv.compile(parsedSchema) : await ajv.compileAsync(parsedSchema);
|
|
1599
1651
|
schemaCache.set(cacheKey, validator);
|
|
1600
1652
|
return validator;
|
|
1601
1653
|
} catch (error) {
|
|
@@ -1665,8 +1717,39 @@ async function validateFile(filePath, validator) {
|
|
|
1665
1717
|
}
|
|
1666
1718
|
async function validateSchema(schema) {
|
|
1667
1719
|
try {
|
|
1668
|
-
|
|
1669
|
-
|
|
1720
|
+
let parsedSchema;
|
|
1721
|
+
if (typeof schema === "string") {
|
|
1722
|
+
try {
|
|
1723
|
+
parsedSchema = JSON.parse(schema);
|
|
1724
|
+
} catch {
|
|
1725
|
+
parsedSchema = parse(schema);
|
|
1726
|
+
}
|
|
1727
|
+
} else if (Buffer.isBuffer(schema)) {
|
|
1728
|
+
const content = schema.toString("utf-8");
|
|
1729
|
+
try {
|
|
1730
|
+
parsedSchema = JSON.parse(content);
|
|
1731
|
+
} catch {
|
|
1732
|
+
parsedSchema = parse(content);
|
|
1733
|
+
}
|
|
1734
|
+
} else {
|
|
1735
|
+
parsedSchema = schema;
|
|
1736
|
+
}
|
|
1737
|
+
const dialect = detectDialect(parsedSchema);
|
|
1738
|
+
const ajv = await getAjv(dialect);
|
|
1739
|
+
const metaValid = ajv.validateSchema(parsedSchema);
|
|
1740
|
+
if (!metaValid && ajv.errors) {
|
|
1741
|
+
const diagnostics = ajv.errors.map(
|
|
1742
|
+
(error) => createDiagnostic(
|
|
1743
|
+
error.instancePath || "",
|
|
1744
|
+
error.message || "Schema meta-validation failed",
|
|
1745
|
+
error.keyword || "unknown",
|
|
1746
|
+
"ERROR",
|
|
1747
|
+
"ajv"
|
|
1748
|
+
)
|
|
1749
|
+
);
|
|
1750
|
+
return { valid: false, diagnostics, source: "ajv" };
|
|
1751
|
+
}
|
|
1752
|
+
await compileSchema(parsedSchema);
|
|
1670
1753
|
return {
|
|
1671
1754
|
valid: true,
|
|
1672
1755
|
diagnostics: [],
|
|
@@ -1737,14 +1820,16 @@ async function validateFileBySchemaId(filePath, schemaId, registryOptions) {
|
|
|
1737
1820
|
throw error;
|
|
1738
1821
|
}
|
|
1739
1822
|
}
|
|
1740
|
-
var
|
|
1823
|
+
var ajvInstances, metaschemaReady, schemaCache;
|
|
1741
1824
|
var init_validator = __esm({
|
|
1742
1825
|
"src/schema/validator.ts"() {
|
|
1743
1826
|
init_telemetry();
|
|
1827
|
+
init_ajv_formats();
|
|
1744
1828
|
init_errors();
|
|
1745
1829
|
init_registry2();
|
|
1746
1830
|
init_utils();
|
|
1747
|
-
|
|
1831
|
+
ajvInstances = /* @__PURE__ */ new Map();
|
|
1832
|
+
metaschemaReady = /* @__PURE__ */ new Map();
|
|
1748
1833
|
schemaCache = /* @__PURE__ */ new Map();
|
|
1749
1834
|
}
|
|
1750
1835
|
});
|
|
@@ -3699,6 +3784,224 @@ var init_capabilities2 = __esm({
|
|
|
3699
3784
|
}
|
|
3700
3785
|
});
|
|
3701
3786
|
|
|
3787
|
+
// src/foundry/signals/config-reload-endpoint.ts
|
|
3788
|
+
function createConfigReloadEndpoint(options) {
|
|
3789
|
+
const { loader, validator, onReload: onReload2, auth, rateLimit, logger, telemetry } = options;
|
|
3790
|
+
return async (payload, req) => {
|
|
3791
|
+
const correlationId = payload.correlation_id ?? generateCorrelationId();
|
|
3792
|
+
const authResult = await auth(req);
|
|
3793
|
+
if (!authResult.authenticated) {
|
|
3794
|
+
if (logger) {
|
|
3795
|
+
logger.warn("Config reload endpoint: authentication failed", {
|
|
3796
|
+
correlation_id: correlationId,
|
|
3797
|
+
reason: authResult.reason
|
|
3798
|
+
});
|
|
3799
|
+
}
|
|
3800
|
+
if (telemetry) {
|
|
3801
|
+
telemetry.emit("fulmen.config.http_endpoint.auth_failed", {
|
|
3802
|
+
correlation_id: correlationId
|
|
3803
|
+
});
|
|
3804
|
+
}
|
|
3805
|
+
return {
|
|
3806
|
+
status: "error",
|
|
3807
|
+
error: "authentication_failed",
|
|
3808
|
+
message: authResult.reason || "Authentication required",
|
|
3809
|
+
statusCode: 401
|
|
3810
|
+
};
|
|
3811
|
+
}
|
|
3812
|
+
const identity = authResult.identity || "unknown";
|
|
3813
|
+
if (rateLimit) {
|
|
3814
|
+
const rateLimitResult = await rateLimit(identity);
|
|
3815
|
+
if (!rateLimitResult.allowed) {
|
|
3816
|
+
if (logger) {
|
|
3817
|
+
logger.warn("Config reload endpoint: rate limit exceeded", {
|
|
3818
|
+
correlation_id: correlationId,
|
|
3819
|
+
identity
|
|
3820
|
+
});
|
|
3821
|
+
}
|
|
3822
|
+
if (telemetry) {
|
|
3823
|
+
telemetry.emit("fulmen.config.http_endpoint.rate_limited", {
|
|
3824
|
+
correlation_id: correlationId
|
|
3825
|
+
});
|
|
3826
|
+
}
|
|
3827
|
+
return {
|
|
3828
|
+
status: "error",
|
|
3829
|
+
error: "rate_limit_exceeded",
|
|
3830
|
+
message: "Rate limit exceeded. Please try again later.",
|
|
3831
|
+
statusCode: 429
|
|
3832
|
+
};
|
|
3833
|
+
}
|
|
3834
|
+
}
|
|
3835
|
+
if (telemetry) {
|
|
3836
|
+
telemetry.emit("fulmen.config.http_endpoint.reload_requested", {
|
|
3837
|
+
correlation_id: correlationId
|
|
3838
|
+
});
|
|
3839
|
+
}
|
|
3840
|
+
try {
|
|
3841
|
+
const config = await loader();
|
|
3842
|
+
if (validator) {
|
|
3843
|
+
const validation = await validator(config);
|
|
3844
|
+
if (!validation.valid) {
|
|
3845
|
+
if (logger) {
|
|
3846
|
+
logger.warn("Config reload endpoint: validation failed", {
|
|
3847
|
+
correlation_id: correlationId,
|
|
3848
|
+
error_count: validation.errors?.length ?? 0
|
|
3849
|
+
});
|
|
3850
|
+
}
|
|
3851
|
+
if (telemetry) {
|
|
3852
|
+
telemetry.emit("fulmen.config.http_endpoint.reload_rejected", {
|
|
3853
|
+
correlation_id: correlationId,
|
|
3854
|
+
reason: "validation_failed"
|
|
3855
|
+
});
|
|
3856
|
+
}
|
|
3857
|
+
return {
|
|
3858
|
+
status: "error",
|
|
3859
|
+
error: "validation_failed",
|
|
3860
|
+
message: "Configuration validation failed",
|
|
3861
|
+
validation_errors: validation.errors,
|
|
3862
|
+
statusCode: 422
|
|
3863
|
+
};
|
|
3864
|
+
}
|
|
3865
|
+
}
|
|
3866
|
+
if (onReload2) {
|
|
3867
|
+
await onReload2(config);
|
|
3868
|
+
}
|
|
3869
|
+
if (telemetry) {
|
|
3870
|
+
telemetry.emit("fulmen.config.http_endpoint.reload_accepted", {
|
|
3871
|
+
correlation_id: correlationId
|
|
3872
|
+
});
|
|
3873
|
+
}
|
|
3874
|
+
if (logger) {
|
|
3875
|
+
logger.info("Config reload endpoint: reload accepted", {
|
|
3876
|
+
correlation_id: correlationId,
|
|
3877
|
+
reason: payload.reason
|
|
3878
|
+
});
|
|
3879
|
+
}
|
|
3880
|
+
return {
|
|
3881
|
+
status: "reloaded",
|
|
3882
|
+
correlation_id: correlationId,
|
|
3883
|
+
message: "Configuration reloaded",
|
|
3884
|
+
statusCode: 200
|
|
3885
|
+
};
|
|
3886
|
+
} catch (error) {
|
|
3887
|
+
if (logger) {
|
|
3888
|
+
logger.warn("Config reload endpoint: reload failed", {
|
|
3889
|
+
correlation_id: correlationId,
|
|
3890
|
+
error: error instanceof Error ? error.message : String(error)
|
|
3891
|
+
});
|
|
3892
|
+
}
|
|
3893
|
+
if (telemetry) {
|
|
3894
|
+
telemetry.emit("fulmen.config.http_endpoint.reload_error", {
|
|
3895
|
+
correlation_id: correlationId,
|
|
3896
|
+
error_type: error instanceof Error ? error.constructor.name : "unknown"
|
|
3897
|
+
});
|
|
3898
|
+
}
|
|
3899
|
+
return {
|
|
3900
|
+
status: "error",
|
|
3901
|
+
error: "reload_failed",
|
|
3902
|
+
message: error instanceof Error ? error.message : String(error),
|
|
3903
|
+
statusCode: 500
|
|
3904
|
+
};
|
|
3905
|
+
}
|
|
3906
|
+
};
|
|
3907
|
+
}
|
|
3908
|
+
function generateCorrelationId() {
|
|
3909
|
+
return `cfg-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
3910
|
+
}
|
|
3911
|
+
var init_config_reload_endpoint = __esm({
|
|
3912
|
+
"src/foundry/signals/config-reload-endpoint.ts"() {
|
|
3913
|
+
}
|
|
3914
|
+
});
|
|
3915
|
+
|
|
3916
|
+
// src/appidentity/runtime.ts
|
|
3917
|
+
function detectRuntime() {
|
|
3918
|
+
const versions = process.versions;
|
|
3919
|
+
if (typeof versions.bun === "string" && versions.bun.length > 0) {
|
|
3920
|
+
return { name: "bun", version: versions.bun };
|
|
3921
|
+
}
|
|
3922
|
+
if (typeof versions.node === "string" && versions.node.length > 0) {
|
|
3923
|
+
return { name: "node", version: versions.node };
|
|
3924
|
+
}
|
|
3925
|
+
return { name: "unknown" };
|
|
3926
|
+
}
|
|
3927
|
+
function buildRuntimeInfo(options = {}) {
|
|
3928
|
+
const runtime = detectRuntime();
|
|
3929
|
+
const serviceName = options.serviceName ?? options.identity?.app.binary_name ?? "unknown-service";
|
|
3930
|
+
const vendor = options.vendor ?? options.identity?.app.vendor;
|
|
3931
|
+
return {
|
|
3932
|
+
service: {
|
|
3933
|
+
name: serviceName,
|
|
3934
|
+
vendor,
|
|
3935
|
+
version: options.version
|
|
3936
|
+
},
|
|
3937
|
+
runtime,
|
|
3938
|
+
platform: {
|
|
3939
|
+
os: process.platform,
|
|
3940
|
+
arch: process.arch
|
|
3941
|
+
}
|
|
3942
|
+
};
|
|
3943
|
+
}
|
|
3944
|
+
var init_runtime = __esm({
|
|
3945
|
+
"src/appidentity/runtime.ts"() {
|
|
3946
|
+
}
|
|
3947
|
+
});
|
|
3948
|
+
|
|
3949
|
+
// src/foundry/signals/control-discovery-endpoint.ts
|
|
3950
|
+
function createControlDiscoveryEndpoint(options) {
|
|
3951
|
+
const { identity, version, endpoints, auth, authSummary, logger, telemetry } = options;
|
|
3952
|
+
return async (req) => {
|
|
3953
|
+
if (auth) {
|
|
3954
|
+
const authResult = await auth(req);
|
|
3955
|
+
if (!authResult.authenticated) {
|
|
3956
|
+
if (logger) {
|
|
3957
|
+
logger.warn("Control discovery endpoint: authentication failed", {
|
|
3958
|
+
reason: authResult.reason
|
|
3959
|
+
});
|
|
3960
|
+
}
|
|
3961
|
+
if (telemetry) {
|
|
3962
|
+
telemetry.emit("fulmen.control.discovery.auth_failed", {
|
|
3963
|
+
service: identity.app.binary_name
|
|
3964
|
+
});
|
|
3965
|
+
}
|
|
3966
|
+
return {
|
|
3967
|
+
status: "error",
|
|
3968
|
+
error: "authentication_failed",
|
|
3969
|
+
message: authResult.reason || "Authentication required",
|
|
3970
|
+
statusCode: 401
|
|
3971
|
+
};
|
|
3972
|
+
}
|
|
3973
|
+
}
|
|
3974
|
+
if (telemetry) {
|
|
3975
|
+
telemetry.emit("fulmen.control.discovery.served", {
|
|
3976
|
+
service: identity.app.binary_name
|
|
3977
|
+
});
|
|
3978
|
+
}
|
|
3979
|
+
const runtime = buildRuntimeInfo({ identity, version });
|
|
3980
|
+
return {
|
|
3981
|
+
status: "ok",
|
|
3982
|
+
service: {
|
|
3983
|
+
name: identity.app.binary_name,
|
|
3984
|
+
vendor: identity.app.vendor,
|
|
3985
|
+
version
|
|
3986
|
+
},
|
|
3987
|
+
runtime: {
|
|
3988
|
+
name: runtime.runtime.name,
|
|
3989
|
+
version: runtime.runtime.version,
|
|
3990
|
+
platform: runtime.platform.os,
|
|
3991
|
+
arch: runtime.platform.arch
|
|
3992
|
+
},
|
|
3993
|
+
auth_summary: authSummary,
|
|
3994
|
+
endpoints,
|
|
3995
|
+
statusCode: 200
|
|
3996
|
+
};
|
|
3997
|
+
};
|
|
3998
|
+
}
|
|
3999
|
+
var init_control_discovery_endpoint = __esm({
|
|
4000
|
+
"src/foundry/signals/control-discovery-endpoint.ts"() {
|
|
4001
|
+
init_runtime();
|
|
4002
|
+
}
|
|
4003
|
+
});
|
|
4004
|
+
|
|
3702
4005
|
// src/foundry/signals/convenience.ts
|
|
3703
4006
|
async function onShutdown(manager, handler, options = {}) {
|
|
3704
4007
|
await manager.register("SIGTERM", handler, options);
|
|
@@ -3958,7 +4261,7 @@ var init_guards = __esm({
|
|
|
3958
4261
|
function createSignalEndpoint(options) {
|
|
3959
4262
|
const { manager, auth, rateLimit, logger, telemetry, allowedSignals } = options;
|
|
3960
4263
|
return async (payload, req) => {
|
|
3961
|
-
const correlationId = payload.correlation_id ??
|
|
4264
|
+
const correlationId = payload.correlation_id ?? generateCorrelationId2();
|
|
3962
4265
|
const authResult = await auth(req);
|
|
3963
4266
|
if (!authResult.authenticated) {
|
|
3964
4267
|
if (logger) {
|
|
@@ -4081,7 +4384,7 @@ function normalizeSignalName(signal) {
|
|
|
4081
4384
|
}
|
|
4082
4385
|
return `SIG${upper}`;
|
|
4083
4386
|
}
|
|
4084
|
-
function
|
|
4387
|
+
function generateCorrelationId2() {
|
|
4085
4388
|
return `sig-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
4086
4389
|
}
|
|
4087
4390
|
function createBearerTokenAuth(expectedToken) {
|
|
@@ -4548,6 +4851,8 @@ var init_signals = __esm({
|
|
|
4548
4851
|
"src/foundry/signals/index.ts"() {
|
|
4549
4852
|
init_capabilities2();
|
|
4550
4853
|
init_catalog();
|
|
4854
|
+
init_config_reload_endpoint();
|
|
4855
|
+
init_control_discovery_endpoint();
|
|
4551
4856
|
init_convenience();
|
|
4552
4857
|
init_double_tap();
|
|
4553
4858
|
init_guards();
|
|
@@ -4693,7 +4998,9 @@ __export(foundry_exports, {
|
|
|
4693
4998
|
clearMimeTypeCache: () => clearMimeTypeCache,
|
|
4694
4999
|
clearPatternCache: () => clearPatternCache,
|
|
4695
5000
|
createBearerTokenAuth: () => createBearerTokenAuth,
|
|
5001
|
+
createConfigReloadEndpoint: () => createConfigReloadEndpoint,
|
|
4696
5002
|
createConfigReloadHandler: () => createConfigReloadHandler,
|
|
5003
|
+
createControlDiscoveryEndpoint: () => createControlDiscoveryEndpoint,
|
|
4697
5004
|
createDoubleTapTracker: () => createDoubleTapTracker,
|
|
4698
5005
|
createSignalEndpoint: () => createSignalEndpoint,
|
|
4699
5006
|
createSignalManager: () => createSignalManager,
|
|
@@ -5749,6 +6056,7 @@ var init_cli = __esm({
|
|
|
5749
6056
|
// src/schema/index.ts
|
|
5750
6057
|
var init_schema = __esm({
|
|
5751
6058
|
"src/schema/index.ts"() {
|
|
6059
|
+
init_ajv_formats();
|
|
5752
6060
|
init_cli();
|
|
5753
6061
|
init_errors();
|
|
5754
6062
|
init_export();
|