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

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,8 @@
1
+ {
2
+ "@context": {
3
+ "as": "https://www.w3.org/ns/activitystreams#",
4
+ "sh": "https://sockethub.org/ns#",
5
+ "platform": "sh:platform",
6
+ "emailType": "sh:emailType"
7
+ }
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "@context": {
3
+ "as": "https://www.w3.org/ns/activitystreams#",
4
+ "sh": "https://sockethub.org/ns#",
5
+ "platform": "sh:platform",
6
+ "instagramType": "sh:instagramType"
7
+ }
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "@context": {
3
+ "as": "https://www.w3.org/ns/activitystreams#",
4
+ "sh": "https://sockethub.org/ns#",
5
+ "platform": "sh:platform",
6
+ "messengerType": "sh:messengerType"
7
+ }
8
+ }
@@ -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.2",
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: "1f74d4e07311496f0acc021855137bc197d79eab",
16186
16186
  types: "./dist/index.d.ts"
16187
16187
  };
16188
16188
 
@@ -16287,8 +16287,11 @@ var SockethubConfigSchema = {
16287
16287
  "@sockethub/platform-caldav",
16288
16288
  "@sockethub/platform-dummy",
16289
16289
  "@sockethub/platform-feeds",
16290
+ "@sockethub/platform-email",
16290
16291
  "@sockethub/platform-irc",
16291
16292
  "@sockethub/platform-metadata",
16293
+ "@sockethub/platform-messenger",
16294
+ "@sockethub/platform-instagram",
16292
16295
  "@sockethub/platform-xmpp"
16293
16296
  ]
16294
16297
  },
@@ -16304,7 +16307,8 @@ var SockethubConfigSchema = {
16304
16307
  connectTimeoutMs: { type: "integer", minimum: 1 },
16305
16308
  allowPrivateAddresses: { type: "boolean" },
16306
16309
  allowInsecureHttp: { type: "boolean" },
16307
- concurrency: { type: "integer", minimum: 1 }
16310
+ concurrency: { type: "integer", minimum: 1 },
16311
+ discoveryCacheTtlMs: { type: "integer", minimum: 0 }
16308
16312
  }
16309
16313
  },
16310
16314
  "@sockethub/platform-caldav": {
@@ -16314,7 +16318,20 @@ var SockethubConfigSchema = {
16314
16318
  connectTimeoutMs: { type: "integer", minimum: 1 },
16315
16319
  allowPrivateAddresses: { type: "boolean" },
16316
16320
  allowInsecureHttp: { type: "boolean" },
16317
- concurrency: { type: "integer", minimum: 1 }
16321
+ concurrency: { type: "integer", minimum: 1 },
16322
+ discoveryCacheTtlMs: { type: "integer", minimum: 0 }
16323
+ }
16324
+ },
16325
+ "@sockethub/platform-email": {
16326
+ type: "object",
16327
+ additionalProperties: false,
16328
+ properties: {
16329
+ connectTimeoutMs: {
16330
+ type: "integer",
16331
+ minimum: 5000,
16332
+ maximum: 120000
16333
+ },
16334
+ allowPrivateAddresses: { type: "boolean" }
16318
16335
  }
16319
16336
  },
