@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.
@@ -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
- addFormats(ajv, {
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 ?? generateCorrelationId();
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 generateCorrelationId() {
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