@knpkv/herdr-hub 0.21.0 → 0.22.0
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/README.md +15 -1
- package/dist/activity-history.d.ts +3 -1
- package/dist/activity-history.d.ts.map +1 -1
- package/dist/activity-history.js +14 -23
- package/dist/activity-history.js.map +1 -1
- package/dist/approval-client.js +29 -4
- package/dist/approval-client.js.map +1 -1
- package/dist/approval.js +46 -46
- package/dist/approval.js.map +4 -4
- package/dist/http.d.ts +4 -1
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +130 -33
- package/dist/http.js.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.css.map +3 -3
- package/dist/module-contract.d.ts +13 -2
- package/dist/module-contract.d.ts.map +1 -1
- package/dist/module-contract.js +9 -1
- package/dist/module-contract.js.map +1 -1
- package/dist/module-needs-you-server.d.ts +59 -0
- package/dist/module-needs-you-server.d.ts.map +1 -0
- package/dist/module-needs-you-server.js +96 -0
- package/dist/module-needs-you-server.js.map +1 -0
- package/dist/module-needs-you.d.ts +146 -0
- package/dist/module-needs-you.d.ts.map +1 -0
- package/dist/module-needs-you.js +63 -0
- package/dist/module-needs-you.js.map +1 -0
- package/dist/module-server.d.ts +12 -9
- package/dist/module-server.d.ts.map +1 -1
- package/dist/module-server.js +29 -8
- package/dist/module-server.js.map +1 -1
- package/dist/modules.d.ts +1 -0
- package/dist/modules.d.ts.map +1 -1
- package/dist/modules.js +1 -0
- package/dist/modules.js.map +1 -1
- package/dist/superapp-view.d.ts.map +1 -1
- package/dist/superapp-view.js +1 -1
- package/dist/superapp-view.js.map +1 -1
- package/dist/today-fleet-activity.d.ts +11 -0
- package/dist/today-fleet-activity.d.ts.map +1 -0
- package/dist/today-fleet-activity.js +18 -0
- package/dist/today-fleet-activity.js.map +1 -0
- package/dist/today-module-view.d.ts +18 -0
- package/dist/today-module-view.d.ts.map +1 -0
- package/dist/today-module-view.js +45 -0
- package/dist/today-module-view.js.map +1 -0
- package/dist/today-view.d.ts +19 -0
- package/dist/today-view.d.ts.map +1 -0
- package/dist/today-view.js +80 -0
- package/dist/today-view.js.map +1 -0
- package/dist/views.d.ts +1 -0
- package/dist/views.d.ts.map +1 -1
- package/dist/views.js +1 -0
- package/dist/views.js.map +1 -1
- package/package.json +5 -5
package/dist/http.d.ts
CHANGED
|
@@ -4,12 +4,13 @@ import { FleetApprovalError, FleetJobNotFoundError, FleetOperationError, FleetVa
|
|
|
4
4
|
import { Tailscale } from "@knpkv/herdr-tailscale";
|
|
5
5
|
import type { WorkCheckpointConflictError, WorkProjectionError, WorkService, WorkStoreError } from "@knpkv/herdr-work";
|
|
6
6
|
import { WorkGoalCheckpoint } from "@knpkv/herdr-work/model";
|
|
7
|
-
import { Effect } from "effect";
|
|
7
|
+
import { Crypto, Effect } from "effect";
|
|
8
8
|
import type { Redacted } from "effect";
|
|
9
9
|
import * as HttpClient from "effect/http/HttpClient";
|
|
10
10
|
import { type DashboardSnapshot } from "./dashboard-model.js";
|
|
11
11
|
import { DashboardResponseBudgetError } from "./errors.js";
|
|
12
12
|
import { type LanWorkListenerOptions } from "./lan-work.js";
|
|
13
|
+
import type { ServerModule } from "./module-server.js";
|
|
13
14
|
import { makePushSender } from "./push-sender.js";
|
|
14
15
|
import { type RelayHubBackends } from "./relay/mount.js";
|
|
15
16
|
export type UiAssets = {
|
|
@@ -32,6 +33,8 @@ export type HubRelayOptions = {
|
|
|
32
33
|
readonly backends?: RelayHubBackends;
|
|
33
34
|
};
|
|
34
35
|
export type HttpServerOptions = {
|
|
36
|
+
/** Additional product layers join the shared registry at startup; handlers close their requirements. */
|
|
37
|
+
readonly modules?: ReadonlyArray<ServerModule<unknown, HttpClient.HttpClient | Tailscale | Crypto.Crypto>>;
|
|
35
38
|
readonly lanWork?: LanWorkListenerOptions;
|
|
36
39
|
/** Mounts Relay at `/v1/relay/*` on the canonical listener. */
|
|
37
40
|
readonly relay?: HubRelayOptions;
|
package/dist/http.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAIV,iBAAiB,EAGlB,MAAM,sBAAsB,CAAA;AAsB7B,OAAO,KAAK,EACV,qBAAqB,EACrB,8BAA8B,EAC9B,YAAY,EACZ,mBAAmB,EACnB,eAAe,EACf,4BAA4B,EAC5B,iBAAiB,EAEjB,oBAAoB,EACrB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAEL,kBAAkB,EAElB,qBAAqB,EACrB,mBAAmB,EAEnB,oBAAoB,EAWrB,MAAM,oBAAoB,CAAA;AAE3B,OAAO,EAA+D,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAC/G,OAAO,KAAK,EACV,2BAA2B,EAC3B,mBAAmB,EAInB,WAAW,EAEX,cAAc,EACf,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EAEL,kBAAkB,EAKnB,MAAM,yBAAyB,CAAA;AAChC,OAAO,
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uCAyClC,CAAA;AA0gBF,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oGAyCjC,CAAA;AA0OF,eAAO,MAAM,UAAU,mBACL,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,wCA4B1D,CAAA;AAEF,eAAO,MAAM,eAAe,WAClB,iBAAiB,WAChB,YAAY,YACX,QAAQ,YACT,iBAAiB,KACzB,OAAO,CAAC;IACT,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IACnC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,QAAQ,CAAC,kBAAkB,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,IAAI,CAAA;CAC9D,CAyxEA,CAAA"}
|
package/dist/http.js
CHANGED
|
@@ -4,7 +4,7 @@ import { decodeBoundedResponseJson, FleetApprovalError, FleetAuthorizationError,
|
|
|
4
4
|
import { authorizeWhois, discoverFleetPeers, layer as tailscaleLayer, Tailscale } from "@knpkv/herdr-tailscale";
|
|
5
5
|
import { approvalTargetMatchesOrigin, makeWorkService, WorkSnapshotWindow, WorkStore } from "@knpkv/herdr-work";
|
|
6
6
|
import { WorkAdmissionTarget, WorkGoalCheckpoint, WorkPullRequestAttach, WorkPullRequestLinkRequest, WorkRecoveryTarget } from "@knpkv/herdr-work/model";
|
|
7
|
-
import { Cause, Clock, Crypto, Duration, Effect, Equal, Exit, Fiber, FileSystem, Layer, ManagedRuntime, Queue, Result, Schema, Scope, Semaphore, Stream } from "effect";
|
|
7
|
+
import { Cause, Clock, Context, Crypto, Duration, Effect, Equal, Exit, Fiber, FileSystem, Layer, ManagedRuntime, Queue, Result, Schema, Scope, Semaphore, Stream } from "effect";
|
|
8
8
|
import * as HttpClient from "effect/http/HttpClient";
|
|
9
9
|
import { ChildProcessSpawner } from "effect/process";
|
|
10
10
|
import { createServer } from "node:http";
|
|
@@ -27,6 +27,8 @@ import { isRelayedScrollState, makeLatestSignalSender, rawText, relayTerminalClo
|
|
|
27
27
|
import { LanWorkPage, LanWorkPairPage } from "./lan-work-view.js";
|
|
28
28
|
import { decodeLanWorkPairRequest, LanWorkConfigurationError, LanWorkOriginRejectedError, LanWorkPairingMalformedError, LanWorkPairRequestInput, LanWorkSelectionMalformedError, lanWorkSessionCookie, makeLanWorkPairing, readLanWorkSessionCookie } from "./lan-work.js";
|
|
29
29
|
import { ApprovalNotificationCandidate, PushSubscriptionRecord, PushSubscriptionRemoval } from "./model.js";
|
|
30
|
+
import { fleetModule, todayModule } from "./module-contract.js";
|
|
31
|
+
import * as ModuleServer from "./module-server.js";
|
|
30
32
|
import { generateVapidKeys, makePushSender } from "./push-sender.js";
|
|
31
33
|
import { validatePushEndpoint } from "./push-subscription.js";
|
|
32
34
|
import { makePushWorker } from "./push-worker.js";
|
|
@@ -75,6 +77,8 @@ const json = (response, status, value, headers = {}) => {
|
|
|
75
77
|
};
|
|
76
78
|
const apiError = (error) => {
|
|
77
79
|
switch (error._tag) {
|
|
80
|
+
case "ModuleRouteFailure":
|
|
81
|
+
return { status: error.status, body: { error: error.code } };
|
|
78
82
|
case "FleetAuthorizationError":
|
|
79
83
|
return { status: 403, body: { error: error._tag, actor: error.actor } };
|
|
80
84
|
case "FleetJobNotFoundError":
|
|
@@ -599,6 +603,79 @@ const pendingFailureReason = (error) => {
|
|
|
599
603
|
return "request_failed";
|
|
600
604
|
}
|
|
601
605
|
};
|
|
606
|
+
/** Keep only the pending-job fields already exposed by the dashboard and Relay. */
|
|
607
|
+
const fleetPendingJob = (host, record) => ({
|
|
608
|
+
host,
|
|
609
|
+
jobId: record.id,
|
|
610
|
+
kind: record.payload.kind,
|
|
611
|
+
actor: record.actor,
|
|
612
|
+
createdAt: record.createdAt,
|
|
613
|
+
expiresAt: record.approvalExpiresAt ?? null
|
|
614
|
+
});
|
|
615
|
+
/**
|
|
616
|
+
* Relay and Today share one bounded read with per-source failure and pagination results.
|
|
617
|
+
* Peer discovery still runs after a failed local read so Today can retain healthy peer jobs.
|
|
618
|
+
*/
|
|
619
|
+
const readFleetPendingJobs = Effect.fn("HostHttp.readFleetPendingJobs")(function* (config, service, maxPages) {
|
|
620
|
+
const local = yield* Effect.result(readPages((cursor) => Effect.map(service.pendingApprovalPage(cursor), (page) => ({
|
|
621
|
+
items: page.records.map((record) => fleetPendingJob(config.host, sanitizeJobRecord(record))),
|
|
622
|
+
next: page.nextCursor
|
|
623
|
+
})), maxPages));
|
|
624
|
+
const peers = yield* Effect.result(fleetPeers(config));
|
|
625
|
+
const remote = Result.isSuccess(peers)
|
|
626
|
+
? yield* Effect.forEach(peers.success, (peer) => Effect.result(readPages((cursor) => Effect.map(fetchPeerPending(peer, cursor), (page) => ({
|
|
627
|
+
items: page.approvals.map((approval) => fleetPendingJob(peer.host, sanitizePendingApproval(approval))),
|
|
628
|
+
next: page.nextCursor
|
|
629
|
+
})), maxPages)).pipe(Effect.map((result) => ({ peer, result }))), { concurrency: 4 })
|
|
630
|
+
: [];
|
|
631
|
+
return { local, peers, remote };
|
|
632
|
+
});
|
|
633
|
+
/** Read current peer availability on every poll; this path issues no approval proofs. */
|
|
634
|
+
const readFleetNeedsYou = Effect.fn("HostHttp.readFleetNeedsYou")(function* (config, service) {
|
|
635
|
+
const pending = yield* readFleetPendingJobs(config, service, relayPendingPagesPerHost);
|
|
636
|
+
const jobs = [];
|
|
637
|
+
const issues = [];
|
|
638
|
+
const hosts = [];
|
|
639
|
+
if (Result.isSuccess(pending.local)) {
|
|
640
|
+
for (const job of pending.local.success.items)
|
|
641
|
+
jobs.push(job);
|
|
642
|
+
if (pending.local.success.more)
|
|
643
|
+
issues.push({ state: "truncated" });
|
|
644
|
+
}
|
|
645
|
+
else {
|
|
646
|
+
yield* Effect.logWarning("Today local approvals failed", pending.local.failure);
|
|
647
|
+
hosts.push({ host: config.host, reason: "request_failed" });
|
|
648
|
+
}
|
|
649
|
+
if (Result.isFailure(pending.peers)) {
|
|
650
|
+
yield* Effect.logWarning("Today peer discovery failed", pending.peers.failure);
|
|
651
|
+
issues.push({ state: "failed", reason: "request_failed" });
|
|
652
|
+
}
|
|
653
|
+
for (const remote of pending.remote) {
|
|
654
|
+
if (Result.isSuccess(remote.result)) {
|
|
655
|
+
for (const job of remote.result.success.items)
|
|
656
|
+
jobs.push(job);
|
|
657
|
+
if (remote.result.success.more && !issues.some((issue) => issue.state === "truncated")) {
|
|
658
|
+
issues.push({ state: "truncated" });
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
else {
|
|
662
|
+
hosts.push({ host: remote.peer.host, reason: pendingFailureReason(remote.result.failure) });
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
if (hosts.length > 0)
|
|
666
|
+
issues.push({ state: "hosts", hosts });
|
|
667
|
+
return {
|
|
668
|
+
items: jobs.map((job) => ({
|
|
669
|
+
sourceKey: `${job.host.toLowerCase()}:${job.jobId}`,
|
|
670
|
+
destination: { _tag: "FleetApproval", module: "fleet", host: job.host, jobId: job.jobId },
|
|
671
|
+
kind: job.kind,
|
|
672
|
+
actor: job.actor,
|
|
673
|
+
createdAt: job.createdAt,
|
|
674
|
+
expiresAt: job.expiresAt
|
|
675
|
+
})),
|
|
676
|
+
issues
|
|
677
|
+
};
|
|
678
|
+
});
|
|
602
679
|
const aggregatePeerPending = Effect.fn("HostHttp.aggregatePeerPending")(function* (peers, pagination = "first") {
|
|
603
680
|
const results = yield* Effect.all(peers.map((peer) => Effect.result(pagination === "all"
|
|
604
681
|
? fetchAllPeerPending(peer)
|
|
@@ -1006,6 +1083,21 @@ export const startHttpServer = async (config, service, uiAssets, options = {}) =
|
|
|
1006
1083
|
}
|
|
1007
1084
|
};
|
|
1008
1085
|
try {
|
|
1086
|
+
const moduleScope = await httpRuntime.runPromise(Scope.make());
|
|
1087
|
+
finalizers.unshift(() => httpRuntime.runPromise(Scope.close(moduleScope, Exit.void)));
|
|
1088
|
+
const modules = [
|
|
1089
|
+
{ descriptor: todayModule, handlers: Layer.succeed(ModuleServer.ModuleHandlers, { routes: [] }) },
|
|
1090
|
+
{
|
|
1091
|
+
descriptor: fleetModule,
|
|
1092
|
+
handlers: Layer.effect(ModuleServer.ModuleHandlers, Effect.gen(function* () {
|
|
1093
|
+
const context = yield* Effect.context();
|
|
1094
|
+
return { routes: [], needsYou: readFleetNeedsYou(config, service).pipe(Effect.provideContext(context)) };
|
|
1095
|
+
}))
|
|
1096
|
+
},
|
|
1097
|
+
...(options.modules ?? [])
|
|
1098
|
+
];
|
|
1099
|
+
const moduleContext = await httpRuntime.runPromise(Layer.build(ModuleServer.makeModuleLayer(modules.map((module) => module.descriptor), modules)).pipe(Effect.provideService(Scope.Scope, moduleScope)));
|
|
1100
|
+
const registry = Context.get(moduleContext, ModuleServer.ModuleRegistry);
|
|
1009
1101
|
const tlsCredentials = isHub && approvalTls !== null
|
|
1010
1102
|
? await httpRuntime.runPromise(Effect.gen(function* () {
|
|
1011
1103
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
@@ -1069,39 +1161,19 @@ export const startHttpServer = async (config, service, uiAssets, options = {}) =
|
|
|
1069
1161
|
})), { store: archiveStore, observedAt });
|
|
1070
1162
|
})),
|
|
1071
1163
|
pendingJobs: asRead("the pending approvals")(Effect.gen(function* () {
|
|
1072
|
-
const
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
const remote = yield* Effect.forEach(peers, (peer) => Effect.result(readPages((cursor) => Effect.map(fetchPeerPending(peer, cursor), (page) => ({
|
|
1078
|
-
items: page.approvals.map(sanitizePendingApproval),
|
|
1079
|
-
next: page.nextCursor
|
|
1080
|
-
})), relayPendingPagesPerHost)).pipe(Effect.map((result) => ({ peer, result }))), { concurrency: 4 });
|
|
1081
|
-
const jobs = [
|
|
1082
|
-
...local.items.map((record) => ({
|
|
1083
|
-
host: config.host,
|
|
1084
|
-
jobId: record.id,
|
|
1085
|
-
kind: record.payload.kind,
|
|
1086
|
-
actor: record.actor,
|
|
1087
|
-
createdAt: record.createdAt,
|
|
1088
|
-
expiresAt: record.approvalExpiresAt ?? null
|
|
1089
|
-
})),
|
|
1090
|
-
...remote.flatMap(({ peer, result }) => Result.isSuccess(result)
|
|
1091
|
-
? result.success.items.map((approval) => ({
|
|
1092
|
-
host: peer.host,
|
|
1093
|
-
jobId: approval.id,
|
|
1094
|
-
kind: approval.payload.kind,
|
|
1095
|
-
actor: approval.actor,
|
|
1096
|
-
createdAt: approval.createdAt,
|
|
1097
|
-
expiresAt: approval.approvalExpiresAt
|
|
1098
|
-
}))
|
|
1099
|
-
: [])
|
|
1100
|
-
];
|
|
1164
|
+
const pending = yield* readFleetPendingJobs(config, service, relayPendingPagesPerHost);
|
|
1165
|
+
if (Result.isFailure(pending.local))
|
|
1166
|
+
return yield* pending.local.failure;
|
|
1167
|
+
if (Result.isFailure(pending.peers))
|
|
1168
|
+
return yield* pending.peers.failure;
|
|
1101
1169
|
return {
|
|
1102
|
-
jobs
|
|
1103
|
-
|
|
1104
|
-
|
|
1170
|
+
jobs: [
|
|
1171
|
+
...pending.local.success.items,
|
|
1172
|
+
...pending.remote.flatMap(({ result }) => Result.isSuccess(result) ? result.success.items : [])
|
|
1173
|
+
],
|
|
1174
|
+
more: pending.local.success.more ||
|
|
1175
|
+
pending.remote.some(({ result }) => Result.isSuccess(result) && result.success.more),
|
|
1176
|
+
unreachable: pending.remote.flatMap(({ peer, result }) => Result.isFailure(result) ? [peer.host] : [])
|
|
1105
1177
|
};
|
|
1106
1178
|
})),
|
|
1107
1179
|
localJob: (jobId) => asRead(`job ${jobId}`)(service.get(jobId).pipe(Effect.map(sanitizeJobRecord), Effect.catchTag("FleetJobNotFoundError", () => Effect.succeed(null)))),
|
|
@@ -1946,6 +2018,31 @@ export const startHttpServer = async (config, service, uiAssets, options = {}) =
|
|
|
1946
2018
|
login: header(request, "tailscale-user-login"),
|
|
1947
2019
|
remoteAddress: request.socket.remoteAddress
|
|
1948
2020
|
});
|
|
2021
|
+
if (url.pathname === "/v1/modules" || url.pathname.startsWith("/v1/modules/")) {
|
|
2022
|
+
if (mode === "local") {
|
|
2023
|
+
json(response, 404, { error: "not_found" });
|
|
2024
|
+
return;
|
|
2025
|
+
}
|
|
2026
|
+
const result = await runRequest(ModuleServer.dispatchModuleRoute({
|
|
2027
|
+
method: request.method ?? "GET",
|
|
2028
|
+
url,
|
|
2029
|
+
listener: mode,
|
|
2030
|
+
authorize: authorized,
|
|
2031
|
+
sameOrigin: sameOrigin(request, expectedOrigin()),
|
|
2032
|
+
readJson: () => readJson(request, Schema.Json)
|
|
2033
|
+
}).pipe(Effect.provideService(ModuleServer.ModuleRegistry, registry), Effect.result));
|
|
2034
|
+
if (Result.isFailure(result)) {
|
|
2035
|
+
const mapped = apiError(result.failure);
|
|
2036
|
+
json(response, mapped.status, mapped.body);
|
|
2037
|
+
}
|
|
2038
|
+
else if (result.success === null) {
|
|
2039
|
+
json(response, 404, { error: "not_found" });
|
|
2040
|
+
}
|
|
2041
|
+
else {
|
|
2042
|
+
json(response, result.success.status, result.success.body);
|
|
2043
|
+
}
|
|
2044
|
+
return;
|
|
2045
|
+
}
|
|
1949
2046
|
if (mode === "serve" &&
|
|
1950
2047
|
relayMount !== null &&
|
|
1951
2048
|
await handleRelayRoute(request, response, url, {
|