@fulmenhq/tsfulmen 0.2.2 → 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 +28 -0
- package/README.md +9 -8
- package/dist/appidentity/index.d.ts +30 -108
- package/dist/appidentity/index.js +251 -8
- package/dist/appidentity/index.js.map +1 -1
- package/dist/config/index.d.ts +46 -1
- package/dist/config/index.js +309 -10
- package/dist/config/index.js.map +1 -1
- package/dist/crucible/index.js +249 -7
- package/dist/crucible/index.js.map +1 -1
- package/dist/errors/index.js +249 -7
- package/dist/errors/index.js.map +1 -1
- package/dist/foundry/index.d.ts +2 -1
- package/dist/foundry/index.js +250 -8
- package/dist/foundry/index.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +252 -9
- package/dist/index.js.map +1 -1
- package/dist/pathfinder/index.js +249 -7
- package/dist/pathfinder/index.js.map +1 -1
- package/dist/reports/license-inventory.csv +29 -23
- package/dist/schema/index.d.ts +14 -1
- package/dist/schema/index.js +250 -8
- package/dist/schema/index.js.map +1 -1
- package/dist/signals/index.d.ts +483 -395
- package/dist/signals/index.js +250 -8
- package/dist/signals/index.js.map +1 -1
- package/dist/telemetry/http/index.js +250 -7
- package/dist/telemetry/http/index.js.map +1 -1
- package/dist/telemetry/index.js +249 -7
- package/dist/telemetry/index.js.map +1 -1
- package/dist/telemetry/prometheus/index.js +251 -7
- package/dist/telemetry/prometheus/index.js.map +1 -1
- package/dist/types-Dv5TERCM.d.ts +108 -0
- package/package.json +8 -8
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import 'crypto';
|
|
2
|
+
import addFormats from 'ajv-formats';
|
|
2
3
|
import { spawn } from 'child_process';
|
|
3
4
|
import { readFile, writeFile, access, mkdir } from 'fs/promises';
|
|
4
5
|
import { parse, stringify } from 'yaml';
|
|
@@ -9,7 +10,6 @@ import Ajv from 'ajv';
|
|
|
9
10
|
import Ajv2019 from 'ajv/dist/2019';
|
|
10
11
|
import Ajv2020 from 'ajv/dist/2020';
|
|
11
12
|
import AjvDraft04 from 'ajv-draft-04';
|
|
12
|
-
import addFormats from 'ajv-formats';
|
|
13
13
|
import { Readable } from 'stream';
|
|
14
14
|
import picomatch from 'picomatch';
|
|
15
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';
|
|
@@ -120,6 +120,27 @@ var init_serialization = __esm({
|
|
|
120
120
|
init_severity();
|
|
121
121
|
}
|
|
122
122
|
});
|
|
123
|
+
function applyFulmenAjvFormats(ajv, options = {}) {
|
|
124
|
+
const mode = options.mode ?? "fast";
|
|
125
|
+
const formats = options.formats ?? DEFAULT_FORMATS;
|
|
126
|
+
addFormats(ajv, { mode, formats });
|
|
127
|
+
return ajv;
|
|
128
|
+
}
|
|
129
|
+
var DEFAULT_FORMATS;
|
|
130
|
+
var init_ajv_formats = __esm({
|
|
131
|
+
"src/schema/ajv-formats.ts"() {
|
|
132
|
+
DEFAULT_FORMATS = [
|
|
133
|
+
"date-time",
|
|
134
|
+
"email",
|
|
135
|
+
"hostname",
|
|
136
|
+
"ipv4",
|
|
137
|
+
"ipv6",
|
|
138
|
+
"uri",
|
|
139
|
+
"uri-reference",
|
|
140
|
+
"uuid"
|
|
141
|
+
];
|
|
142
|
+
}
|
|
143
|
+
});
|
|
123
144
|
|
|
124
145
|
// src/schema/errors.ts
|
|
125
146
|
var errors_exports = {};
|
|
@@ -1678,10 +1699,7 @@ function createAjv(dialect) {
|
|
|
1678
1699
|
// Enable async schema loading for YAML references
|
|
1679
1700
|
loadSchema: loadReferencedSchema
|
|
1680
1701
|
});
|
|
1681
|
-
|
|
1682
|
-
mode: "fast",
|
|
1683
|
-
formats: ["date-time", "email", "hostname", "ipv4", "ipv6", "uri", "uri-reference"]
|
|
1684
|
-
});
|
|
1702
|
+
applyFulmenAjvFormats(ajv);
|
|
1685
1703
|
return ajv;
|
|
1686
1704
|
}
|
|
1687
1705
|
async function getAjv(dialect) {
|
|
@@ -1927,6 +1945,7 @@ var ajvInstances, metaschemaReady, schemaCache;
|
|
|
1927
1945
|
var init_validator = __esm({
|
|
1928
1946
|
"src/schema/validator.ts"() {
|
|
1929
1947
|
init_telemetry();
|
|
1948
|
+
init_ajv_formats();
|
|
1930
1949
|
init_errors();
|
|
1931
1950
|
init_registry();
|
|
1932
1951
|
init_utils();
|
|
@@ -3886,6 +3905,224 @@ var init_capabilities2 = __esm({
|
|
|
3886
3905
|
}
|
|
3887
3906
|
});
|
|
3888
3907
|
|
|
3908
|
+
// src/foundry/signals/config-reload-endpoint.ts
|
|
3909
|
+
function createConfigReloadEndpoint(options) {
|
|
3910
|
+
const { loader, validator, onReload: onReload2, auth, rateLimit, logger, telemetry } = options;
|
|
3911
|
+
return async (payload, req) => {
|
|
3912
|
+
const correlationId = payload.correlation_id ?? generateCorrelationId();
|
|
3913
|
+
const authResult = await auth(req);
|
|
3914
|
+
if (!authResult.authenticated) {
|
|
3915
|
+
if (logger) {
|
|
3916
|
+
logger.warn("Config reload endpoint: authentication failed", {
|
|
3917
|
+
correlation_id: correlationId,
|
|
3918
|
+
reason: authResult.reason
|
|
3919
|
+
});
|
|
3920
|
+
}
|
|
3921
|
+
if (telemetry) {
|
|
3922
|
+
telemetry.emit("fulmen.config.http_endpoint.auth_failed", {
|
|
3923
|
+
correlation_id: correlationId
|
|
3924
|
+
});
|
|
3925
|
+
}
|
|
3926
|
+
return {
|
|
3927
|
+
status: "error",
|
|
3928
|
+
error: "authentication_failed",
|
|
3929
|
+
message: authResult.reason || "Authentication required",
|
|
3930
|
+
statusCode: 401
|
|
3931
|
+
};
|
|
3932
|
+
}
|
|
3933
|
+
const identity = authResult.identity || "unknown";
|
|
3934
|
+
if (rateLimit) {
|
|
3935
|
+
const rateLimitResult = await rateLimit(identity);
|
|
3936
|
+
if (!rateLimitResult.allowed) {
|
|
3937
|
+
if (logger) {
|
|
3938
|
+
logger.warn("Config reload endpoint: rate limit exceeded", {
|
|
3939
|
+
correlation_id: correlationId,
|
|
3940
|
+
identity
|
|
3941
|
+
});
|
|
3942
|
+
}
|
|
3943
|
+
if (telemetry) {
|
|
3944
|
+
telemetry.emit("fulmen.config.http_endpoint.rate_limited", {
|
|
3945
|
+
correlation_id: correlationId
|
|
3946
|
+
});
|
|
3947
|
+
}
|
|
3948
|
+
return {
|
|
3949
|
+
status: "error",
|
|
3950
|
+
error: "rate_limit_exceeded",
|
|
3951
|
+
message: "Rate limit exceeded. Please try again later.",
|
|
3952
|
+
statusCode: 429
|
|
3953
|
+
};
|
|
3954
|
+
}
|
|
3955
|
+
}
|
|
3956
|
+
if (telemetry) {
|
|
3957
|
+
telemetry.emit("fulmen.config.http_endpoint.reload_requested", {
|
|
3958
|
+
correlation_id: correlationId
|
|
3959
|
+
});
|
|
3960
|
+
}
|
|
3961
|
+
try {
|
|
3962
|
+
const config = await loader();
|
|
3963
|
+
if (validator) {
|
|
3964
|
+
const validation = await validator(config);
|
|
3965
|
+
if (!validation.valid) {
|
|
3966
|
+
if (logger) {
|
|
3967
|
+
logger.warn("Config reload endpoint: validation failed", {
|
|
3968
|
+
correlation_id: correlationId,
|
|
3969
|
+
error_count: validation.errors?.length ?? 0
|
|
3970
|
+
});
|
|
3971
|
+
}
|
|
3972
|
+
if (telemetry) {
|
|
3973
|
+
telemetry.emit("fulmen.config.http_endpoint.reload_rejected", {
|
|
3974
|
+
correlation_id: correlationId,
|
|
3975
|
+
reason: "validation_failed"
|
|
3976
|
+
});
|
|
3977
|
+
}
|
|
3978
|
+
return {
|
|
3979
|
+
status: "error",
|
|
3980
|
+
error: "validation_failed",
|
|
3981
|
+
message: "Configuration validation failed",
|
|
3982
|
+
validation_errors: validation.errors,
|
|
3983
|
+
statusCode: 422
|
|
3984
|
+
};
|
|
3985
|
+
}
|
|
3986
|
+
}
|
|
3987
|
+
if (onReload2) {
|
|
3988
|
+
await onReload2(config);
|
|
3989
|
+
}
|
|
3990
|
+
if (telemetry) {
|
|
3991
|
+
telemetry.emit("fulmen.config.http_endpoint.reload_accepted", {
|
|
3992
|
+
correlation_id: correlationId
|
|
3993
|
+
});
|
|
3994
|
+
}
|
|
3995
|
+
if (logger) {
|
|
3996
|
+
logger.info("Config reload endpoint: reload accepted", {
|
|
3997
|
+
correlation_id: correlationId,
|
|
3998
|
+
reason: payload.reason
|
|
3999
|
+
});
|
|
4000
|
+
}
|
|
4001
|
+
return {
|
|
4002
|
+
status: "reloaded",
|
|
4003
|
+
correlation_id: correlationId,
|
|
4004
|
+
message: "Configuration reloaded",
|
|
4005
|
+
statusCode: 200
|
|
4006
|
+
};
|
|
4007
|
+
} catch (error) {
|
|
4008
|
+
if (logger) {
|
|
4009
|
+
logger.warn("Config reload endpoint: reload failed", {
|
|
4010
|
+
correlation_id: correlationId,
|
|
4011
|
+
error: error instanceof Error ? error.message : String(error)
|
|
4012
|
+
});
|
|
4013
|
+
}
|
|
4014
|
+
if (telemetry) {
|
|
4015
|
+
telemetry.emit("fulmen.config.http_endpoint.reload_error", {
|
|
4016
|
+
correlation_id: correlationId,
|
|
4017
|
+
error_type: error instanceof Error ? error.constructor.name : "unknown"
|
|
4018
|
+
});
|
|
4019
|
+
}
|
|
4020
|
+
return {
|
|
4021
|
+
status: "error",
|
|
4022
|
+
error: "reload_failed",
|
|
4023
|
+
message: error instanceof Error ? error.message : String(error),
|
|
4024
|
+
statusCode: 500
|
|
4025
|
+
};
|
|
4026
|
+
}
|
|
4027
|
+
};
|
|
4028
|
+
}
|
|
4029
|
+
function generateCorrelationId() {
|
|
4030
|
+
return `cfg-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
4031
|
+
}
|
|
4032
|
+
var init_config_reload_endpoint = __esm({
|
|
4033
|
+
"src/foundry/signals/config-reload-endpoint.ts"() {
|
|
4034
|
+
}
|
|
4035
|
+
});
|
|
4036
|
+
|
|
4037
|
+
// src/appidentity/runtime.ts
|
|
4038
|
+
function detectRuntime() {
|
|
4039
|
+
const versions = process.versions;
|
|
4040
|
+
if (typeof versions.bun === "string" && versions.bun.length > 0) {
|
|
4041
|
+
return { name: "bun", version: versions.bun };
|
|
4042
|
+
}
|
|
4043
|
+
if (typeof versions.node === "string" && versions.node.length > 0) {
|
|
4044
|
+
return { name: "node", version: versions.node };
|
|
4045
|
+
}
|
|
4046
|
+
return { name: "unknown" };
|
|
4047
|
+
}
|
|
4048
|
+
function buildRuntimeInfo(options = {}) {
|
|
4049
|
+
const runtime = detectRuntime();
|
|
4050
|
+
const serviceName = options.serviceName ?? options.identity?.app.binary_name ?? "unknown-service";
|
|
4051
|
+
const vendor = options.vendor ?? options.identity?.app.vendor;
|
|
4052
|
+
return {
|
|
4053
|
+
service: {
|
|
4054
|
+
name: serviceName,
|
|
4055
|
+
vendor,
|
|
4056
|
+
version: options.version
|
|
4057
|
+
},
|
|
4058
|
+
runtime,
|
|
4059
|
+
platform: {
|
|
4060
|
+
os: process.platform,
|
|
4061
|
+
arch: process.arch
|
|
4062
|
+
}
|
|
4063
|
+
};
|
|
4064
|
+
}
|
|
4065
|
+
var init_runtime = __esm({
|
|
4066
|
+
"src/appidentity/runtime.ts"() {
|
|
4067
|
+
}
|
|
4068
|
+
});
|
|
4069
|
+
|
|
4070
|
+
// src/foundry/signals/control-discovery-endpoint.ts
|
|
4071
|
+
function createControlDiscoveryEndpoint(options) {
|
|
4072
|
+
const { identity, version, endpoints, auth, authSummary, logger, telemetry } = options;
|
|
4073
|
+
return async (req) => {
|
|
4074
|
+
if (auth) {
|
|
4075
|
+
const authResult = await auth(req);
|
|
4076
|
+
if (!authResult.authenticated) {
|
|
4077
|
+
if (logger) {
|
|
4078
|
+
logger.warn("Control discovery endpoint: authentication failed", {
|
|
4079
|
+
reason: authResult.reason
|
|
4080
|
+
});
|
|
4081
|
+
}
|
|
4082
|
+
if (telemetry) {
|
|
4083
|
+
telemetry.emit("fulmen.control.discovery.auth_failed", {
|
|
4084
|
+
service: identity.app.binary_name
|
|
4085
|
+
});
|
|
4086
|
+
}
|
|
4087
|
+
return {
|
|
4088
|
+
status: "error",
|
|
4089
|
+
error: "authentication_failed",
|
|
4090
|
+
message: authResult.reason || "Authentication required",
|
|
4091
|
+
statusCode: 401
|
|
4092
|
+
};
|
|
4093
|
+
}
|
|
4094
|
+
}
|
|
4095
|
+
if (telemetry) {
|
|
4096
|
+
telemetry.emit("fulmen.control.discovery.served", {
|
|
4097
|
+
service: identity.app.binary_name
|
|
4098
|
+
});
|
|
4099
|
+
}
|
|
4100
|
+
const runtime = buildRuntimeInfo({ identity, version });
|
|
4101
|
+
return {
|
|
4102
|
+
status: "ok",
|
|
4103
|
+
service: {
|
|
4104
|
+
name: identity.app.binary_name,
|
|
4105
|
+
vendor: identity.app.vendor,
|
|
4106
|
+
version
|
|
4107
|
+
},
|
|
4108
|
+
runtime: {
|
|
4109
|
+
name: runtime.runtime.name,
|
|
4110
|
+
version: runtime.runtime.version,
|
|
4111
|
+
platform: runtime.platform.os,
|
|
4112
|
+
arch: runtime.platform.arch
|
|
4113
|
+
},
|
|
4114
|
+
auth_summary: authSummary,
|
|
4115
|
+
endpoints,
|
|
4116
|
+
statusCode: 200
|
|
4117
|
+
};
|
|
4118
|
+
};
|
|
4119
|
+
}
|
|
4120
|
+
var init_control_discovery_endpoint = __esm({
|
|
4121
|
+
"src/foundry/signals/control-discovery-endpoint.ts"() {
|
|
4122
|
+
init_runtime();
|
|
4123
|
+
}
|
|
4124
|
+
});
|
|
4125
|
+
|
|
3889
4126
|
// src/foundry/signals/convenience.ts
|
|
3890
4127
|
async function onShutdown(manager, handler, options = {}) {
|
|
3891
4128
|
await manager.register("SIGTERM", handler, options);
|
|
@@ -4145,7 +4382,7 @@ var init_guards = __esm({
|
|
|
4145
4382
|
function createSignalEndpoint(options) {
|
|
4146
4383
|
const { manager, auth, rateLimit, logger, telemetry, allowedSignals } = options;
|
|
4147
4384
|
return async (payload, req) => {
|
|
4148
|
-
const correlationId = payload.correlation_id ??
|
|
4385
|
+
const correlationId = payload.correlation_id ?? generateCorrelationId2();
|
|
4149
4386
|
const authResult = await auth(req);
|
|
4150
4387
|
if (!authResult.authenticated) {
|
|
4151
4388
|
if (logger) {
|
|
@@ -4268,7 +4505,7 @@ function normalizeSignalName(signal) {
|
|
|
4268
4505
|
}
|
|
4269
4506
|
return `SIG${upper}`;
|
|
4270
4507
|
}
|
|
4271
|
-
function
|
|
4508
|
+
function generateCorrelationId2() {
|
|
4272
4509
|
return `sig-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
4273
4510
|
}
|
|
4274
4511
|
function createBearerTokenAuth(expectedToken) {
|
|
@@ -4735,6 +4972,8 @@ var init_signals = __esm({
|
|
|
4735
4972
|
"src/foundry/signals/index.ts"() {
|
|
4736
4973
|
init_capabilities2();
|
|
4737
4974
|
init_catalog();
|
|
4975
|
+
init_config_reload_endpoint();
|
|
4976
|
+
init_control_discovery_endpoint();
|
|
4738
4977
|
init_convenience();
|
|
4739
4978
|
init_double_tap();
|
|
4740
4979
|
init_guards();
|
|
@@ -4880,7 +5119,9 @@ __export(foundry_exports, {
|
|
|
4880
5119
|
clearMimeTypeCache: () => clearMimeTypeCache,
|
|
4881
5120
|
clearPatternCache: () => clearPatternCache,
|
|
4882
5121
|
createBearerTokenAuth: () => createBearerTokenAuth,
|
|
5122
|
+
createConfigReloadEndpoint: () => createConfigReloadEndpoint,
|
|
4883
5123
|
createConfigReloadHandler: () => createConfigReloadHandler,
|
|
5124
|
+
createControlDiscoveryEndpoint: () => createControlDiscoveryEndpoint,
|
|
4884
5125
|
createDoubleTapTracker: () => createDoubleTapTracker,
|
|
4885
5126
|
createSignalEndpoint: () => createSignalEndpoint,
|
|
4886
5127
|
createSignalManager: () => createSignalManager,
|
|
@@ -5650,6 +5891,7 @@ var init_cli = __esm({
|
|
|
5650
5891
|
// src/schema/index.ts
|
|
5651
5892
|
var init_schema = __esm({
|
|
5652
5893
|
"src/schema/index.ts"() {
|
|
5894
|
+
init_ajv_formats();
|
|
5653
5895
|
init_cli();
|
|
5654
5896
|
init_errors();
|
|
5655
5897
|
init_export();
|
|
@@ -10780,6 +11022,7 @@ __export(appidentity_exports, {
|
|
|
10780
11022
|
AppIdentityError: () => AppIdentityError,
|
|
10781
11023
|
MAX_ANCESTOR_SEARCH_DEPTH: () => MAX_ANCESTOR_SEARCH_DEPTH,
|
|
10782
11024
|
buildEnvVar: () => buildEnvVar,
|
|
11025
|
+
buildRuntimeInfo: () => buildRuntimeInfo,
|
|
10783
11026
|
clearEmbeddedIdentity: () => clearEmbeddedIdentity,
|
|
10784
11027
|
clearIdentityCache: () => clearIdentityCache,
|
|
10785
11028
|
getBinaryName: () => getBinaryName,
|
|
@@ -10802,6 +11045,7 @@ var init_appidentity = __esm({
|
|
|
10802
11045
|
init_errors4();
|
|
10803
11046
|
init_helpers();
|
|
10804
11047
|
init_loader2();
|
|
11048
|
+
init_runtime();
|
|
10805
11049
|
}
|
|
10806
11050
|
});
|
|
10807
11051
|
|