@sockethub/schemas 3.0.0-beta.0 → 3.0.0-beta.1

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.
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Ajv compiles JSON schemas with `new Function`. Environments that forbid eval
3
+ * — a browser-extension page under a Manifest V3 Content Security Policy, or
4
+ * some sandboxes — block that call, which would otherwise make importing this
5
+ * package throw before a single schema is used. Detect availability once so
6
+ * validation can be skipped there.
7
+ *
8
+ * Skipping client-side validation is safe: the Sockethub server validates every
9
+ * inbound message against the same schemas.
10
+ */
11
+ /**
12
+ * Report whether the environment allows code generation, i.e. whether
13
+ * `new Function` succeeds. The result is probed once and cached, so callers may
14
+ * invoke this freely.
15
+ */
16
+ export declare function isCodegenAvailable(): boolean;
17
+ /** Emit a one-time notice that schema validation is disabled. */
18
+ export declare function warnCodegenUnavailable(): void;
19
+ /**
20
+ * Force the codegen-availability result. Test-only seam for exercising the
21
+ * CSP fallback; pass `undefined` to restore detection.
22
+ */
23
+ export declare function setCodegenAvailableForTesting(value?: boolean): void;
package/dist/index.d.ts CHANGED
@@ -6,6 +6,7 @@ import { SockethubConfigSchema, SockethubConfigSchemaId } from "./schemas/socket
6
6
  import { type ServiceDescriptor, ServiceDescriptorSchema, type ServiceEndpoints, validateServiceDescriptor } from "./service-descriptor.js";
7
7
  import { addPlatformContext, addPlatformSchema, getPlatformSchema, registerSystemPlatformContexts, resolvePlatformId, setValidationErrorOptions, validateActivityStream, validateActivityStreamResponse, validateCredentials, validatePlatformSchema, validateSockethubConfig } from "./validator.js";
8
8
  export { normalizeActivityStream } from "./activity-stream-helper.js";
9
+ export { isCodegenAvailable } from "./helpers/codegen.js";
9
10
  export { AS2_BASE_CONTEXT_URL, SOCKETHUB_BASE_CONTEXT_URL, PLATFORM_CONTEXT_PREFIX, ERROR_PLATFORM_ID, ERROR_PLATFORM_CONTEXT_URL, INTERNAL_PLATFORM_ID, INTERNAL_PLATFORM_CONTEXT_URL, buildCanonicalContext, platformIdFromContext, addPlatformContext, addPlatformSchema, getPlatformSchema, resolvePlatformId, registerSystemPlatformContexts, validatePlatformSchema, validateCredentials, validateActivityStream, validateActivityStreamResponse, validateServiceDescriptor, validateSockethubConfig, setValidationErrorOptions, PlatformSchema, ServiceDescriptorSchema, ActivityStreamSchema, SockethubConfigSchema, SockethubConfigSchemaId, ObjectTypesList, ObjectTypesSchema, InternalObjectTypesList, };
10
11
  export type { ServiceDescriptor, ServiceEndpoints };
11
12
  export * from "./types.js";