16320
16337
  "@sockethub/platform-dummy": {
@@ -16337,14 +16354,16 @@ var SockethubConfigSchema = {
16337
16354
  type: "object",
16338
16355
  additionalProperties: false,
16339
16356
  properties: {
16340
- connectTimeoutMs: { type: "number" }
16357
+ connectTimeoutMs: { type: "number" },
16358
+ allowPrivateAddresses: { type: "boolean" }
16341
16359
  }
16342
16360
  },
16343
16361
  "@sockethub/platform-xmpp": {
16344
16362
  type: "object",
16345
16363
  additionalProperties: false,
16346
16364
  properties: {
16347
- connectTimeoutMs: { type: "number" }
16365
+ connectTimeoutMs: { type: "number" },
16366
+ allowPrivateAddresses: { type: "boolean" }
16348
16367
  }
16349
16368
  },
16350
16369
  "@sockethub/platform-metadata": {
@@ -16434,11 +16453,29 @@ var SockethubConfigSchema = {
16434
16453
  type: "object",
16435
16454
  additionalProperties: false,
16436
16455
  properties: {
16456
+ maxInstancesPerSession: {
16457
+ type: "integer",
16458
+ minimum: 0,
16459
+ default: 10,
16460
+ description: "Maximum persistent instances per socket session. 0 disables the cap."
16461
+ },
16462
+ maxInstancesPerIp: {
16463
+ type: "integer",
16464
+ minimum: 0,
16465
+ default: 20,
16466
+ description: "Maximum persistent instances per client IP, including HTTP actions. 0 disables the cap."
16467
+ },
16468
+ maxStartsPerIpPerMinute: {
16469
+ type: "integer",
16470
+ minimum: 0,
16471
+ default: 60,
16472
+ description: "Maximum new persistent instances a client IP may start per minute, " + "including HTTP actions. Bounds fork/teardown churn that the " + "concurrent caps allow. Reusing a running instance does not count. " + "0 disables the cap."
16473
+ },
16437
16474
  maxPlatformInstances: {
16438
16475
  type: "number",
16439
16476
  minimum: 0,
16440
16477
  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."
16478
+ 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
16479
  }
16443
16480
  }
16444
16481
  },
@@ -16622,6 +16659,28 @@ var SockethubConfigSchemaId = versionedSchemaId(SockethubConfigSchema.$id, packa
16622
16659
  // src/service-descriptor.ts
16623
16660
  var import_ajv = __toESM(require_ajv(), 1);
16624
16661
 
16662
+ // src/helpers/codegen.ts
16663
+ var available;
16664
+ var warned = false;
16665
+ function isCodegenAvailable() {
16666
+ if (available === undefined) {
16667
+ try {
16668
+ new Function("return true");
16669
+ available = true;
16670
+ } catch {
16671
+ available = false;
16672
+ }
16673
+ }
16674
+ return available;
16675
+ }
16676
+ function warnCodegenUnavailable() {
16677
+ if (warned) {
16678
+ return;
16679
+ }
16680
+ warned = true;
16681
+ 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.");
16682
+ }
16683
+
16625
16684
  // src/schemas/service-descriptor.ts
16626
16685
  var apiVersion = {
16627
16686
  type: "integer",
@@ -16666,12 +16725,65 @@ var ServiceDescriptorSchema = {
16666
16725
  };
16667
16726
 
16668
16727
  // src/service-descriptor.ts
16669
- var ajv = new import_ajv.default({ strictTypes: false, allErrors: true });
16728
+ var ajv;
16670
16729
  var validator;
16671
16730
  function validateServiceDescriptor(descriptor) {
16731
+ if (!isCodegenAvailable()) {
16732
+ warnCodegenUnavailable();
16733
+ return isServiceDescriptorShape(descriptor);
16734
+ }
16735
+ if (!ajv) {
16736
+ ajv = new import_ajv.default({ strictTypes: false, allErrors: true });
16737
+ }
16672
16738
  validator ??= ajv.compile(ServiceDescriptorSchema);
16673
16739
  return validator(descriptor);
16674
16740
  }
16741
+ function isServiceDescriptorShape(descriptor) {
16742
+ if (!descriptor || typeof descriptor !== "object") {
16743
+ return false;
16744
+ }
16745
+ const value = descriptor;
16746
+ if (value.name !== "sockethub") {
16747
+ return false;
16748
+ }
16749
+ if (!isApiVersion(value.apiVersion)) {
16750
+ return false;
16751
+ }
16752
+ if (!Array.isArray(value.platforms)) {
16753
+ return false;
16754
+ }
16755
+ for (const platform of value.platforms) {
16756
+ if (!platform || typeof platform !== "object") {
16757
+ return false;
16758
+ }
16759
+ const entry = platform;
16760
+ if (typeof entry.id !== "string" || entry.id.length === 0) {
16761
+ return false;
16762
+ }
16763
+ if (!isApiVersion(entry.apiVersion)) {
16764
+ return false;
16765
+ }
16766
+ }
16767
+ if (value.endpoints !== undefined) {
16768
+ if (!value.endpoints || typeof value.endpoints !== "object") {
16769
+ return false;
16770
+ }
16771
+ const endpoints = value.endpoints;
16772
+ if (!isAbsolutePath(endpoints.socketIO)) {
16773
+ return false;
16774
+ }
16775
+ if (endpoints.httpActions !== undefined && !isAbsolutePath(endpoints.httpActions)) {
16776
+ return false;
16777
+ }
16778
+ }
16779
+ return true;
16780
+ }
16781
+ function isApiVersion(value) {
16782
+ return typeof value === "number" && Number.isInteger(value) && value >= 0;
16783
+ }
16784
+ function isAbsolutePath(value) {
16785
+ return typeof value === "string" && /^\/(?![/\\])[^\s\\]*$/.test(value);
16786
+ }
16675
16787
 
16676
16788
  // src/validator.ts
16677
16789
  var import_ajv2 = __toESM(require_ajv(), 1);
@@ -16688,8 +16800,12 @@ function parseMsg(error) {
16688
16800
  }
16689
16801
  return err;
16690
16802
  }
16691
- function getTypeList(msg) {
16803
+ var MAX_TYPE_LIST_DEPTH = 64;
16804
+ function getTypeList(msg, depth = 0) {
16692
16805
  const types = [];
16806
+ if (depth > MAX_TYPE_LIST_DEPTH) {
16807
+ return types;
16808
+ }
16693
16809
  if (msg?.type) {
16694
16810
  types.push(msg.type);
16695
16811
  }
@@ -16697,7 +16813,7 @@ function getTypeList(msg) {
16697
16813
  for (const prop in record) {
16698
16814
  const value = record[prop];
16699
16815
  if (value && typeof value === "object" && "type" in value) {
16700
- types.push(...getTypeList(value));
16816
+ types.push(...getTypeList(value, depth + 1));
16701
16817
  }
16702
16818
  }
16703
16819
  return types;
@@ -16779,26 +16895,41 @@ function composeFinalError(error, options) {
16779
16895
  }
16780
16896
 
16781
16897
  // 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
16898
  var schemaURL = "https://sockethub.org/schemas/v0";
16786
16899
  var schemas = {};
16787
16900
  var validationErrorOptions = {};
16788
16901
  var systemContextsRegistered = false;
16789
16902
  schemas[`${schemaURL}/activity-stream`] = ActivityStreamSchema;
16790
- for (const uri in schemas) {
16791
- ajv2.addSchema(schemas[uri], uri);
16903
+ var ajv2;
16904
+ function getAjv() {
16905
+ if (!isCodegenAvailable()) {
16906
+ warnCodegenUnavailable();
16907
+ return;
16908
+ }
16909
+ if (!ajv2) {
16910
+ const instance = new import_ajv2.default({ strictTypes: false, allErrors: true });
16911
+ import_ajv_formats.default(instance);
16912
+ import_ajv_formats_draft2019.default(instance);
16913
+ for (const uri in schemas) {
16914
+ instance.addSchema(schemas[uri], uri);
16915
+ }
16916
+ ajv2 = instance;
16917
+ }
16918
+ return ajv2;
16792
16919
  }
16793
16920
  function registerSystemContext(platformId, contextUrl) {
16794
16921
  registerPlatformContext(platformId, contextUrl, `${schemaURL}/context/${platformId}/messages`, `${schemaURL}/context/${platformId}/credentials`);
16922
+ const instance = getAjv();
16923
+ if (!instance) {
16924
+ return;
16925
+ }
16795
16926
  const messageSchemaRef = `${schemaURL}/context/${platformId}/messages`;
16796
- if (!ajv2.getSchema(messageSchemaRef)) {
16797
- ajv2.addSchema({}, messageSchemaRef);
16927
+ if (!instance.getSchema(messageSchemaRef)) {
16928
+ instance.addSchema({}, messageSchemaRef);
16798
16929
  }
16799
16930
  const credentialsSchemaRef = `${schemaURL}/context/${platformId}/credentials`;
16800
- if (!ajv2.getSchema(credentialsSchemaRef)) {
16801
- ajv2.addSchema({}, credentialsSchemaRef);
16931
+ if (!instance.getSchema(credentialsSchemaRef)) {
16932
+ instance.addSchema({}, credentialsSchemaRef);
16802
16933
  }
16803
16934
  }
16804
16935
  function registerSystemPlatformContexts() {
@@ -16811,7 +16942,11 @@ function registerSystemPlatformContexts() {
16811
16942
  }
16812
16943
  registerSystemPlatformContexts();
16813
16944
  function handleValidation(schemaRef, msg) {
16814
- const validator = ajv2.getSchema(schemaRef);
16945
+ const instance = getAjv();
16946
+ if (!instance) {
16947
+ return "";
16948
+ }
16949
+ const validator = instance.getSchema(schemaRef);
16815
16950
  if (!validator) {
16816
16951
  return `schema ${schemaRef} not found`;
16817
16952
  }
@@ -16836,17 +16971,25 @@ function setValidationErrorOptions(options) {
16836
16971
  }
16837
16972
  var sockethubConfigValidator;
16838
16973
  function validateSockethubConfig(config) {
16974
+ const instance = getAjv();
16975
+ if (!instance) {
16976
+ return "";
16977
+ }
16839
16978
  if (!sockethubConfigValidator) {
16840
- sockethubConfigValidator = ajv2.compile(SockethubConfigSchema);
16979
+ sockethubConfigValidator = instance.compile(SockethubConfigSchema);
16841
16980
  }
16842
16981
  if (sockethubConfigValidator(config)) {
16843
16982
  return "";
16844
16983
  }
16845
- return ajv2.errorsText(sockethubConfigValidator.errors, {
16984
+ return instance.errorsText(sockethubConfigValidator.errors, {
16846
16985
  dataVar: "config"
16847
16986
  });
16848
16987
  }
16849
16988
  function validateActivityStream(msg) {
16989
+ if (!isCodegenAvailable()) {
16990
+ warnCodegenUnavailable();
16991
+ return "";
16992
+ }
16850
16993
  const streamValidationError = handleValidation(`${schemaURL}/activity-stream`, msg);
16851
16994
  if (streamValidationError) {
16852
16995
  return streamValidationError;
@@ -16862,6 +17005,10 @@ function validateActivityStream(msg) {
16862
17005
  return handleValidation(schemaId, msg);
16863
17006
  }
16864
17007
  function validateActivityStreamResponse(msg) {
17008
+ if (!isCodegenAvailable()) {
17009
+ warnCodegenUnavailable();
17010
+ return "";
17011
+ }
16865
17012
  const platformContextUrl = resolvePlatformContextUrl(msg);
16866
17013
  if (!platformContextUrl) {
16867
17014
  return "";
@@ -16871,12 +17018,17 @@ function validateActivityStreamResponse(msg) {
16871
17018
  return "";
16872
17019
  }
16873
17020
  const responsesSchemaId = `${schemaURL}/context/${platformId}/responses`;
16874
- if (!ajv2.getSchema(responsesSchemaId)) {
17021
+ const instance = getAjv();
17022
+ if (!instance || !instance.getSchema(responsesSchemaId)) {
16875
17023
  return "";
16876
17024
  }
16877
17025
  return handleValidation(responsesSchemaId, msg);
16878
17026
  }
16879
17027
  function validateCredentials(msg) {
17028
+ if (!isCodegenAvailable()) {
17029
+ warnCodegenUnavailable();
17030
+ return "";
17031
+ }
16880
17032
  if (!Array.isArray(msg["@context"])) {
16881
17033
  return "credential activity streams must have an @context set";
16882
17034
  }
@@ -16898,15 +17050,18 @@ function validateCredentials(msg) {
16898
17050
  return handleValidation(credentialsSchemaId, msg);
16899
17051
  }
16900
17052
  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}`;
17053
+ const instance = getAjv();
17054
+ if (instance) {
17055
+ const validate = instance.compile(PlatformSchema);
17056
+ const err = validate(schema);
17057
+ if (!err) {
17058
+ const validationError = validate.errors?.[0];
17059
+ let message = `${validationError?.instancePath ?? ""} ${validationError?.message ?? "is invalid"}`;
17060
+ if (validationError?.keyword === "additionalProperties") {
17061
+ message += `: ${validationError.params.additionalProperty}`;
17062
+ }
17063
+ return `platform schema failed to validate: ${message}`;
16908
17064
  }
16909
- return `platform schema failed to validate: ${message}`;
16910
17065
  }
16911
17066
  const platform = schema;
16912
17067
  const messages = platform.messages;
@@ -16948,13 +17103,16 @@ function validatePlatformSchema(schema) {
16948
17103
  return "";
16949
17104
  }
16950
17105
  function addPlatformSchema(schema, platform_type) {
16951
- const schemaRef = `${schemaURL}/context/${platform_type}`;
16952
- if (!ajv2.getSchema(schemaRef)) {
16953
- ajv2.addSchema(schema, schemaRef);
17106
+ const instance = getAjv();
17107
+ if (!instance) {
17108
+ return;
16954
17109
  }
17110
+ const schemaRef = `${schemaURL}/context/${platform_type}`;
17111
+ instance.removeSchema(schemaRef);
17112
+ instance.addSchema(schema, schemaRef);
16955
17113
  }
16956
17114
  function getPlatformSchema(platform_type) {
16957
- return ajv2.getSchema(`${schemaURL}/context/${platform_type}`);
17115
+ return getAjv()?.getSchema(`${schemaURL}/context/${platform_type}`);
16958
17116
  }
16959
17117
  function addPlatformContext(platformId, platformContextUrl) {
16960
17118
  registerPlatformContext(platformId, platformContextUrl, `${schemaURL}/context/${platformId}/messages`, `${schemaURL}/context/${platformId}/credentials`);
@@ -17018,6 +17176,7 @@ export {
17018
17176
  addPlatformSchema,
17019
17177
  buildCanonicalContext,
17020
17178
  getPlatformSchema,
17179
+ isCodegenAvailable,
17021
17180
  normalizeActivityStream,
17022
17181
  platformIdFromContext,
17023
17182
  registerSystemPlatformContexts,
@@ -17031,4 +17190,4 @@ export {
17031
17190
  validateSockethubConfig
17032
17191
  };
17033
17192
 
17034
- //# debugId=878BEB7D547F15C164756E2164756E21
17193
+ //# debugId=A3B598B447DA32C764756E2164756E21