@sockethub/server 5.0.0-beta.0 → 5.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.
@@ -30,7 +30,5 @@ export interface MessageHandlersOptions {
30
30
  * Normalize middleware errors into payload-safe error responses.
31
31
  * Removes internal-only properties that must never be sent to clients.
32
32
  */
33
- export declare function attachError<T extends ActivityStream>(err: unknown, msg?: T): Error | (T & {
34
- sessionSecret?: string;
35
- });
33
+ export declare function attachError<T extends ActivityStream>(err: unknown, msg?: T): T | Error;
36
34
  export declare function createMessageHandlers(options: MessageHandlersOptions): MessageHandlers;
@@ -1,3 +1,16 @@
1
1
  import type { ActivityStream } from "@sockethub/schemas";
2
2
  import type { MiddlewareChainInterface } from "../middleware.js";
3
+ /**
4
+ * Maximum nesting depth accepted for client-supplied messages. Validation
5
+ * error formatting and the socket.io encoder both recurse over the message, so
6
+ * an unbounded depth lets a single payload overflow the stack and crash the
7
+ * server.
8
+ */
9
+ export declare const MAX_MESSAGE_DEPTH = 64;
10
+ /**
11
+ * Iteratively check whether a value nests deeper than `max` levels. Must not
12
+ * recurse itself, since it guards the recursive code paths.
13
+ */
14
+ export declare function exceedsDepth(root: unknown, max?: number): boolean;
15
+ /** Reject malformed or over-deep input before normalizing an activity. */
3
16
  export default function normalizeActivityStreamMiddleware<T extends ActivityStream>(msg: T, done: MiddlewareChainInterface<T>): void;
@@ -0,0 +1,2 @@
1
+ /** Disable namespaces that log raw payloads or session IDs, or recurse over client input. */
2
+ export default function disablePayloadDebug(): void;
@@ -55,6 +55,7 @@ export default class PlatformInstance {
55
55
  readonly parentId: string;
56
56
  private readonly parentSecret1?;
57
57
  readonly sessions: Set<string>;
58
+ readonly ownerIps: Set<string>;
58
59
  readonly sessionIps: Map<string, string>;
59
60
  private readonly sessionSecrets;
60
61
  private processMessageListener?;
@@ -63,12 +64,14 @@ export default class PlatformInstance {
63
64
  private heartbeatFailureHandled;
64
65
  private replaced;
65
66
  private shutdownResult?;
67
+ private retirementError?;
66
68
  /**
67
69
  * Actor this instance was opened for. Updated when the platform re-keys
68
70
  * (IRC nick change) so a later rename moves the credential scope off the
69
71
  * actor the client is using now, not the one from process start.
70
72
  */
71
73
  private actor?;
74
+ get actorId(): string | undefined;
72
75
  constructor(params: PlatformInstanceParams);
73
76
  createQueue(): void;
74
77
  resolveSentryEnv(): string | undefined;
@@ -97,7 +100,7 @@ export default class PlatformInstance {
97
100
  * independent run would resolve while the first is still obliterating
98
101
  * the queue name the replacement is about to reuse.
99
102
  */
100
- shutdown(): Promise<void>;
103
+ shutdown(pendingJobError?: string): Promise<void>;
101
104
  private teardown;
102
105
  /**
103
106
  * When jobs are completed or failed, we prepare the results and send them to the client socket
@@ -110,6 +113,7 @@ export default class PlatformInstance {
110
113
  * mid-job) don't leak handlers for the lifetime of the instance.
111
114
  */
112
115
  registerCompletedJobHandler(title: string, handler: CompletedJobHandler): void;
116
+ private failRetiredJob;
113
117
  private takeCompletedJobHandler;
114
118
  private pruneExpiredJobHandlers;
115
119
  /**
package/dist/platform.js CHANGED
@@ -20497,7 +20497,7 @@ var init_package = __esm(() => {
20497
20497
  package_default = {
20498
20498
  name: "@sockethub/schemas",
20499
20499
  description: "JSON schema files for validating Sockethub Activity Streams",
20500
- version: "3.0.0-beta.0",
20500
+ version: "3.0.0-beta.2",
20501
20501
  type: "module",
20502
20502
  private: false,
20503
20503
  author: "Nick Jennings <nick@silverbucket.net>",
@@ -20567,7 +20567,7 @@ var init_package = __esm(() => {
20567
20567
  "ajv-formats": "^2.1.1",
20568
20568
  "ajv-formats-draft2019": "^1.6.1"
20569
20569
  },
20570
- gitHead: "75002ae8f15d7679bd58a9327f5a1d7eeaffa237",
20570
+ gitHead: "1f74d4e07311496f0acc021855137bc197d79eab",
20571
20571
  types: "./dist/index.d.ts"
20572
20572
  };
20573
20573
  });
@@ -20676,8 +20676,11 @@ var init_sockethub_config = __esm(() => {
20676
20676
  "@sockethub/platform-caldav",
20677
20677
  "@sockethub/platform-dummy",
20678
20678
  "@sockethub/platform-feeds",
20679
+ "@sockethub/platform-email",
20679
20680
  "@sockethub/platform-irc",
20680
20681
  "@sockethub/platform-metadata",
20682
+ "@sockethub/platform-messenger",
20683
+ "@sockethub/platform-instagram",
20681
20684
  "@sockethub/platform-xmpp"
20682
20685
  ]
20683
20686
  },
@@ -20693,7 +20696,8 @@ var init_sockethub_config = __esm(() => {
20693
20696
  connectTimeoutMs: { type: "integer", minimum: 1 },
20694
20697
  allowPrivateAddresses: { type: "boolean" },
20695
20698
  allowInsecureHttp: { type: "boolean" },
20696
- concurrency: { type: "integer", minimum: 1 }
20699
+ concurrency: { type: "integer", minimum: 1 },
20700
+ discoveryCacheTtlMs: { type: "integer", minimum: 0 }
20697
20701
  }
20698
20702
  },
20699
20703
  "@sockethub/platform-caldav": {
@@ -20703,7 +20707,20 @@ var init_sockethub_config = __esm(() => {
20703
20707
  connectTimeoutMs: { type: "integer", minimum: 1 },
20704
20708
  allowPrivateAddresses: { type: "boolean" },
20705
20709
  allowInsecureHttp: { type: "boolean" },
20706
- concurrency: { type: "integer", minimum: 1 }
20710
+ concurrency: { type: "integer", minimum: 1 },
20711
+ discoveryCacheTtlMs: { type: "integer", minimum: 0 }
20712
+ }
20713
+ },
20714
+ "@sockethub/platform-email": {
20715
+ type: "object",
20716
+ additionalProperties: false,
20717
+ properties: {
20718
+ connectTimeoutMs: {
20719
+ type: "integer",
20720
+ minimum: 5000,
20721
+ maximum: 120000
20722
+ },
20723
+ allowPrivateAddresses: { type: "boolean" }
20707
20724
  }
20708
20725
  },
20709
20726
  "@sockethub/platform-dummy": {
@@ -20726,14 +20743,16 @@ var init_sockethub_config = __esm(() => {
20726
20743
  type: "object",
20727
20744
  additionalProperties: false,
20728
20745
  properties: {
20729
- connectTimeoutMs: { type: "number" }
20746
+ connectTimeoutMs: { type: "number" },
20747
+ allowPrivateAddresses: { type: "boolean" }
20730
20748
  }
20731
20749
  },
20732
20750
  "@sockethub/platform-xmpp": {
20733
20751
  type: "object",
20734
20752
  additionalProperties: false,
20735
20753
  properties: {
20736
- connectTimeoutMs: { type: "number" }
20754
+ connectTimeoutMs: { type: "number" },
20755
+ allowPrivateAddresses: { type: "boolean" }
20737
20756
  }
20738
20757
  },
20739
20758
  "@sockethub/platform-metadata": {
@@ -20823,11 +20842,29 @@ var init_sockethub_config = __esm(() => {
20823
20842
  type: "object",
20824
20843
  additionalProperties: false,
20825
20844
  properties: {
20845
+ maxInstancesPerSession: {
20846
+ type: "integer",
20847
+ minimum: 0,
20848
+ default: 10,
20849
+ description: "Maximum persistent instances per socket session. 0 disables the cap."
20850
+ },
20851
+ maxInstancesPerIp: {
20852
+ type: "integer",
20853
+ minimum: 0,
20854
+ default: 20,
20855
+ description: "Maximum persistent instances per client IP, including HTTP actions. 0 disables the cap."
20856
+ },
20857
+ maxStartsPerIpPerMinute: {
20858
+ type: "integer",
20859
+ minimum: 0,
20860
+ default: 60,
20861
+ 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."
20862
+ },
20826
20863
  maxPlatformInstances: {
20827
20864
  type: "number",
20828
20865
  minimum: 0,
20829
20866
  default: 100,
20830
- 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."
20867
+ 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."
20831
20868
  }
20832
20869
  }
20833
20870
  },
@@ -27196,15 +27233,33 @@ var require_ajv = __commonJS(function(exports, module) {
27196
27233
  } });
27197
27234
  });
27198
27235
 
27236
+ // ../schemas/src/helpers/codegen.ts
27237
+ function isCodegenAvailable() {
27238
+ if (available === undefined) {
27239
+ try {
27240
+ new Function("return true");
27241
+ available = true;
27242
+ } catch {
27243
+ available = false;
27244
+ }
27245
+ }
27246
+ return available;
27247
+ }
27248
+ function warnCodegenUnavailable() {
27249
+ if (warned) {
27250
+ return;
27251
+ }
27252
+ warned = true;
27253
+ 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.");
27254
+ }
27255
+ var available, warned = false;
27256
+
27199
27257
  // ../schemas/src/schemas/service-descriptor.ts
27200
27258
  var init_service_descriptor = () => {};
27201
27259
 
27202
27260
  // ../schemas/src/service-descriptor.ts
27203
- var import_ajv, ajv;
27204
27261
  var init_service_descriptor2 = __esm(() => {
27205
27262
  init_service_descriptor();
27206
- import_ajv = __toESM(require_ajv(), 1);
27207
- ajv = new import_ajv.default({ strictTypes: false, allErrors: true });
27208
27263
  });
27209
27264
 
27210
27265
  // ../../node_modules/ajv-formats/dist/formats.js
@@ -36752,15 +36807,35 @@ var init_error_parser = __esm(() => {
36752
36807
  });
36753
36808
 
36754
36809
  // ../schemas/src/validator.ts
36810
+ function getAjv() {
36811
+ if (!isCodegenAvailable()) {
36812
+ warnCodegenUnavailable();
36813
+ return;
36814
+ }
36815
+ if (!ajv) {
36816
+ const instance = new import_ajv.default({ strictTypes: false, allErrors: true });
36817
+ import_ajv_formats.default(instance);
36818
+ import_ajv_formats_draft2019.default(instance);
36819
+ for (const uri in schemas) {
36820
+ instance.addSchema(schemas[uri], uri);
36821
+ }
36822
+ ajv = instance;
36823
+ }
36824
+ return ajv;
36825
+ }
36755
36826
  function registerSystemContext(platformId, contextUrl) {
36756
36827
  registerPlatformContext(platformId, contextUrl, `${schemaURL}/context/${platformId}/messages`, `${schemaURL}/context/${platformId}/credentials`);
36828
+ const instance = getAjv();
36829
+ if (!instance) {
36830
+ return;
36831
+ }
36757
36832
  const messageSchemaRef = `${schemaURL}/context/${platformId}/messages`;
36758
- if (!ajv2.getSchema(messageSchemaRef)) {
36759
- ajv2.addSchema({}, messageSchemaRef);
36833
+ if (!instance.getSchema(messageSchemaRef)) {
36834
+ instance.addSchema({}, messageSchemaRef);
36760
36835
  }
36761
36836
  const credentialsSchemaRef = `${schemaURL}/context/${platformId}/credentials`;
36762
- if (!ajv2.getSchema(credentialsSchemaRef)) {
36763
- ajv2.addSchema({}, credentialsSchemaRef);
36837
+ if (!instance.getSchema(credentialsSchemaRef)) {
36838
+ instance.addSchema({}, credentialsSchemaRef);
36764
36839
  }
36765
36840
  }
36766
36841
  function registerSystemPlatformContexts() {
@@ -36772,17 +36847,21 @@ function registerSystemPlatformContexts() {
36772
36847
  systemContextsRegistered = true;
36773
36848
  }
36774
36849
  function validateSockethubConfig(config) {
36850
+ const instance = getAjv();
36851
+ if (!instance) {
36852
+ return "";
36853
+ }
36775
36854
  if (!sockethubConfigValidator) {
36776
- sockethubConfigValidator = ajv2.compile(SockethubConfigSchema);
36855
+ sockethubConfigValidator = instance.compile(SockethubConfigSchema);
36777
36856
  }
36778
36857
  if (sockethubConfigValidator(config)) {
36779
36858
  return "";
36780
36859
  }
36781
- return ajv2.errorsText(sockethubConfigValidator.errors, {
36860
+ return instance.errorsText(sockethubConfigValidator.errors, {
36782
36861
  dataVar: "config"
36783
36862
  });
36784
36863
  }
36785
- var import_ajv2, import_ajv_formats, import_ajv_formats_draft2019, ajv2, schemaURL = "https://sockethub.org/schemas/v0", schemas, systemContextsRegistered = false, sockethubConfigValidator;
36864
+ var import_ajv, import_ajv_formats, import_ajv_formats_draft2019, schemaURL = "https://sockethub.org/schemas/v0", schemas, systemContextsRegistered = false, ajv, sockethubConfigValidator;
36786
36865
  var init_validator = __esm(() => {
36787
36866
  init_context();
36788
36867
  init_error_parser();
@@ -36790,17 +36869,11 @@ var init_validator = __esm(() => {
36790
36869
  init_activity_stream();
36791
36870
  init_platform();
36792
36871
  init_sockethub_config();
36793
- import_ajv2 = __toESM(require_ajv(), 1);
36872
+ import_ajv = __toESM(require_ajv(), 1);
36794
36873
  import_ajv_formats = __toESM(require_dist(), 1);
36795
36874
  import_ajv_formats_draft2019 = __toESM(require_ajv_formats_draft2019(), 1);
36796
- ajv2 = new import_ajv2.default({ strictTypes: false, allErrors: true });
36797
- import_ajv_formats.default(ajv2);
36798
- import_ajv_formats_draft2019.default(ajv2);
36799
36875
  schemas = {};
36800
36876
  schemas[`${schemaURL}/activity-stream`] = ActivityStreamSchema;
36801
- for (const uri in schemas) {
36802
- ajv2.addSchema(schemas[uri], uri);
36803
- }
36804
36877
  registerSystemPlatformContexts();
36805
36878
  });
36806
36879
 
@@ -73881,6 +73954,9 @@ var init_config_schema = __esm(() => {
73881
73954
  "rateLimiter.maxRequests": { format: "nat" },
73882
73955
  "rateLimiter.blockDurationMs": { format: "nat" },
73883
73956
  "rateLimiter.maxConnectionsPerIp": { format: "nat" },
73957
+ "limits.maxInstancesPerSession": { format: "nat" },
73958
+ "limits.maxInstancesPerIp": { format: "nat" },
73959
+ "limits.maxStartsPerIpPerMinute": { format: "nat" },
73884
73960
  "limits.maxPlatformInstances": { format: "nat" },
73885
73961
  "credentials.ttlMs": {
73886
73962
  format: "nat",
@@ -95701,6 +95777,7 @@ class JobWorker extends JobBase {
95701
95777
  redisConfig;
95702
95778
  queueId;
95703
95779
  concurrency;
95780
+ maxStalledCount;
95704
95781
  initialized = false;
95705
95782
  constructor(parentId, instanceId, secret, redisConfig, options = {}) {
95706
95783
  super(secret);
@@ -95709,6 +95786,7 @@ class JobWorker extends JobBase {
95709
95786
  throw new Error(`JobWorker concurrency must be a positive integer, got ${options.concurrency}`);
95710
95787
  }
95711
95788
  this.concurrency = concurrency;
95789
+ this.maxStalledCount = options.maxStalledCount ?? 3;
95712
95790
  this.log = createLogger(`data-layer:worker:${parentId}:${instanceId}`);
95713
95791
  this.connectionName = getLoggerNamespace(this.log);
95714
95792
  redisConfig.connectionName = this.connectionName;
@@ -95724,7 +95802,7 @@ class JobWorker extends JobBase {
95724
95802
  this.worker = new import_bullmq2.Worker(queueName, this.jobHandler.bind(this), {
95725
95803
  connection: this.redisConfig,
95726
95804
  concurrency: this.concurrency,
95727
- maxStalledCount: 3
95805
+ maxStalledCount: this.maxStalledCount
95728
95806
  });
95729
95807
  this.worker.on("error", (err) => {
95730
95808
  this.log.warn(`worker error: ${err.message}`);
@@ -96165,7 +96243,10 @@ async function startPlatformProcess() {
96165
96243
  }
96166
96244
  }
96167
96245
  const concurrency = getWorkerConcurrency();
96168
- jobWorker = new JobWorker(parentId, queueInstanceId, parentSecret1 + parentSecret2, { url: redisUrl }, { concurrency });
96246
+ jobWorker = new JobWorker(parentId, queueInstanceId, parentSecret1 + parentSecret2, { url: redisUrl }, {
96247
+ concurrency,
96248
+ maxStalledCount: platform.config.persist && platform.config.retryStalledJobs === false ? 0 : 3
96249
+ });
96169
96250
  logger.info(`listening on the queue for incoming jobs (concurrency: ${concurrency})`);
96170
96251
  jobWorker.onJob(getJobHandler());
96171
96252
  jobWorkerStarted = true;
@@ -6,6 +6,8 @@ declare class ProcessManager {
6
6
  private readonly parentSecret2;
7
7
  private init;
8
8
  private readonly ensureChains;
9
+ private readonly startsPerIp;
10
+ private startsWindowBegan;
9
11
  constructor(parentId: string, parentSecret1: string, parentSecret2: string, init: IInitObject);
10
12
  /**
11
13
  * @param sessionId socket id to register with the instance; absent for HTTP
@@ -24,18 +26,19 @@ declare class ProcessManager {
24
26
  */
25
27
  private ensureProcess;
26
28
  private ensureProcessNow;
27
- /**
28
- * Each platform instance forks a full child process; without an upper
29
- * bound, a public instance can be driven into resource exhaustion.
30
- * Throws when the configured cap (`limits.maxPlatformInstances`, 0 =
31
- * disabled) has been reached and a new instance would be created.
32
- *
33
- * `identifier`'s existing (dead) slot, if any, is excluded from the
34
- * count: replacing a crashed instance for the same actor doesn't
35
- * increase the total instance count, so it shouldn't be blocked by
36
- * the cap.
29
+ /** Stateless workers are bounded by the enabled platform count, independently
30
+ * of client occupancy. Check owners even when attaching to a shared worker.
37
31
  */
38
32
  private assertInstanceCapacity;
33
+ /**
34
+ * Instance caps bound how many workers run at once, not how fast a client
35
+ * can churn them (e.g. replacing credentials forks a fresh worker each
36
+ * time). Budget new persistent starts per IP, the one key a client cannot
37
+ * rotate.
38
+ * shortcut: fixed one-minute window allows a 2x burst at the boundary;
39
+ * switch to a sliding window if that burst matters.
40
+ */
41
+ private assertStartRate;
39
42
  private isProcessAlive;
40
43
  }
41
44
  export default ProcessManager;
@@ -1,3 +1,22 @@
1
+ import type { IncomingMessage } from "node:http";
2
+ import type { Express } from "express";
3
+ /** Resolve socket admission using the same compiled proxy policy as Express req.ip. */
4
+ export declare function getRequestClientIp(request: IncomingMessage, app: Express): string;
5
+ /**
6
+ * Client address for socket admission, per-IP quotas, and anonymous reconnect.
7
+ *
8
+ * `x-forwarded-for` is a chain. The nearest proxy appends the address it
9
+ * actually accepted, and anything to the left of that may have been set by
10
+ * the client. Reading the first entry treats that prefix as the client, so
11
+ * an attacker can present a victim's address and, during janitor grace,
12
+ * take over that victim's anonymous connection (the reconnect key is the
13
+ * actor plus this address). Hop count is already what HTTP uses: one trusted
14
+ * hop yields the address the proxy appended, not the spoofed prefix.
15
+ *
16
+ * A custom `proxyHeader` is not a chain Express understands. The operator
17
+ * vouched for that header, and its first address is the value.
18
+ */
19
+ export declare function resolveSocketClientIp(request: IncomingMessage, app: Express | undefined, reconnectIpSource: unknown, proxyHeader: unknown, fallbackAddress: string | undefined): string;
1
20
  /**
2
21
  * Resolution of Express's `trust proxy` setting.
3
22
  *
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sockethub/server",
3
3
  "description": "A polyglot messaging service, server libraries",
4
- "version": "5.0.0-beta.0",
4
+ "version": "5.0.0-beta.2",
5
5
  "type": "module",
6
6
  "private": false,
7
7
  "author": "Nick Jennings <nick@silverbucket.net>",
@@ -26,7 +26,7 @@
26
26
  "bin": "bin/sockethub",
27
27
  "preferGlobal": true,
28
28
  "engines": {
29
- "node": ">=20"
29
+ "node": ">=20.19"
30
30
  },
31
31
  "keywords": [
32
32
  "sockethub",
@@ -53,17 +53,19 @@
53
53
  "dependencies": {
54
54
  "@sentry/node": "^10.36.0",
55
55
  "@sentry/profiling-node": "10.36.0",
56
- "@sockethub/client": "^5.0.0-beta.0",
57
- "@sockethub/data-layer": "^1.0.0-beta.0",
58
- "@sockethub/logger": "^1.0.0-beta.0",
59
- "@sockethub/schemas": "^3.0.0-beta.0",
60
- "@sockethub/util": "^1.0.0-beta.0",
56
+ "@sockethub/client": "^5.0.0-beta.2",
57
+ "@sockethub/data-layer": "^1.0.0-beta.2",
58
+ "@sockethub/logger": "^1.0.0-beta.2",
59
+ "@sockethub/schemas": "^3.0.0-beta.2",
60
+ "@sockethub/util": "^1.0.0-beta.2",
61
61
  "chalk": "^5.6.2",
62
62
  "convict": "^6.2.5",
63
+ "debug": "^4.4.3",
63
64
  "ejs": "^3.1.10",
64
65
  "express": "^5.1.0",
65
66
  "express-rate-limit": "^8.2.1",
66
67
  "jquery": "^3.7.1",
68
+ "proxy-addr": "^2.0.7",
67
69
  "rate-limit-redis": "^4.2.0",
68
70
  "socket.io": "^4.8.3"
69
71
  },
@@ -82,21 +84,25 @@
82
84
  "@types/debug": "^4.1.12",
83
85
  "@types/express": "^5.0.0",
84
86
  "@types/jquery": "^3.5.33",
87
+ "@types/proxy-addr": "^2.0.3",
85
88
  "@types/sinon": "^17.0.4",
86
89
  "jaribu": "^2.2.3",
87
90
  "sinon": "^17.0.2",
88
91
  "web-streams-polyfill": "^3.3.3"
89
92
  },
90
93
  "optionalDependencies": {
91
- "@sockethub/examples": "^1.0.0-beta.0",
92
- "@sockethub/platform-caldav": "^1.0.0-beta.0",
93
- "@sockethub/platform-carddav": "^1.0.0-beta.0",
94
- "@sockethub/platform-dummy": "^3.0.0-beta.0",
95
- "@sockethub/platform-feeds": "^4.0.0-beta.0",
96
- "@sockethub/platform-irc": "^4.0.0-beta.0",
97
- "@sockethub/platform-metadata": "^1.0.1-beta.0",
98
- "@sockethub/platform-xmpp": "^5.0.0-beta.0"
94
+ "@sockethub/examples": "^1.0.0-beta.2",
95
+ "@sockethub/platform-caldav": "^1.0.0-beta.2",
96
+ "@sockethub/platform-carddav": "^1.0.0-beta.2",
97
+ "@sockethub/platform-dummy": "^3.0.0-beta.2",
98
+ "@sockethub/platform-email": "^1.0.0-beta.2",
99
+ "@sockethub/platform-feeds": "^4.0.0-beta.2",
100
+ "@sockethub/platform-instagram": "^1.0.0-beta.2",
101
+ "@sockethub/platform-irc": "^4.0.0-beta.2",
102
+ "@sockethub/platform-messenger": "^1.0.0-beta.2",
103
+ "@sockethub/platform-metadata": "^1.0.1-beta.2",
104
+ "@sockethub/platform-xmpp": "^5.0.0-beta.2"
99
105
  },
100
- "gitHead": "a17e337ee7d2dd496d225c0d6e8ae48f4f4ce73c",
106
+ "gitHead": "d241420f9743f66a15ed083a1390595b331a96ac",
101
107
  "types": "./dist/index.d.ts"
102
108
  }