package/dist/index.js CHANGED
@@ -16112,7 +16112,7 @@ var PlatformSchema = {
16112
16112
  var package_default = {
16113
16113
  name: "@sockethub/schemas",
16114
16114
  description: "JSON schema files for validating Sockethub Activity Streams",
16115
- version: "3.0.0-beta.0",
16115
+ version: "3.0.0-beta.1",
16116
16116
  type: "module",
16117
16117
  private: false,
16118
16118
  author: "Nick Jennings <nick@silverbucket.net>",
@@ -16182,7 +16182,7 @@ var package_default = {
16182
16182
  "ajv-formats": "^2.1.1",
16183
16183
  "ajv-formats-draft2019": "^1.6.1"
16184
16184
  },
16185
- gitHead: "75002ae8f15d7679bd58a9327f5a1d7eeaffa237",
16185
+ gitHead: "06c9062f1cb5f0c0599fd979e6e91da79f08eda0",
16186
16186
  types: "./dist/index.d.ts"
16187
16187
  };
16188
16188
 
@@ -16344,7 +16344,8 @@ var SockethubConfigSchema = {
16344
16344
  type: "object",
16345
16345
  additionalProperties: false,
16346
16346
  properties: {
16347
- connectTimeoutMs: { type: "number" }
16347
+ connectTimeoutMs: { type: "number" },
16348
+ allowPrivateAddresses: { type: "boolean" }
16348
16349
  }
16349
16350
  },
16350
16351
  "@sockethub/platform-metadata": {
@@ -16434,11 +16435,23 @@ var SockethubConfigSchema = {
16434
16435
  type: "object",
16435
16436
  additionalProperties: false,
16436
16437
  properties: {
16438
+ maxInstancesPerSession: {
16439
+ type: "integer",
16440
+ minimum: 0,
16441
+ default: 10,
16442
+ description: "Maximum persistent instances per socket session. 0 disables the cap."
16443
+ },
16444
+ maxInstancesPerIp: {
16445
+ type: "integer",
16446
+ minimum: 0,
16447
+ default: 20,
16448
+ description: "Maximum persistent instances per client IP, including HTTP actions. 0 disables the cap."
16449
+ },
16437
16450
  maxPlatformInstances: {
16438
16451
  type: "number",
16439
16452
  minimum: 0,
16440
16453
  default: 100,
16441
- description: "Upper bound on concurrently running platform instances " + "(child processes). Each persistent-platform actor forks " + "its own process, so an unbounded count is a resource " + "exhaustion risk on public instances. 0 disables the cap."
16454
+ description: "Upper bound on concurrently running persistent platform instances " + "(child processes). Each persistent-platform actor forks " + "its own process, so an unbounded count is a resource " + "exhaustion risk on public instances. 0 disables the cap."
16442
16455
  }
16443
16456
  }
16444
16457
  },
@@ -16622,6 +16635,28 @@ var SockethubConfigSchemaId = versionedSchemaId(SockethubConfigSchema.$id, packa
16622
16635
  // src/service-descriptor.ts
16623
16636
  var import_ajv = __toESM(require_ajv(), 1);
16624
16637
 
16638
+ // src/helpers/codegen.ts
16639
+ var available;
16640
+ var warned = false;
16641
+ function isCodegenAvailable() {
16642
+ if (available === undefined) {
16643
+ try {
16644
+ new Function("return true");
16645
+ available = true;
16646
+ } catch {
16647
+ available = false;
16648
+ }
16649
+ }
16650
+ return available;
16651
+ }
16652
+ function warnCodegenUnavailable() {
16653
+ if (warned) {
16654
+ return;
16655
+ }
16656
+ warned = true;
16657
+ console.warn("[@sockethub/schemas] Schema validation is disabled: this environment's Content Security Policy blocks `new Function`, which Ajv needs to compile schemas. The Sockethub server still validates every message.");
16658
+ }
16659
+
16625
16660
  // src/schemas/service-descriptor.ts
16626
16661
  var apiVersion = {
16627
16662
  type: "integer",
@@ -16666,12 +16701,65 @@ var ServiceDescriptorSchema = {
16666
16701
  };
16667
16702
 
16668
16703
  // src/service-descriptor.ts
16669
- var ajv = new import_ajv.default({ strictTypes: false, allErrors: true });
16704
+ var ajv;
16670
16705
  var validator;
16671
16706
  function validateServiceDescriptor(descriptor) {
16707
+ if (!isCodegenAvailable()) {
16708
+ warnCodegenUnavailable();
16709
+ return isServiceDescriptorShape(descriptor);
16710
+ }
16711
+ if (!ajv) {
16712
+ ajv = new import_ajv.default({ strictTypes: false, allErrors: true });
16713
+ }
16672
16714
  validator ??= ajv.compile(ServiceDescriptorSchema);
16673
16715
  return validator(descriptor);
16674
16716
  }
16717
+ function isServiceDescriptorShape(descriptor) {
16718
+ if (!descriptor || typeof descriptor !== "object") {
16719
+ return false;
16720
+ }
16721
+ const value = descriptor;
16722
+ if (value.name !== "sockethub") {
16723
+ return false;
16724
+ }
16725
+ if (!isApiVersion(value.apiVersion)) {
16726
+ return false;
16727
+ }
16728
+ if (!Array.isArray(value.platforms)) {
16729
+ return false;
16730
+ }
16731
+ for (const platform of value.platforms) {
16732
+ if (!platform || typeof platform !== "object") {
16733
+ return false;
16734
+ }
16735
+ const entry = platform;
16736
+ if (typeof entry.id !== "string" || entry.id.length === 0) {
16737
+ return false;
16738
+ }
16739
+ if (!isApiVersion(entry.apiVersion)) {
16740
+ return false;
16741
+ }
16742
+ }
16743
+ if (value.endpoints !== undefined) {
16744
+ if (!value.endpoints || typeof value.endpoints !== "object") {
16745
+ return false;
16746
+ }
16747
+ const endpoints = value.endpoints;
16748
+ if (!isAbsolutePath(endpoints.socketIO)) {
16749
+ return false;
16750
+ }
16751
+ if (endpoints.httpActions !== undefined && !isAbsolutePath(endpoints.httpActions)) {
16752
+ return false;
16753
+ }
16754
+ }
16755
+ return true;
16756
+ }
16757
+ function isApiVersion(value) {
16758
+ return typeof value === "number" && Number.isInteger(value) && value >= 0;
16759
+ }
16760
+ function isAbsolutePath(value) {
16761
+ return typeof value === "string" && /^\/(?![/\\])[^\s\\]*$/.test(value);
16762
+ }
16675
16763
 
16676
16764
  // src/validator.ts
16677
16765
  var import_ajv2 = __toESM(require_ajv(), 1);
@@ -16688,8 +16776,12 @@ function parseMsg(error) {
16688
16776
  }
16689
16777
  return err;
16690
16778
  }
16691
- function getTypeList(msg) {
16779
+ var MAX_TYPE_LIST_DEPTH = 64;
16780
+ function getTypeList(msg, depth = 0) {
16692
16781
  const types = [];
16782
+ if (depth > MAX_TYPE_LIST_DEPTH) {
16783
+ return types;
16784
+ }
16693
16785
  if (msg?.type) {
16694
16786
  types.push(msg.type);
16695
16787
  }
@@ -16697,7 +16789,7 @@ function getTypeList(msg) {
16697
16789
  for (const prop in record) {
16698
16790
  const value = record[prop];
16699
16791
  if (value && typeof value === "object" && "type" in value) {
16700
- types.push(...getTypeList(value));
16792
+ types.push(...getTypeList(value, depth + 1));
16701
16793
  }
16702
16794
  }
16703
16795
  return types;
@@ -16779,26 +16871,41 @@ function composeFinalError(error, options) {
16779
16871
  }
16780
16872
 
16781
16873
  // src/validator.ts
16782
- var ajv2 = new import_ajv2.default({ strictTypes: false, allErrors: true });
16783
- import_ajv_formats.default(ajv2);
16784
- import_ajv_formats_draft2019.default(ajv2);
16785
16874
  var schemaURL = "https://sockethub.org/schemas/v0";
16786
16875
  var schemas = {};
16787
16876
  var validationErrorOptions = {};
16788
16877
  var systemContextsRegistered = false;
16789
16878
  schemas[`${schemaURL}/activity-stream`] = ActivityStreamSchema;
16790
- for (const uri in schemas) {
16791
- ajv2.addSchema(schemas[uri], uri);
16879
+ var ajv2;
16880
+ function getAjv() {
16881
+ if (!isCodegenAvailable()) {
16882
+ warnCodegenUnavailable();
16883
+ return;
16884
+ }
16885
+ if (!ajv2) {
16886
+ const instance = new import_ajv2.default({ strictTypes: false, allErrors: true });
16887
+ import_ajv_formats.default(instance);
16888
+ import_ajv_formats_draft2019.default(instance);
16889
+ for (const uri in schemas) {
16890
+ instance.addSchema(schemas[uri], uri);
16891
+ }
16892
+ ajv2 = instance;
16893
+ }
16894
+ return ajv2;
16792
16895
  }
16793
16896
  function registerSystemContext(platformId, contextUrl) {
16794
16897
  registerPlatformContext(platformId, contextUrl, `${schemaURL}/context/${platformId}/messages`, `${schemaURL}/context/${platformId}/credentials`);
16898
+ const instance = getAjv();
16899
+ if (!instance) {
16900
+ return;
16901
+ }
16795
16902
  const messageSchemaRef = `${schemaURL}/context/${platformId}/messages`;
16796
- if (!ajv2.getSchema(messageSchemaRef)) {
16797
- ajv2.addSchema({}, messageSchemaRef);
16903
+ if (!instance.getSchema(messageSchemaRef)) {
16904
+ instance.addSchema({}, messageSchemaRef);
16798
16905
  }
16799
16906
  const credentialsSchemaRef = `${schemaURL}/context/${platformId}/credentials`;
16800
- if (!ajv2.getSchema(credentialsSchemaRef)) {
16801
- ajv2.addSchema({}, credentialsSchemaRef);
16907
+ if (!instance.getSchema(credentialsSchemaRef)) {
16908
+ instance.addSchema({}, credentialsSchemaRef);
16802
16909
  }
16803
16910
  }
16804
16911
  function registerSystemPlatformContexts() {
@@ -16811,7 +16918,11 @@ function registerSystemPlatformContexts() {
16811
16918
  }
16812
16919
  registerSystemPlatformContexts();
16813
16920
  function handleValidation(schemaRef, msg) {
16814
- const validator = ajv2.getSchema(schemaRef);
16921
+ const instance = getAjv();
16922
+ if (!instance) {
16923
+ return "";
16924
+ }
16925
+ const validator = instance.getSchema(schemaRef);
16815
16926
  if (!validator) {
16816
16927
  return `schema ${schemaRef} not found`;
16817
16928
  }
@@ -16836,17 +16947,25 @@ function setValidationErrorOptions(options) {
16836
16947
  }
16837
16948
  var sockethubConfigValidator;
16838
16949
  function validateSockethubConfig(config) {
16950
+ const instance = getAjv();
16951
+ if (!instance) {
16952
+ return "";
16953
+ }
16839
16954
  if (!sockethubConfigValidator) {
16840
- sockethubConfigValidator = ajv2.compile(SockethubConfigSchema);
16955
+ sockethubConfigValidator = instance.compile(SockethubConfigSchema);
16841
16956
  }
16842
16957
  if (sockethubConfigValidator(config)) {
16843
16958
  return "";
16844
16959
  }
16845
- return ajv2.errorsText(sockethubConfigValidator.errors, {
16960
+ return instance.errorsText(sockethubConfigValidator.errors, {
16846
16961
  dataVar: "config"
16847
16962
  });
16848
16963
  }
16849
16964
  function validateActivityStream(msg) {
16965
+ if (!isCodegenAvailable()) {
16966
+ warnCodegenUnavailable();
16967
+ return "";
16968
+ }
16850
16969
  const streamValidationError = handleValidation(`${schemaURL}/activity-stream`, msg);
16851
16970
  if (streamValidationError) {
16852
16971
  return streamValidationError;
@@ -16862,6 +16981,10 @@ function validateActivityStream(msg) {
16862
16981
  return handleValidation(schemaId, msg);
16863
16982
  }
16864
16983
  function validateActivityStreamResponse(msg) {
16984
+ if (!isCodegenAvailable()) {
16985
+ warnCodegenUnavailable();
16986
+ return "";
16987
+ }
16865
16988
  const platformContextUrl = resolvePlatformContextUrl(msg);
16866
16989
  if (!platformContextUrl) {
16867
16990
  return "";
@@ -16871,12 +16994,17 @@ function validateActivityStreamResponse(msg) {
16871
16994
  return "";
16872
16995
  }
16873
16996
  const responsesSchemaId = `${schemaURL}/context/${platformId}/responses`;
16874
- if (!ajv2.getSchema(responsesSchemaId)) {
16997
+ const instance = getAjv();
16998
+ if (!instance || !instance.getSchema(responsesSchemaId)) {
16875
16999
  return "";
16876
17000
  }
16877
17001
  return handleValidation(responsesSchemaId, msg);
16878
17002
  }
16879
17003
  function validateCredentials(msg) {
17004
+ if (!isCodegenAvailable()) {
17005
+ warnCodegenUnavailable();
17006
+ return "";
17007
+ }
16880
17008
  if (!Array.isArray(msg["@context"])) {
16881
17009
  return "credential activity streams must have an @context set";
16882
17010
  }
@@ -16898,15 +17026,18 @@ function validateCredentials(msg) {
16898
17026
  return handleValidation(credentialsSchemaId, msg);
16899
17027
  }
16900
17028
  function validatePlatformSchema(schema) {
16901
- const validate = ajv2.compile(PlatformSchema);
16902
- const err = validate(schema);
16903
- if (!err) {
16904
- const validationError = validate.errors[0];
16905
- let message = `${validationError.instancePath} ${validationError.message}`;
16906
- if (validationError.keyword === "additionalProperties") {
16907
- message += `: ${validationError.params.additionalProperty}`;
17029
+ const instance = getAjv();
17030
+ if (instance) {
17031
+ const validate = instance.compile(PlatformSchema);
17032
+ const err = validate(schema);
17033
+ if (!err) {
17034
+ const validationError = validate.errors?.[0];
17035
+ let message = `${validationError?.instancePath ?? ""} ${validationError?.message ?? "is invalid"}`;
17036
+ if (validationError?.keyword === "additionalProperties") {
17037
+ message += `: ${validationError.params.additionalProperty}`;
17038
+ }
17039
+ return `platform schema failed to validate: ${message}`;
16908
17040
  }
16909
- return `platform schema failed to validate: ${message}`;
16910
17041
  }
16911
17042
  const platform = schema;
16912
17043
  const messages = platform.messages;
@@ -16948,13 +17079,17 @@ function validatePlatformSchema(schema) {
16948
17079
  return "";
16949
17080
  }
16950
17081
  function addPlatformSchema(schema, platform_type) {
17082
+ const instance = getAjv();
17083
+ if (!instance) {
17084
+ return;
17085
+ }
16951
17086
  const schemaRef = `${schemaURL}/context/${platform_type}`;
16952
- if (!ajv2.getSchema(schemaRef)) {
16953
- ajv2.addSchema(schema, schemaRef);
17087
+ if (!instance.getSchema(schemaRef)) {
17088
+ instance.addSchema(schema, schemaRef);
16954
17089
  }
16955
17090
  }
16956
17091
  function getPlatformSchema(platform_type) {
16957
- return ajv2.getSchema(`${schemaURL}/context/${platform_type}`);
17092
+ return getAjv()?.getSchema(`${schemaURL}/context/${platform_type}`);
16958
17093
  }
16959
17094
  function addPlatformContext(platformId, platformContextUrl) {
16960
17095
  registerPlatformContext(platformId, platformContextUrl, `${schemaURL}/context/${platformId}/messages`, `${schemaURL}/context/${platformId}/credentials`);
@@ -17018,6 +17153,7 @@ export {
17018
17153
  addPlatformSchema,
17019
17154
  buildCanonicalContext,
17020
17155
  getPlatformSchema,
17156
+ isCodegenAvailable,
17021
17157
  normalizeActivityStream,
17022
17158
  platformIdFromContext,
17023
17159
  registerSystemPlatformContexts,
@@ -17031,4 +17167,4 @@ export {
17031
17167
  validateSockethubConfig
17032
17168
  };
17033
17169
 
17034
- //# debugId=878BEB7D547F15C164756E2164756E21
17170
+ //# debugId=835ED6EDFB33FD9B64756E2164756E21