@aeolus-fleet/core 0.0.0 → 0.19.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/LICENSE +201 -0
- package/README.md +98 -1
- package/dist/adapters/cli/fleet-init.d.ts +14 -0
- package/dist/adapters/cli/fleet-init.js +68 -0
- package/dist/adapters/cli/fleet-init.js.map +1 -0
- package/dist/adapters/cli/io.d.ts +35 -0
- package/dist/adapters/cli/io.js +21 -0
- package/dist/adapters/cli/io.js.map +1 -0
- package/dist/adapters/cli/migrate.d.ts +11 -0
- package/dist/adapters/cli/migrate.js +12 -0
- package/dist/adapters/cli/migrate.js.map +1 -0
- package/dist/adapters/cli/operator-reset-password.d.ts +12 -0
- package/dist/adapters/cli/operator-reset-password.js +49 -0
- package/dist/adapters/cli/operator-reset-password.js.map +1 -0
- package/dist/adapters/cli/run.d.ts +14 -0
- package/dist/adapters/cli/run.js +40 -0
- package/dist/adapters/cli/run.js.map +1 -0
- package/dist/adapters/cli/terminal.d.ts +20 -0
- package/dist/adapters/cli/terminal.js +68 -0
- package/dist/adapters/cli/terminal.js.map +1 -0
- package/dist/adapters/crypto/passwords.d.ts +2 -0
- package/dist/adapters/crypto/passwords.js +59 -0
- package/dist/adapters/crypto/passwords.js.map +1 -0
- package/dist/adapters/crypto/secrets.d.ts +5 -0
- package/dist/adapters/crypto/secrets.js +10 -0
- package/dist/adapters/crypto/secrets.js.map +1 -0
- package/dist/adapters/http/device-label.d.ts +9 -0
- package/dist/adapters/http/device-label.js +39 -0
- package/dist/adapters/http/device-label.js.map +1 -0
- package/dist/adapters/http/rate-limiter.d.ts +21 -0
- package/dist/adapters/http/rate-limiter.js +44 -0
- package/dist/adapters/http/rate-limiter.js.map +1 -0
- package/dist/adapters/http/request-credentials.d.ts +23 -0
- package/dist/adapters/http/request-credentials.js +45 -0
- package/dist/adapters/http/request-credentials.js.map +1 -0
- package/dist/adapters/http/server.d.ts +47 -0
- package/dist/adapters/http/server.js +216 -0
- package/dist/adapters/http/server.js.map +1 -0
- package/dist/adapters/http/version.d.ts +9 -0
- package/dist/adapters/http/version.js +23 -0
- package/dist/adapters/http/version.js.map +1 -0
- package/dist/adapters/mcp/mcp-endpoint.d.ts +8 -0
- package/dist/adapters/mcp/mcp-endpoint.js +127 -0
- package/dist/adapters/mcp/mcp-endpoint.js.map +1 -0
- package/dist/adapters/prisma/client.d.ts +10 -0
- package/dist/adapters/prisma/client.js +20 -0
- package/dist/adapters/prisma/client.js.map +1 -0
- package/dist/adapters/prisma/delivery-notices.d.ts +34 -0
- package/dist/adapters/prisma/delivery-notices.js +113 -0
- package/dist/adapters/prisma/delivery-notices.js.map +1 -0
- package/dist/adapters/prisma/event-log.d.ts +11 -0
- package/dist/adapters/prisma/event-log.js +61 -0
- package/dist/adapters/prisma/event-log.js.map +1 -0
- package/dist/adapters/prisma/failure-log.d.ts +22 -0
- package/dist/adapters/prisma/failure-log.js +70 -0
- package/dist/adapters/prisma/failure-log.js.map +1 -0
- package/dist/adapters/prisma/fleet-counter.d.ts +3 -0
- package/dist/adapters/prisma/fleet-counter.js +6 -0
- package/dist/adapters/prisma/fleet-counter.js.map +1 -0
- package/dist/adapters/prisma/fleet-event-wakeups.d.ts +33 -0
- package/dist/adapters/prisma/fleet-event-wakeups.js +86 -0
- package/dist/adapters/prisma/fleet-event-wakeups.js.map +1 -0
- package/dist/adapters/prisma/generated/browser.d.ts +127 -0
- package/dist/adapters/prisma/generated/browser.js +18 -0
- package/dist/adapters/prisma/generated/browser.js.map +1 -0
- package/dist/adapters/prisma/generated/client.d.ts +146 -0
- package/dist/adapters/prisma/generated/client.js +38 -0
- package/dist/adapters/prisma/generated/client.js.map +1 -0
- package/dist/adapters/prisma/generated/commonInputTypes.d.ts +879 -0
- package/dist/adapters/prisma/generated/commonInputTypes.js +11 -0
- package/dist/adapters/prisma/generated/commonInputTypes.js.map +1 -0
- package/dist/adapters/prisma/generated/enums.d.ts +75 -0
- package/dist/adapters/prisma/generated/enums.js +73 -0
- package/dist/adapters/prisma/generated/enums.js.map +1 -0
- package/dist/adapters/prisma/generated/internal/class.d.ts +308 -0
- package/dist/adapters/prisma/generated/internal/class.js +52 -0
- package/dist/adapters/prisma/generated/internal/class.js.map +1 -0
- package/dist/adapters/prisma/generated/internal/prismaNamespace.d.ts +2131 -0
- package/dist/adapters/prisma/generated/internal/prismaNamespace.js +295 -0
- package/dist/adapters/prisma/generated/internal/prismaNamespace.js.map +1 -0
- package/dist/adapters/prisma/generated/internal/prismaNamespaceBrowser.d.ts +273 -0
- package/dist/adapters/prisma/generated/internal/prismaNamespaceBrowser.js +265 -0
- package/dist/adapters/prisma/generated/internal/prismaNamespaceBrowser.js.map +1 -0
- package/dist/adapters/prisma/generated/models/ConsoleSession.d.ts +2137 -0
- package/dist/adapters/prisma/generated/models/ConsoleSession.js +2 -0
- package/dist/adapters/prisma/generated/models/ConsoleSession.js.map +1 -0
- package/dist/adapters/prisma/generated/models/Credential.d.ts +1360 -0
- package/dist/adapters/prisma/generated/models/Credential.js +2 -0
- package/dist/adapters/prisma/generated/models/Credential.js.map +1 -0
- package/dist/adapters/prisma/generated/models/CrewRequest.d.ts +1558 -0
- package/dist/adapters/prisma/generated/models/CrewRequest.js +2 -0
- package/dist/adapters/prisma/generated/models/CrewRequest.js.map +1 -0
- package/dist/adapters/prisma/generated/models/Delivery.d.ts +2211 -0
- package/dist/adapters/prisma/generated/models/Delivery.js +2 -0
- package/dist/adapters/prisma/generated/models/Delivery.js.map +1 -0
- package/dist/adapters/prisma/generated/models/Event.d.ts +1991 -0
- package/dist/adapters/prisma/generated/models/Event.js +2 -0
- package/dist/adapters/prisma/generated/models/Event.js.map +1 -0
- package/dist/adapters/prisma/generated/models/Fleet.d.ts +3032 -0
- package/dist/adapters/prisma/generated/models/Fleet.js +2 -0
- package/dist/adapters/prisma/generated/models/Fleet.js.map +1 -0
- package/dist/adapters/prisma/generated/models/Guide.d.ts +943 -0
- package/dist/adapters/prisma/generated/models/Guide.js +2 -0
- package/dist/adapters/prisma/generated/models/Guide.js.map +1 -0
- package/dist/adapters/prisma/generated/models/GuideProgress.d.ts +1323 -0
- package/dist/adapters/prisma/generated/models/GuideProgress.js +2 -0
- package/dist/adapters/prisma/generated/models/GuideProgress.js.map +1 -0
- package/dist/adapters/prisma/generated/models/InstallationRequest.d.ts +1036 -0
- package/dist/adapters/prisma/generated/models/InstallationRequest.js +2 -0
- package/dist/adapters/prisma/generated/models/InstallationRequest.js.map +1 -0
- package/dist/adapters/prisma/generated/models/InstallationSettings.d.ts +1027 -0
- package/dist/adapters/prisma/generated/models/InstallationSettings.js +2 -0
- package/dist/adapters/prisma/generated/models/InstallationSettings.js.map +1 -0
- package/dist/adapters/prisma/generated/models/Lease.d.ts +2076 -0
- package/dist/adapters/prisma/generated/models/Lease.js +2 -0
- package/dist/adapters/prisma/generated/models/Lease.js.map +1 -0
- package/dist/adapters/prisma/generated/models/Message.d.ts +2869 -0
- package/dist/adapters/prisma/generated/models/Message.js +2 -0
- package/dist/adapters/prisma/generated/models/Message.js.map +1 -0
- package/dist/adapters/prisma/generated/models/Notice.d.ts +1068 -0
- package/dist/adapters/prisma/generated/models/Notice.js +2 -0
- package/dist/adapters/prisma/generated/models/Notice.js.map +1 -0
- package/dist/adapters/prisma/generated/models/NoticeDismissal.d.ts +1245 -0
- package/dist/adapters/prisma/generated/models/NoticeDismissal.js +2 -0
- package/dist/adapters/prisma/generated/models/NoticeDismissal.js.map +1 -0
- package/dist/adapters/prisma/generated/models/Operator.d.ts +1173 -0
- package/dist/adapters/prisma/generated/models/Operator.js +2 -0
- package/dist/adapters/prisma/generated/models/Operator.js.map +1 -0
- package/dist/adapters/prisma/generated/models/Ship.d.ts +3320 -0
- package/dist/adapters/prisma/generated/models/Ship.js +2 -0
- package/dist/adapters/prisma/generated/models/Ship.js.map +1 -0
- package/dist/adapters/prisma/generated/models/SignInTicket.d.ts +1222 -0
- package/dist/adapters/prisma/generated/models/SignInTicket.js +2 -0
- package/dist/adapters/prisma/generated/models/SignInTicket.js.map +1 -0
- package/dist/adapters/prisma/generated/models.d.ts +18 -0
- package/dist/adapters/prisma/generated/models.js +2 -0
- package/dist/adapters/prisma/generated/models.js.map +1 -0
- package/dist/adapters/prisma/history.d.ts +3 -0
- package/dist/adapters/prisma/history.js +289 -0
- package/dist/adapters/prisma/history.js.map +1 -0
- package/dist/adapters/prisma/identity.d.ts +10 -0
- package/dist/adapters/prisma/identity.js +213 -0
- package/dist/adapters/prisma/identity.js.map +1 -0
- package/dist/adapters/prisma/installation.d.ts +13 -0
- package/dist/adapters/prisma/installation.js +155 -0
- package/dist/adapters/prisma/installation.js.map +1 -0
- package/dist/adapters/prisma/messaging.d.ts +4 -0
- package/dist/adapters/prisma/messaging.js +156 -0
- package/dist/adapters/prisma/messaging.js.map +1 -0
- package/dist/adapters/prisma/migrate.d.ts +5 -0
- package/dist/adapters/prisma/migrate.js +40 -0
- package/dist/adapters/prisma/migrate.js.map +1 -0
- package/dist/adapters/prisma/receiver-wakeups.d.ts +26 -0
- package/dist/adapters/prisma/receiver-wakeups.js +79 -0
- package/dist/adapters/prisma/receiver-wakeups.js.map +1 -0
- package/dist/adapters/prisma/registry.d.ts +8 -0
- package/dist/adapters/prisma/registry.js +427 -0
- package/dist/adapters/prisma/registry.js.map +1 -0
- package/dist/adapters/prisma/rows.d.ts +58 -0
- package/dist/adapters/prisma/rows.js +408 -0
- package/dist/adapters/prisma/rows.js.map +1 -0
- package/dist/adapters/prisma/unit-of-work.d.ts +36 -0
- package/dist/adapters/prisma/unit-of-work.js +66 -0
- package/dist/adapters/prisma/unit-of-work.js.map +1 -0
- package/dist/adapters/rest/openapi.d.ts +12 -0
- package/dist/adapters/rest/openapi.js +62 -0
- package/dist/adapters/rest/openapi.js.map +1 -0
- package/dist/adapters/rest/rest-api.d.ts +8 -0
- package/dist/adapters/rest/rest-api.js +61 -0
- package/dist/adapters/rest/rest-api.js.map +1 -0
- package/dist/adapters/trpc/console.d.ts +150 -0
- package/dist/adapters/trpc/console.js +102 -0
- package/dist/adapters/trpc/console.js.map +1 -0
- package/dist/adapters/trpc/context.d.ts +201 -0
- package/dist/adapters/trpc/context.js +2 -0
- package/dist/adapters/trpc/context.js.map +1 -0
- package/dist/adapters/trpc/fleet.d.ts +637 -0
- package/dist/adapters/trpc/fleet.js +437 -0
- package/dist/adapters/trpc/fleet.js.map +1 -0
- package/dist/adapters/trpc/installation.d.ts +414 -0
- package/dist/adapters/trpc/installation.js +138 -0
- package/dist/adapters/trpc/installation.js.map +1 -0
- package/dist/adapters/trpc/router.d.ts +1263 -0
- package/dist/adapters/trpc/router.js +15 -0
- package/dist/adapters/trpc/router.js.map +1 -0
- package/dist/adapters/trpc/ship-contract.d.ts +107 -0
- package/dist/adapters/trpc/ship-contract.js +165 -0
- package/dist/adapters/trpc/ship-contract.js.map +1 -0
- package/dist/adapters/trpc/ship-protocol.d.ts +9 -0
- package/dist/adapters/trpc/ship-protocol.js +25 -0
- package/dist/adapters/trpc/ship-protocol.js.map +1 -0
- package/dist/adapters/trpc/ship.d.ts +209 -0
- package/dist/adapters/trpc/ship.js +214 -0
- package/dist/adapters/trpc/ship.js.map +1 -0
- package/dist/adapters/trpc/starting-prompt-text.d.ts +7 -0
- package/dist/adapters/trpc/starting-prompt-text.js +60 -0
- package/dist/adapters/trpc/starting-prompt-text.js.map +1 -0
- package/dist/adapters/trpc/system.d.ts +29 -0
- package/dist/adapters/trpc/system.js +15 -0
- package/dist/adapters/trpc/system.js.map +1 -0
- package/dist/adapters/trpc/trpc.d.ts +131 -0
- package/dist/adapters/trpc/trpc.js +350 -0
- package/dist/adapters/trpc/trpc.js.map +1 -0
- package/dist/app.d.ts +31 -0
- package/dist/app.js +80 -0
- package/dist/app.js.map +1 -0
- package/dist/bin/aeolus-core.d.ts +2 -0
- package/dist/bin/aeolus-core.js +45 -0
- package/dist/bin/aeolus-core.js.map +1 -0
- package/dist/config.d.ts +35 -0
- package/dist/config.js +74 -0
- package/dist/config.js.map +1 -0
- package/dist/domain/identity/authenticate.d.ts +46 -0
- package/dist/domain/identity/authenticate.js +18 -0
- package/dist/domain/identity/authenticate.js.map +1 -0
- package/dist/domain/identity/console-session.d.ts +54 -0
- package/dist/domain/identity/console-session.js +29 -0
- package/dist/domain/identity/console-session.js.map +1 -0
- package/dist/domain/identity/credential.d.ts +76 -0
- package/dist/domain/identity/credential.js +63 -0
- package/dist/domain/identity/credential.js.map +1 -0
- package/dist/domain/identity/dismiss-notice.d.ts +19 -0
- package/dist/domain/identity/dismiss-notice.js +23 -0
- package/dist/domain/identity/dismiss-notice.js.map +1 -0
- package/dist/domain/identity/get-guide.d.ts +7 -0
- package/dist/domain/identity/get-guide.js +5 -0
- package/dist/domain/identity/get-guide.js.map +1 -0
- package/dist/domain/identity/get-notices.d.ts +7 -0
- package/dist/domain/identity/get-notices.js +5 -0
- package/dist/domain/identity/get-notices.js.map +1 -0
- package/dist/domain/identity/guide.d.ts +24 -0
- package/dist/domain/identity/guide.js +3 -0
- package/dist/domain/identity/guide.js.map +1 -0
- package/dist/domain/identity/issue-sign-in-ticket.d.ts +38 -0
- package/dist/domain/identity/issue-sign-in-ticket.js +39 -0
- package/dist/domain/identity/issue-sign-in-ticket.js.map +1 -0
- package/dist/domain/identity/notice.d.ts +16 -0
- package/dist/domain/identity/notice.js +12 -0
- package/dist/domain/identity/notice.js.map +1 -0
- package/dist/domain/identity/operator-account.d.ts +28 -0
- package/dist/domain/identity/operator-account.js +21 -0
- package/dist/domain/identity/operator-account.js.map +1 -0
- package/dist/domain/identity/ports.d.ts +193 -0
- package/dist/domain/identity/ports.js +2 -0
- package/dist/domain/identity/ports.js.map +1 -0
- package/dist/domain/identity/public.d.ts +3 -0
- package/dist/domain/identity/public.js +5 -0
- package/dist/domain/identity/public.js.map +1 -0
- package/dist/domain/identity/read-account.d.ts +35 -0
- package/dist/domain/identity/read-account.js +27 -0
- package/dist/domain/identity/read-account.js.map +1 -0
- package/dist/domain/identity/read-guide.d.ts +18 -0
- package/dist/domain/identity/read-guide.js +21 -0
- package/dist/domain/identity/read-guide.js.map +1 -0
- package/dist/domain/identity/read-notices.d.ts +13 -0
- package/dist/domain/identity/read-notices.js +17 -0
- package/dist/domain/identity/read-notices.js.map +1 -0
- package/dist/domain/identity/record-guide-progress.d.ts +19 -0
- package/dist/domain/identity/record-guide-progress.js +24 -0
- package/dist/domain/identity/record-guide-progress.js.map +1 -0
- package/dist/domain/identity/redeem-sign-in-ticket.d.ts +34 -0
- package/dist/domain/identity/redeem-sign-in-ticket.js +25 -0
- package/dist/domain/identity/redeem-sign-in-ticket.js.map +1 -0
- package/dist/domain/identity/reset-operator-password.d.ts +34 -0
- package/dist/domain/identity/reset-operator-password.js +55 -0
- package/dist/domain/identity/reset-operator-password.js.map +1 -0
- package/dist/domain/identity/set-guide.d.ts +13 -0
- package/dist/domain/identity/set-guide.js +12 -0
- package/dist/domain/identity/set-guide.js.map +1 -0
- package/dist/domain/identity/set-notices.d.ts +13 -0
- package/dist/domain/identity/set-notices.js +12 -0
- package/dist/domain/identity/set-notices.js.map +1 -0
- package/dist/domain/identity/set-theme.d.ts +21 -0
- package/dist/domain/identity/set-theme.js +19 -0
- package/dist/domain/identity/set-theme.js.map +1 -0
- package/dist/domain/identity/sign-in-ticket.d.ts +21 -0
- package/dist/domain/identity/sign-in-ticket.js +5 -0
- package/dist/domain/identity/sign-in-ticket.js.map +1 -0
- package/dist/domain/identity/sign-in.d.ts +51 -0
- package/dist/domain/identity/sign-in.js +43 -0
- package/dist/domain/identity/sign-in.js.map +1 -0
- package/dist/domain/identity/sign-out.d.ts +20 -0
- package/dist/domain/identity/sign-out.js +32 -0
- package/dist/domain/identity/sign-out.js.map +1 -0
- package/dist/domain/identity/start-console-session.d.ts +27 -0
- package/dist/domain/identity/start-console-session.js +54 -0
- package/dist/domain/identity/start-console-session.js.map +1 -0
- package/dist/domain/identity/start-viewer-session.d.ts +29 -0
- package/dist/domain/identity/start-viewer-session.js +42 -0
- package/dist/domain/identity/start-viewer-session.js.map +1 -0
- package/dist/domain/messaging/acknowledge-delivery.d.ts +30 -0
- package/dist/domain/messaging/acknowledge-delivery.js +31 -0
- package/dist/domain/messaging/acknowledge-delivery.js.map +1 -0
- package/dist/domain/messaging/answer-ping.d.ts +33 -0
- package/dist/domain/messaging/answer-ping.js +37 -0
- package/dist/domain/messaging/answer-ping.js.map +1 -0
- package/dist/domain/messaging/check-inbox.d.ts +33 -0
- package/dist/domain/messaging/check-inbox.js +61 -0
- package/dist/domain/messaging/check-inbox.js.map +1 -0
- package/dist/domain/messaging/content-type.d.ts +9 -0
- package/dist/domain/messaging/content-type.js +18 -0
- package/dist/domain/messaging/content-type.js.map +1 -0
- package/dist/domain/messaging/daily-message-limit.d.ts +19 -0
- package/dist/domain/messaging/daily-message-limit.js +24 -0
- package/dist/domain/messaging/daily-message-limit.js.map +1 -0
- package/dist/domain/messaging/delivery.d.ts +116 -0
- package/dist/domain/messaging/delivery.js +201 -0
- package/dist/domain/messaging/delivery.js.map +1 -0
- package/dist/domain/messaging/dismiss-delivery.d.ts +28 -0
- package/dist/domain/messaging/dismiss-delivery.js +29 -0
- package/dist/domain/messaging/dismiss-delivery.js.map +1 -0
- package/dist/domain/messaging/inbox-wait.d.ts +8 -0
- package/dist/domain/messaging/inbox-wait.js +19 -0
- package/dist/domain/messaging/inbox-wait.js.map +1 -0
- package/dist/domain/messaging/mark-done.d.ts +45 -0
- package/dist/domain/messaging/mark-done.js +49 -0
- package/dist/domain/messaging/mark-done.js.map +1 -0
- package/dist/domain/messaging/mark-read.d.ts +27 -0
- package/dist/domain/messaging/mark-read.js +34 -0
- package/dist/domain/messaging/mark-read.js.map +1 -0
- package/dist/domain/messaging/message.d.ts +104 -0
- package/dist/domain/messaging/message.js +84 -0
- package/dist/domain/messaging/message.js.map +1 -0
- package/dist/domain/messaging/payload.d.ts +9 -0
- package/dist/domain/messaging/payload.js +16 -0
- package/dist/domain/messaging/payload.js.map +1 -0
- package/dist/domain/messaging/ping-ship.d.ts +38 -0
- package/dist/domain/messaging/ping-ship.js +42 -0
- package/dist/domain/messaging/ping-ship.js.map +1 -0
- package/dist/domain/messaging/ports.d.ts +116 -0
- package/dist/domain/messaging/ports.js +2 -0
- package/dist/domain/messaging/ports.js.map +1 -0
- package/dist/domain/messaging/receive-deliveries.d.ts +68 -0
- package/dist/domain/messaging/receive-deliveries.js +119 -0
- package/dist/domain/messaging/receive-deliveries.js.map +1 -0
- package/dist/domain/messaging/receive-max.d.ts +8 -0
- package/dist/domain/messaging/receive-max.js +17 -0
- package/dist/domain/messaging/receive-max.js.map +1 -0
- package/dist/domain/messaging/reply-to-message.d.ts +35 -0
- package/dist/domain/messaging/reply-to-message.js +49 -0
- package/dist/domain/messaging/reply-to-message.js.map +1 -0
- package/dist/domain/messaging/resend-delivery.d.ts +48 -0
- package/dist/domain/messaging/resend-delivery.js +97 -0
- package/dist/domain/messaging/resend-delivery.js.map +1 -0
- package/dist/domain/messaging/send-message.d.ts +88 -0
- package/dist/domain/messaging/send-message.js +115 -0
- package/dist/domain/messaging/send-message.js.map +1 -0
- package/dist/domain/messaging/send-request.d.ts +16 -0
- package/dist/domain/messaging/send-request.js +18 -0
- package/dist/domain/messaging/send-request.js.map +1 -0
- package/dist/domain/registry/applied-limits.d.ts +15 -0
- package/dist/domain/registry/applied-limits.js +15 -0
- package/dist/domain/registry/applied-limits.js.map +1 -0
- package/dist/domain/registry/assign-crew.d.ts +31 -0
- package/dist/domain/registry/assign-crew.js +35 -0
- package/dist/domain/registry/assign-crew.js.map +1 -0
- package/dist/domain/registry/claim-ship.d.ts +49 -0
- package/dist/domain/registry/claim-ship.js +59 -0
- package/dist/domain/registry/claim-ship.js.map +1 -0
- package/dist/domain/registry/commission-ship.d.ts +54 -0
- package/dist/domain/registry/commission-ship.js +70 -0
- package/dist/domain/registry/commission-ship.js.map +1 -0
- package/dist/domain/registry/confirm-crew-release.d.ts +28 -0
- package/dist/domain/registry/confirm-crew-release.js +28 -0
- package/dist/domain/registry/confirm-crew-release.js.map +1 -0
- package/dist/domain/registry/create-fleet.d.ts +39 -0
- package/dist/domain/registry/create-fleet.js +56 -0
- package/dist/domain/registry/create-fleet.js.map +1 -0
- package/dist/domain/registry/crew-request.d.ts +148 -0
- package/dist/domain/registry/crew-request.js +175 -0
- package/dist/domain/registry/crew-request.js.map +1 -0
- package/dist/domain/registry/delete-fleet.d.ts +46 -0
- package/dist/domain/registry/delete-fleet.js +34 -0
- package/dist/domain/registry/delete-fleet.js.map +1 -0
- package/dist/domain/registry/deregister.d.ts +32 -0
- package/dist/domain/registry/deregister.js +38 -0
- package/dist/domain/registry/deregister.js.map +1 -0
- package/dist/domain/registry/explain-crew-request.d.ts +30 -0
- package/dist/domain/registry/explain-crew-request.js +31 -0
- package/dist/domain/registry/explain-crew-request.js.map +1 -0
- package/dist/domain/registry/fleet.d.ts +12 -0
- package/dist/domain/registry/fleet.js +12 -0
- package/dist/domain/registry/fleet.js.map +1 -0
- package/dist/domain/registry/found-fleet.d.ts +32 -0
- package/dist/domain/registry/found-fleet.js +43 -0
- package/dist/domain/registry/found-fleet.js.map +1 -0
- package/dist/domain/registry/get-fleet-limits.d.ts +17 -0
- package/dist/domain/registry/get-fleet-limits.js +14 -0
- package/dist/domain/registry/get-fleet-limits.js.map +1 -0
- package/dist/domain/registry/get-installation-fleet.d.ts +15 -0
- package/dist/domain/registry/get-installation-fleet.js +12 -0
- package/dist/domain/registry/get-installation-fleet.js.map +1 -0
- package/dist/domain/registry/get-installation-settings.d.ts +7 -0
- package/dist/domain/registry/get-installation-settings.js +5 -0
- package/dist/domain/registry/get-installation-settings.js.map +1 -0
- package/dist/domain/registry/get-ship.d.ts +34 -0
- package/dist/domain/registry/get-ship.js +36 -0
- package/dist/domain/registry/get-ship.js.map +1 -0
- package/dist/domain/registry/get-starting-prompt.d.ts +24 -0
- package/dist/domain/registry/get-starting-prompt.js +46 -0
- package/dist/domain/registry/get-starting-prompt.js.map +1 -0
- package/dist/domain/registry/initialise-fleet.d.ts +28 -0
- package/dist/domain/registry/initialise-fleet.js +39 -0
- package/dist/domain/registry/initialise-fleet.js.map +1 -0
- package/dist/domain/registry/installation-fleet.d.ts +36 -0
- package/dist/domain/registry/installation-fleet.js +22 -0
- package/dist/domain/registry/installation-fleet.js.map +1 -0
- package/dist/domain/registry/installation-request.d.ts +23 -0
- package/dist/domain/registry/installation-request.js +5 -0
- package/dist/domain/registry/installation-request.js.map +1 -0
- package/dist/domain/registry/lease.d.ts +51 -0
- package/dist/domain/registry/lease.js +39 -0
- package/dist/domain/registry/lease.js.map +1 -0
- package/dist/domain/registry/leases.d.ts +66 -0
- package/dist/domain/registry/leases.js +80 -0
- package/dist/domain/registry/leases.js.map +1 -0
- package/dist/domain/registry/limits.d.ts +50 -0
- package/dist/domain/registry/limits.js +24 -0
- package/dist/domain/registry/limits.js.map +1 -0
- package/dist/domain/registry/list-fleet.d.ts +70 -0
- package/dist/domain/registry/list-fleet.js +47 -0
- package/dist/domain/registry/list-fleet.js.map +1 -0
- package/dist/domain/registry/list-fleets.d.ts +11 -0
- package/dist/domain/registry/list-fleets.js +9 -0
- package/dist/domain/registry/list-fleets.js.map +1 -0
- package/dist/domain/registry/list-installation-fleets.d.ts +15 -0
- package/dist/domain/registry/list-installation-fleets.js +15 -0
- package/dist/domain/registry/list-installation-fleets.js.map +1 -0
- package/dist/domain/registry/ping-status.d.ts +17 -0
- package/dist/domain/registry/ping-status.js +28 -0
- package/dist/domain/registry/ping-status.js.map +1 -0
- package/dist/domain/registry/pingable-ship.d.ts +22 -0
- package/dist/domain/registry/pingable-ship.js +21 -0
- package/dist/domain/registry/pingable-ship.js.map +1 -0
- package/dist/domain/registry/ports.d.ts +318 -0
- package/dist/domain/registry/ports.js +2 -0
- package/dist/domain/registry/ports.js.map +1 -0
- package/dist/domain/registry/public.d.ts +8 -0
- package/dist/domain/registry/public.js +10 -0
- package/dist/domain/registry/public.js.map +1 -0
- package/dist/domain/registry/read-assigned-crew-requests.d.ts +14 -0
- package/dist/domain/registry/read-assigned-crew-requests.js +15 -0
- package/dist/domain/registry/read-assigned-crew-requests.js.map +1 -0
- package/dist/domain/registry/recrew-ship.d.ts +33 -0
- package/dist/domain/registry/recrew-ship.js +34 -0
- package/dist/domain/registry/recrew-ship.js.map +1 -0
- package/dist/domain/registry/release-ship.d.ts +38 -0
- package/dist/domain/registry/release-ship.js +47 -0
- package/dist/domain/registry/release-ship.js.map +1 -0
- package/dist/domain/registry/remove-crew-request.d.ts +28 -0
- package/dist/domain/registry/remove-crew-request.js +36 -0
- package/dist/domain/registry/remove-crew-request.js.map +1 -0
- package/dist/domain/registry/rename-ship.d.ts +30 -0
- package/dist/domain/registry/rename-ship.js +39 -0
- package/dist/domain/registry/rename-ship.js.map +1 -0
- package/dist/domain/registry/report-crew-status.d.ts +29 -0
- package/dist/domain/registry/report-crew-status.js +30 -0
- package/dist/domain/registry/report-crew-status.js.map +1 -0
- package/dist/domain/registry/report-details.d.ts +18 -0
- package/dist/domain/registry/report-details.js +41 -0
- package/dist/domain/registry/report-details.js.map +1 -0
- package/dist/domain/registry/report-log.d.ts +21 -0
- package/dist/domain/registry/report-log.js +16 -0
- package/dist/domain/registry/report-log.js.map +1 -0
- package/dist/domain/registry/report.d.ts +30 -0
- package/dist/domain/registry/report.js +30 -0
- package/dist/domain/registry/report.js.map +1 -0
- package/dist/domain/registry/request-crew.d.ts +32 -0
- package/dist/domain/registry/request-crew.js +29 -0
- package/dist/domain/registry/request-crew.js.map +1 -0
- package/dist/domain/registry/resolve-selector.d.ts +25 -0
- package/dist/domain/registry/resolve-selector.js +32 -0
- package/dist/domain/registry/resolve-selector.js.map +1 -0
- package/dist/domain/registry/retire-ship.d.ts +42 -0
- package/dist/domain/registry/retire-ship.js +68 -0
- package/dist/domain/registry/retire-ship.js.map +1 -0
- package/dist/domain/registry/set-fleet-limits.d.ts +30 -0
- package/dist/domain/registry/set-fleet-limits.js +54 -0
- package/dist/domain/registry/set-fleet-limits.js.map +1 -0
- package/dist/domain/registry/set-installation-settings.d.ts +18 -0
- package/dist/domain/registry/set-installation-settings.js +31 -0
- package/dist/domain/registry/set-installation-settings.js.map +1 -0
- package/dist/domain/registry/ship-handle.d.ts +5 -0
- package/dist/domain/registry/ship-handle.js +20 -0
- package/dist/domain/registry/ship-handle.js.map +1 -0
- package/dist/domain/registry/ship-note.d.ts +7 -0
- package/dist/domain/registry/ship-note.js +15 -0
- package/dist/domain/registry/ship-note.js.map +1 -0
- package/dist/domain/registry/ship-report.d.ts +42 -0
- package/dist/domain/registry/ship-report.js +93 -0
- package/dist/domain/registry/ship-report.js.map +1 -0
- package/dist/domain/registry/ship.d.ts +190 -0
- package/dist/domain/registry/ship.js +334 -0
- package/dist/domain/registry/ship.js.map +1 -0
- package/dist/domain/registry/ships.d.ts +25 -0
- package/dist/domain/registry/ships.js +22 -0
- package/dist/domain/registry/ships.js.map +1 -0
- package/dist/domain/registry/starting-prompt.d.ts +32 -0
- package/dist/domain/registry/starting-prompt.js +22 -0
- package/dist/domain/registry/starting-prompt.js.map +1 -0
- package/dist/domain/registry/whoami.d.ts +20 -0
- package/dist/domain/registry/whoami.js +15 -0
- package/dist/domain/registry/whoami.js.map +1 -0
- package/dist/domain/shared/caller.d.ts +25 -0
- package/dist/domain/shared/caller.js +8 -0
- package/dist/domain/shared/caller.js.map +1 -0
- package/dist/domain/shared/clock.d.ts +4 -0
- package/dist/domain/shared/clock.js +2 -0
- package/dist/domain/shared/clock.js.map +1 -0
- package/dist/domain/shared/errors.d.ts +13 -0
- package/dist/domain/shared/errors.js +6 -0
- package/dist/domain/shared/errors.js.map +1 -0
- package/dist/domain/shared/events.d.ts +75 -0
- package/dist/domain/shared/events.js +9 -0
- package/dist/domain/shared/events.js.map +1 -0
- package/dist/domain/shared/follow-fleet.d.ts +32 -0
- package/dist/domain/shared/follow-fleet.js +65 -0
- package/dist/domain/shared/follow-fleet.js.map +1 -0
- package/dist/domain/shared/history.d.ts +124 -0
- package/dist/domain/shared/history.js +16 -0
- package/dist/domain/shared/history.js.map +1 -0
- package/dist/domain/shared/idempotency-key.d.ts +8 -0
- package/dist/domain/shared/idempotency-key.js +14 -0
- package/dist/domain/shared/idempotency-key.js.map +1 -0
- package/dist/domain/shared/notifier.d.ts +17 -0
- package/dist/domain/shared/notifier.js +2 -0
- package/dist/domain/shared/notifier.js.map +1 -0
- package/dist/domain/shared/ping.d.ts +18 -0
- package/dist/domain/shared/ping.js +8 -0
- package/dist/domain/shared/ping.js.map +1 -0
- package/dist/domain/shared/read-fleet-events.d.ts +29 -0
- package/dist/domain/shared/read-fleet-events.js +25 -0
- package/dist/domain/shared/read-fleet-events.js.map +1 -0
- package/dist/domain/shared/read-fleet-limits.d.ts +39 -0
- package/dist/domain/shared/read-fleet-limits.js +24 -0
- package/dist/domain/shared/read-fleet-limits.js.map +1 -0
- package/dist/domain/shared/read-inbox.d.ts +20 -0
- package/dist/domain/shared/read-inbox.js +16 -0
- package/dist/domain/shared/read-inbox.js.map +1 -0
- package/dist/domain/shared/read-message.d.ts +21 -0
- package/dist/domain/shared/read-message.js +18 -0
- package/dist/domain/shared/read-message.js.map +1 -0
- package/dist/domain/shared/read-needs-attention.d.ts +12 -0
- package/dist/domain/shared/read-needs-attention.js +10 -0
- package/dist/domain/shared/read-needs-attention.js.map +1 -0
- package/dist/domain/shared/read-ship-messages.d.ts +28 -0
- package/dist/domain/shared/read-ship-messages.js +30 -0
- package/dist/domain/shared/read-ship-messages.js.map +1 -0
- package/dist/domain/shared/read-ship-timeline.d.ts +18 -0
- package/dist/domain/shared/read-ship-timeline.js +16 -0
- package/dist/domain/shared/read-ship-timeline.js.map +1 -0
- package/dist/domain/shared/result.d.ts +16 -0
- package/dist/domain/shared/result.js +7 -0
- package/dist/domain/shared/result.js.map +1 -0
- package/dist/domain/shared/secrets.d.ts +26 -0
- package/dist/domain/shared/secrets.js +2 -0
- package/dist/domain/shared/secrets.js.map +1 -0
- package/dist/domain/shared/selector.d.ts +29 -0
- package/dist/domain/shared/selector.js +2 -0
- package/dist/domain/shared/selector.js.map +1 -0
- package/dist/domain/shared/unit-of-work.d.ts +13 -0
- package/dist/domain/shared/unit-of-work.js +2 -0
- package/dist/domain/shared/unit-of-work.js.map +1 -0
- package/dist/domain/shared/utc-day.d.ts +4 -0
- package/dist/domain/shared/utc-day.js +9 -0
- package/dist/domain/shared/utc-day.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/start.d.ts +6 -0
- package/dist/start.js +29 -0
- package/dist/start.js.map +1 -0
- package/dist/wiring.d.ts +158 -0
- package/dist/wiring.js +185 -0
- package/dist/wiring.js.map +1 -0
- package/package.json +58 -3
- package/prisma.config.ts +18 -0
- package/src/adapters/prisma/migrations/20260929124818_init/migration.sql +201 -0
- package/src/adapters/prisma/migrations/20260929160000_fleet_argo_console_session/migration.sql +130 -0
- package/src/adapters/prisma/migrations/20260929220017_operator_login/migration.sql +27 -0
- package/src/adapters/prisma/migrations/20260930090000_crew_token/migration.sql +5 -0
- package/src/adapters/prisma/migrations/20260930120000_send/migration.sql +30 -0
- package/src/adapters/prisma/migrations/20260930150000_receive/migration.sql +24 -0
- package/src/adapters/prisma/migrations/20261001010000_event_seq/migration.sql +34 -0
- package/src/adapters/prisma/migrations/20261001020000_console_session_end_reason/migration.sql +14 -0
- package/src/adapters/prisma/migrations/20261001030000_account_theme_session_device/migration.sql +8 -0
- package/src/adapters/prisma/migrations/20261001040000_lease_last_seen/migration.sql +2 -0
- package/src/adapters/prisma/migrations/20261002190000_lease_report/migration.sql +7 -0
- package/src/adapters/prisma/migrations/20261003140000_commission_key/migration.sql +7 -0
- package/src/adapters/prisma/migrations/20261003200000_message_model/migration.sql +5 -0
- package/src/adapters/prisma/migrations/20261003201000_lease_harness/migration.sql +2 -0
- package/src/adapters/prisma/migrations/20261004120000_operator_without_password/migration.sql +2 -0
- package/src/adapters/prisma/migrations/20261004121000_installation_requests/migration.sql +21 -0
- package/src/adapters/prisma/migrations/20261004122000_events_deleted_with_their_fleet/migration.sql +11 -0
- package/src/adapters/prisma/migrations/20261004130000_sign_in_tickets/migration.sql +16 -0
- package/src/adapters/prisma/migrations/20261004140000_fleet_limits/migration.sql +6 -0
- package/src/adapters/prisma/migrations/20261004141000_installation_settings/migration.sql +12 -0
- package/src/adapters/prisma/migrations/20261005090000_viewer_ship/migration.sql +2 -0
- package/src/adapters/prisma/migrations/20261005100000_viewer_sessions/migration.sql +20 -0
- package/src/adapters/prisma/migrations/20261005110000_notices/migration.sql +37 -0
- package/src/adapters/prisma/migrations/20261005120000_guide/migration.sql +34 -0
- package/src/adapters/prisma/migrations/20261006100000_fleet_crew_scope/migration.sql +8 -0
- package/src/adapters/prisma/migrations/20261006140000_lease_report_details/migration.sql +3 -0
- package/src/adapters/prisma/migrations/20261006160000_crew_requests/migration.sql +20 -0
- package/src/adapters/prisma/migrations/20261006180000_crew_scopes/migration.sql +9 -0
- package/src/adapters/prisma/migrations/20261006190000_crew_assignment/migration.sql +13 -0
- package/src/adapters/prisma/migrations/20261006200000_crew_request_reason/migration.sql +3 -0
- package/src/adapters/prisma/migrations/20261007020000_broad_crewing_scope_retired/migration.sql +8 -0
- package/src/adapters/prisma/migrations/migration_lock.toml +3 -0
- package/src/adapters/prisma/schema.prisma +558 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import fastifyWebsocket from '@fastify/websocket';
|
|
3
|
+
import { fastifyTRPCPlugin } from '@trpc/server/adapters/fastify';
|
|
4
|
+
import { getWSConnectionHandler, handleKeepAlive } from '@trpc/server/adapters/ws';
|
|
5
|
+
import Fastify, {} from 'fastify';
|
|
6
|
+
import { registerMcpEndpoint } from '../mcp/mcp-endpoint.js';
|
|
7
|
+
import { createFleetEventWakeups } from '../prisma/fleet-event-wakeups.js';
|
|
8
|
+
import { failureForLog } from '../prisma/failure-log.js';
|
|
9
|
+
import { registerRestApi } from '../rest/rest-api.js';
|
|
10
|
+
import { appRouter } from '../trpc/router.js';
|
|
11
|
+
import { refusalBody, unexpectedFailure } from '../trpc/ship-contract.js';
|
|
12
|
+
import { createRateLimiter } from './rate-limiter.js';
|
|
13
|
+
import { clearedSessionCookie, readBearer, readSessionToken, sessionCookie } from './request-credentials.js';
|
|
14
|
+
import { runningVersions } from './version.js';
|
|
15
|
+
import { INSTALLATION_TOKEN_HEADER } from '../trpc/installation.js';
|
|
16
|
+
/** A header's one value: a header sent twice counts as not sent. */
|
|
17
|
+
function headerValue(value) {
|
|
18
|
+
return typeof value === 'string' ? value : undefined;
|
|
19
|
+
}
|
|
20
|
+
/** Ten sign-in attempts per client per minute. */
|
|
21
|
+
export const DEFAULT_SIGN_IN_RATE_LIMIT = { limit: 10, windowMs: 60_000 };
|
|
22
|
+
/** Ten failed register attempts per client per minute; successful ones are never counted (ADR 0015). */
|
|
23
|
+
export const DEFAULT_REGISTER_RATE_LIMIT = { limit: 10, windowMs: 60_000 };
|
|
24
|
+
/**
|
|
25
|
+
* Refusals Fastify raises itself, before any route runs, by its error code:
|
|
26
|
+
* our code and words, never Fastify's, whose messages may echo the request.
|
|
27
|
+
*/
|
|
28
|
+
const FASTIFY_REFUSALS = {
|
|
29
|
+
FST_ERR_CTP_INVALID_JSON_BODY: { httpStatus: 400, code: 'BAD_REQUEST', message: 'The request body is not valid JSON' },
|
|
30
|
+
FST_ERR_CTP_EMPTY_JSON_BODY: { httpStatus: 400, code: 'BAD_REQUEST', message: 'The request body is not valid JSON' },
|
|
31
|
+
FST_ERR_CTP_BODY_TOO_LARGE: { httpStatus: 413, code: 'PAYLOAD_TOO_LARGE', message: 'The request body is over 1 MiB' },
|
|
32
|
+
FST_ERR_CTP_INVALID_MEDIA_TYPE: {
|
|
33
|
+
httpStatus: 415,
|
|
34
|
+
code: 'UNSUPPORTED_MEDIA_TYPE',
|
|
35
|
+
message: 'The request body must be JSON',
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
/** Any other request Fastify cannot read. */
|
|
39
|
+
const UNREADABLE_REQUEST = { httpStatus: 400, code: 'BAD_REQUEST', message: 'The request cannot be read' };
|
|
40
|
+
/**
|
|
41
|
+
* How often the server pings a live subscription's socket, and how long it
|
|
42
|
+
* waits for the pong before it closes it: a browser that went away without a
|
|
43
|
+
* word frees its subscription within a minute.
|
|
44
|
+
*/
|
|
45
|
+
const KEEP_ALIVE = { pingMs: 30_000, pongWaitMs: 10_000 };
|
|
46
|
+
/** Fastify's own limit on a request body, which its refusal above names: 1 MiB. */
|
|
47
|
+
const BODY_LIMIT_BYTES = 1024 * 1024;
|
|
48
|
+
/** How long a browser may keep the answer to a preflight, in seconds. */
|
|
49
|
+
const PREFLIGHT_MAX_AGE_S = 600;
|
|
50
|
+
/**
|
|
51
|
+
* The session cookie at a door for ships: REST and MCP never read the console
|
|
52
|
+
* session, so they never set or clear its cookie either.
|
|
53
|
+
*/
|
|
54
|
+
const NO_SESSION_COOKIE = { set: () => undefined, clear: () => undefined };
|
|
55
|
+
/**
|
|
56
|
+
* The HTTP host: `/trpc` for the API (its subscriptions over a WebSocket on
|
|
57
|
+
* the same path), `/api/v1` (REST) and `/mcp` for ships, and `/health` for
|
|
58
|
+
* monitoring. Every door builds its calls' context the same
|
|
59
|
+
* way, so the register limit is one budget per client address across all of
|
|
60
|
+
* them.
|
|
61
|
+
*/
|
|
62
|
+
export function buildHttpServer(options) {
|
|
63
|
+
const server = Fastify({
|
|
64
|
+
logger: options.logger ?? false,
|
|
65
|
+
trustProxy: options.shouldTrustProxy ?? false,
|
|
66
|
+
// Unique across restarts, so a caller's request id finds one log line.
|
|
67
|
+
genReqId: () => randomUUID(),
|
|
68
|
+
// tRPC batches several procedure paths into one URL segment.
|
|
69
|
+
routerOptions: { maxParamLength: 5000 },
|
|
70
|
+
bodyLimit: BODY_LIMIT_BYTES,
|
|
71
|
+
});
|
|
72
|
+
// Set first, so every door inherits it. A route's own failures are its own
|
|
73
|
+
// to answer; what reaches this is an error Fastify raised itself.
|
|
74
|
+
// eslint-disable-next-line @typescript-eslint/max-params -- Fastify calls its error handler with three arguments.
|
|
75
|
+
server.setErrorHandler(async (error, request, reply) => {
|
|
76
|
+
const isRefusal = error.statusCode !== undefined && error.statusCode < 500;
|
|
77
|
+
const refusal = FASTIFY_REFUSALS[error.code] ?? (isRefusal ? UNREADABLE_REQUEST : undefined);
|
|
78
|
+
if (refusal !== undefined) {
|
|
79
|
+
return reply.code(refusal.httpStatus).send({ code: refusal.code, message: refusal.message });
|
|
80
|
+
}
|
|
81
|
+
const failure = unexpectedFailure(error, { log: request.log, requestId: request.id });
|
|
82
|
+
return reply.code(failure.httpStatus).send(refusalBody(failure));
|
|
83
|
+
});
|
|
84
|
+
server.setNotFoundHandler(async (_request, reply) => reply.code(404).send({ code: 'NOT_FOUND', message: 'Nothing is served at this path' }));
|
|
85
|
+
const signInLimiter = createRateLimiter(options.signInRateLimit ?? DEFAULT_SIGN_IN_RATE_LIMIT, options.clock);
|
|
86
|
+
const registerFailures = createRateLimiter(options.registerRateLimit ?? DEFAULT_REGISTER_RATE_LIMIT, options.clock);
|
|
87
|
+
const { consoleOrigin, cookieDomain } = options;
|
|
88
|
+
const fleetEvents = options.fleetEvents ?? createFleetEventWakeups();
|
|
89
|
+
// The console may run on another host under the cookie's domain (ADR 0012).
|
|
90
|
+
// Its origin, and no other, may call with credentials and read the answer.
|
|
91
|
+
// On the server's own origin the browser needs none of this, and ignores it.
|
|
92
|
+
server.addHook('onRequest', async (request, reply) => {
|
|
93
|
+
void reply.header('vary', 'Origin');
|
|
94
|
+
if (request.headers.origin !== consoleOrigin) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
void reply.header('access-control-allow-origin', consoleOrigin);
|
|
98
|
+
void reply.header('access-control-allow-credentials', 'true');
|
|
99
|
+
if (request.method === 'OPTIONS') {
|
|
100
|
+
await reply
|
|
101
|
+
.code(204)
|
|
102
|
+
.header('access-control-allow-methods', 'GET, POST')
|
|
103
|
+
.header('access-control-allow-headers', 'content-type')
|
|
104
|
+
.header('access-control-max-age', String(PREFLIGHT_MAX_AGE_S))
|
|
105
|
+
.send();
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
// The versions this process runs and the database's latest migration, for
|
|
109
|
+
// whoever operates the installation. No authentication, no fleet data.
|
|
110
|
+
const versions = runningVersions();
|
|
111
|
+
server.get('/api/version', async () => {
|
|
112
|
+
let migration = null;
|
|
113
|
+
try {
|
|
114
|
+
migration = await options.latestMigration();
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
server.log.error(failureForLog(error), 'latest migration unknown');
|
|
118
|
+
}
|
|
119
|
+
return { ...versions, migration };
|
|
120
|
+
});
|
|
121
|
+
// Server up and database reachable. Nothing about fleets.
|
|
122
|
+
server.get('/health', async (_request, reply) => {
|
|
123
|
+
try {
|
|
124
|
+
await options.checkDatabase();
|
|
125
|
+
return { server: 'up', database: 'up' };
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
server.log.error(failureForLog(error), 'health check failed');
|
|
129
|
+
return reply.code(503).send({ server: 'up', database: 'down' });
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
/** A call's context: who it says it is, how it may say so at this door, and where it came from. */
|
|
133
|
+
const contextFor = (request, caller) => ({
|
|
134
|
+
useCases: options.useCases,
|
|
135
|
+
fleetUrl: options.fleetUrl,
|
|
136
|
+
installation: { configured: options.installationToken, presented: headerValue(request.headers[INSTALLATION_TOKEN_HEADER]) },
|
|
137
|
+
log: request.log,
|
|
138
|
+
fleetEvents,
|
|
139
|
+
...caller,
|
|
140
|
+
userAgent: request.headers['user-agent'],
|
|
141
|
+
origin: request.headers.origin,
|
|
142
|
+
consoleOrigin,
|
|
143
|
+
clientKey: request.ip,
|
|
144
|
+
requestId: request.id,
|
|
145
|
+
takeSignInAttempt: (clientKey) => signInLimiter.take(clientKey),
|
|
146
|
+
signInRetryAt: (clientKey) => signInLimiter.retryAt(clientKey),
|
|
147
|
+
registerFailures,
|
|
148
|
+
});
|
|
149
|
+
const trpc = {
|
|
150
|
+
prefix: '/trpc',
|
|
151
|
+
trpcOptions: {
|
|
152
|
+
router: appRouter,
|
|
153
|
+
createContext: ({ req, res }) => contextFor(req, {
|
|
154
|
+
credentials: {
|
|
155
|
+
bearer: readBearer(req.headers.authorization),
|
|
156
|
+
sessionToken: readSessionToken(req.headers.cookie),
|
|
157
|
+
},
|
|
158
|
+
canUseConsoleSession: true,
|
|
159
|
+
sessionCookie: {
|
|
160
|
+
set: (token, expiresAt) => {
|
|
161
|
+
void res.header('set-cookie', sessionCookie({ token, expiresAt, now: options.clock.now(), domain: cookieDomain }));
|
|
162
|
+
},
|
|
163
|
+
clear: () => {
|
|
164
|
+
void res.header('set-cookie', clearedSessionCookie(cookieDomain));
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
}),
|
|
168
|
+
// The whole failure goes to the log only, under the request's id (the
|
|
169
|
+
// label Fastify's own request lines use); the answer carries that id.
|
|
170
|
+
onError: ({ path, error, ctx }) => {
|
|
171
|
+
if (error.code === 'INTERNAL_SERVER_ERROR') {
|
|
172
|
+
server.log.error({ reqId: ctx?.requestId, path, ...failureForLog(error) }, 'procedure failed');
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
void server.register(fastifyTRPCPlugin, trpc);
|
|
178
|
+
// Live subscriptions: one WebSocket per console, opened on /trpc with the
|
|
179
|
+
// session cookie and the page's Origin, both of which a browser sends on
|
|
180
|
+
// the upgrade. Nothing can set a cookie on a socket, so the session's
|
|
181
|
+
// renewal waits for the console's next HTTP call.
|
|
182
|
+
void server.register(async (scope) => {
|
|
183
|
+
await scope.register(fastifyWebsocket);
|
|
184
|
+
const onConnection = getWSConnectionHandler({
|
|
185
|
+
router: appRouter,
|
|
186
|
+
wss: scope.websocketServer,
|
|
187
|
+
createContext: ({ req }) => contextFor({
|
|
188
|
+
headers: req.headers,
|
|
189
|
+
ip: req.socket.remoteAddress ?? '',
|
|
190
|
+
id: randomUUID(),
|
|
191
|
+
log: server.log,
|
|
192
|
+
}, {
|
|
193
|
+
credentials: { sessionToken: readSessionToken(req.headers.cookie) },
|
|
194
|
+
canUseConsoleSession: true,
|
|
195
|
+
sessionCookie: NO_SESSION_COOKIE,
|
|
196
|
+
}),
|
|
197
|
+
onError: ({ path, error, ctx }) => {
|
|
198
|
+
if (error.code === 'INTERNAL_SERVER_ERROR') {
|
|
199
|
+
server.log.error({ reqId: ctx?.requestId, path, ...failureForLog(error) }, 'subscription failed');
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
scope.get('/trpc', { websocket: true }, (socket, request) => {
|
|
204
|
+
onConnection(socket, request.raw);
|
|
205
|
+
handleKeepAlive(socket, KEEP_ALIVE.pingMs, KEEP_ALIVE.pongWaitMs);
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
// The doors for ships: the credentials are the ones the call carries, never the console session.
|
|
209
|
+
const shipDoor = {
|
|
210
|
+
contextFor: (request, credentials) => contextFor(request, { credentials, canUseConsoleSession: false, sessionCookie: NO_SESSION_COOKIE }),
|
|
211
|
+
};
|
|
212
|
+
registerRestApi(server, shipDoor);
|
|
213
|
+
registerMcpEndpoint(server, shipDoor);
|
|
214
|
+
return server;
|
|
215
|
+
}
|
|
216
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/adapters/http/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The versions this server process runs: its own package's, and that of the
|
|
3
|
+
* @aeolus-fleet/common it loaded, which a deploy that failed halfway may
|
|
4
|
+
* leave different. Read once, when the server starts.
|
|
5
|
+
*/
|
|
6
|
+
export declare function runningVersions(): {
|
|
7
|
+
server: string;
|
|
8
|
+
common: string;
|
|
9
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
const packageJson = z.object({ version: z.string() });
|
|
5
|
+
/** The version in a package.json, read from disk: what this process runs, not what a deploy meant to ship. */
|
|
6
|
+
function versionAt(file) {
|
|
7
|
+
return packageJson.parse(JSON.parse(readFileSync(file, 'utf8'))).version;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* The versions this server process runs: its own package's, and that of the
|
|
11
|
+
* @aeolus-fleet/common it loaded, which a deploy that failed halfway may
|
|
12
|
+
* leave different. Read once, when the server starts.
|
|
13
|
+
*/
|
|
14
|
+
export function runningVersions() {
|
|
15
|
+
// This file sits at src/adapters/http, or dist/adapters/http once built:
|
|
16
|
+
// the package root is three levels up either way.
|
|
17
|
+
const server = versionAt(new URL('../../../package.json', import.meta.url));
|
|
18
|
+
const commonEntry = createRequire(import.meta.url).resolve('@aeolus-fleet/common');
|
|
19
|
+
// Common's entry is src/index.ts or dist/index.js: its package.json is one level up.
|
|
20
|
+
const common = versionAt(new URL('../package.json', `file://${commonEntry}`));
|
|
21
|
+
return { server, common };
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../../src/adapters/http/version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAEtD,8GAA8G;AAC9G,SAAS,SAAS,CAAC,IAAkB;IACnC,OAAO,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;AAC3E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe;IAC7B,yEAAyE;IACzE,kDAAkD;IAClD,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,GAAG,CAAC,uBAAuB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5E,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACnF,qFAAqF;IACrF,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,GAAG,CAAC,iBAAiB,EAAE,UAAU,WAAW,EAAE,CAAC,CAAC,CAAC;IAC9E,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FastifyInstance, FastifyRequest } from 'fastify';
|
|
2
|
+
import type { Context, RequestCredentials } from '../trpc/context.js';
|
|
3
|
+
export interface McpEndpointOptions {
|
|
4
|
+
/** The context of one call, for this request, with the credentials the tool call carries. */
|
|
5
|
+
contextFor: (request: FastifyRequest, credentials: RequestCredentials) => Context;
|
|
6
|
+
}
|
|
7
|
+
/** Mounts `/mcp` on the HTTP server. */
|
|
8
|
+
export declare function registerMcpEndpoint(server: FastifyInstance, options: McpEndpointOptions): void;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `/mcp`: the ship contract as a remote MCP server, over streamable HTTP with
|
|
3
|
+
* the official SDK (ADR 0004). One tool per ship procedure, listed and called
|
|
4
|
+
* through the router (see trpc/ship-contract.ts); nothing here decides
|
|
5
|
+
* anything about a ship.
|
|
6
|
+
*
|
|
7
|
+
* The connection carries no ship (ADR 0015): many conversations share one
|
|
8
|
+
* MCP connection, each crewing its own ship. So every tool but `register`
|
|
9
|
+
* takes the crew token as its `crewToken` argument, and no header of the
|
|
10
|
+
* connection is ever read as a credential. The endpoint is stateless: a fresh
|
|
11
|
+
* server answers each HTTP request, and nothing is kept between them.
|
|
12
|
+
*/
|
|
13
|
+
import { MCP_PATH } from '@aeolus-fleet/common';
|
|
14
|
+
import { createMcpHandler, McpServer, } from '@modelcontextprotocol/server';
|
|
15
|
+
import { z } from 'zod';
|
|
16
|
+
import { callShip, refusalBody, SHIP_CALLS, unexpectedFailure, } from '../trpc/ship-contract.js';
|
|
17
|
+
import { SHIP_PROTOCOL } from '../trpc/ship-protocol.js';
|
|
18
|
+
/** How the server names itself to MCP clients. Its version is the ship contract's, as in `/api/v1`. */
|
|
19
|
+
const SERVER_INFO = { name: 'aeolus-fleet', version: '1' };
|
|
20
|
+
const CREW_TOKEN_PROPERTY = {
|
|
21
|
+
type: 'string',
|
|
22
|
+
description: 'The crew token register gave you (aeolus_ct_v1_...): it says which ship you crew.',
|
|
23
|
+
};
|
|
24
|
+
/** The one credential a tool takes as an argument. Whether it is a valid one is for the router to judge. */
|
|
25
|
+
const crewTokenArgument = z.string();
|
|
26
|
+
const objectOutput = z.looseObject({ type: z.literal('object') });
|
|
27
|
+
/** A ship call as an MCP tool: every one but `register` asks for the crew token first. */
|
|
28
|
+
function toolOf(call) {
|
|
29
|
+
const input = call.input?.schema ?? { type: 'object', properties: {}, required: [] };
|
|
30
|
+
const inputSchema = call.credential === 'crewToken'
|
|
31
|
+
? {
|
|
32
|
+
...input,
|
|
33
|
+
properties: { crewToken: CREW_TOKEN_PROPERTY, ...input.properties },
|
|
34
|
+
required: ['crewToken', ...input.required],
|
|
35
|
+
}
|
|
36
|
+
: input;
|
|
37
|
+
// MCP takes an output schema only for an object; fleet_list answers a list, as text.
|
|
38
|
+
return {
|
|
39
|
+
name: call.name,
|
|
40
|
+
description: call.description,
|
|
41
|
+
inputSchema,
|
|
42
|
+
...(call.output.type === 'object' && { outputSchema: objectOutput.parse(call.output) }),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
const TOOLS = SHIP_CALLS.map(toolOf);
|
|
46
|
+
/** A tool error the model reads: the code first, so it can tell a refusal from a failure. */
|
|
47
|
+
function refusalResult(refusal) {
|
|
48
|
+
const { code, message, requestId } = refusal;
|
|
49
|
+
const text = requestId === undefined ? `${code}: ${message}` : `${code}: ${message} (request id ${requestId})`;
|
|
50
|
+
return { content: [{ type: 'text', text }], isError: true };
|
|
51
|
+
}
|
|
52
|
+
/** One tool call, as a call through the router with the crew token its arguments carry. */
|
|
53
|
+
async function callTool(params, at) {
|
|
54
|
+
const { request, options } = at;
|
|
55
|
+
const call = SHIP_CALLS.find((candidate) => candidate.name === params.name);
|
|
56
|
+
if (!call) {
|
|
57
|
+
const names = SHIP_CALLS.map((known) => known.name).join(', ');
|
|
58
|
+
return refusalResult({
|
|
59
|
+
code: 'NOT_FOUND',
|
|
60
|
+
message: `There is no tool named ${params.name}. The tools are ${names}.`,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
const args = params.arguments ?? {};
|
|
64
|
+
const { crewToken, ...input } = args;
|
|
65
|
+
const result = await callShip(call, call.credential === 'crewToken'
|
|
66
|
+
? { ctx: options.contextFor(request, { bearer: crewTokenArgument.safeParse(crewToken).data }), input, log: request.log }
|
|
67
|
+
: { ctx: options.contextFor(request, {}), input: args, log: request.log });
|
|
68
|
+
if (!result.isOk) {
|
|
69
|
+
return refusalResult(result.refusal);
|
|
70
|
+
}
|
|
71
|
+
const text = JSON.stringify(result.output);
|
|
72
|
+
const structuredContent = z.record(z.string(), z.unknown()).safeParse(result.output);
|
|
73
|
+
return structuredContent.success
|
|
74
|
+
? { content: [{ type: 'text', text }], structuredContent: structuredContent.data }
|
|
75
|
+
: { content: [{ type: 'text', text }] };
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* The MCP server answering one HTTP request: the ship tools, each a call
|
|
79
|
+
* through the router, and the ship protocol as its instructions, which a
|
|
80
|
+
* client reads when it connects. It answers `tools/list` and `tools/call`
|
|
81
|
+
* itself, at the protocol level, rather than registering each tool: a
|
|
82
|
+
* registered tool's arguments are validated by the SDK before its handler
|
|
83
|
+
* runs, and the router must be the one to judge them, so a refusal reads with
|
|
84
|
+
* its own code.
|
|
85
|
+
*/
|
|
86
|
+
function shipToolServer(request, options) {
|
|
87
|
+
const mcp = new McpServer(SERVER_INFO, { capabilities: { tools: {} }, instructions: SHIP_PROTOCOL });
|
|
88
|
+
mcp.server.setRequestHandler('tools/list', () => ({ tools: TOOLS }));
|
|
89
|
+
// A failure here would otherwise reach the client as a protocol error in its own words.
|
|
90
|
+
mcp.server.setRequestHandler('tools/call', async ({ params }) => {
|
|
91
|
+
try {
|
|
92
|
+
return await callTool(params, { request, options });
|
|
93
|
+
}
|
|
94
|
+
catch (thrown) {
|
|
95
|
+
return refusalResult(unexpectedFailure(thrown, { log: request.log, requestId: request.id }));
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
return mcp;
|
|
99
|
+
}
|
|
100
|
+
/** The request as the SDK's web-standard handler takes it. Fastify has read the JSON body already. */
|
|
101
|
+
function webRequestOf(request) {
|
|
102
|
+
const headers = new Headers();
|
|
103
|
+
for (const [name, value] of Object.entries(request.headers)) {
|
|
104
|
+
for (const each of Array.isArray(value) ? value : [value]) {
|
|
105
|
+
if (each !== undefined) {
|
|
106
|
+
headers.append(name, each);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return new Request(new URL(request.url, `${request.protocol}://${request.host}`), { method: request.method, headers });
|
|
111
|
+
}
|
|
112
|
+
/** Mounts `/mcp` on the HTTP server. */
|
|
113
|
+
export function registerMcpEndpoint(server, options) {
|
|
114
|
+
server.all(MCP_PATH, async (request, reply) => {
|
|
115
|
+
try {
|
|
116
|
+
// A handler per request, so each tool call knows the request it came
|
|
117
|
+
// with: its client address for the register limit, its id for the log.
|
|
118
|
+
const handler = createMcpHandler(() => shipToolServer(request, options));
|
|
119
|
+
return await handler.fetch(webRequestOf(request), { parsedBody: request.body });
|
|
120
|
+
}
|
|
121
|
+
catch (thrown) {
|
|
122
|
+
const refusal = unexpectedFailure(thrown, { log: request.log, requestId: request.id });
|
|
123
|
+
return await reply.code(refusal.httpStatus).send(refusalBody(refusal));
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=mcp-endpoint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-endpoint.js","sourceRoot":"","sources":["../../../src/adapters/mcp/mcp-endpoint.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { PrismaClient, type Prisma } from './generated/client.js';
|
|
2
|
+
export type { PrismaClient } from './generated/client.js';
|
|
3
|
+
/** The client itself, or the client of one interactive transaction. Repositories take either. */
|
|
4
|
+
export type Db = PrismaClient | Prisma.TransactionClient;
|
|
5
|
+
/** Creates a Prisma client on a pg connection pool for the given database. */
|
|
6
|
+
export declare function createPrismaClient(databaseUrl: string): PrismaClient;
|
|
7
|
+
/** Throws when the database cannot answer a trivial query. */
|
|
8
|
+
export declare function checkDatabase(prisma: PrismaClient): Promise<void>;
|
|
9
|
+
/** The latest migration applied to the database, by name; null before the first. */
|
|
10
|
+
export declare function latestMigration(db: PrismaClient): Promise<string | null>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { PrismaPg } from '@prisma/adapter-pg';
|
|
2
|
+
import { PrismaClient } from './generated/client.js';
|
|
3
|
+
/** Creates a Prisma client on a pg connection pool for the given database. */
|
|
4
|
+
export function createPrismaClient(databaseUrl) {
|
|
5
|
+
return new PrismaClient({ adapter: new PrismaPg({ connectionString: databaseUrl }) });
|
|
6
|
+
}
|
|
7
|
+
/** Throws when the database cannot answer a trivial query. */
|
|
8
|
+
export async function checkDatabase(prisma) {
|
|
9
|
+
await prisma.$queryRaw `SELECT 1`;
|
|
10
|
+
}
|
|
11
|
+
/** The latest migration applied to the database, by name; null before the first. */
|
|
12
|
+
export async function latestMigration(db) {
|
|
13
|
+
const [row] = await db.$queryRaw `
|
|
14
|
+
SELECT migration_name FROM _prisma_migrations
|
|
15
|
+
WHERE finished_at IS NOT NULL AND rolled_back_at IS NULL
|
|
16
|
+
ORDER BY migration_name DESC
|
|
17
|
+
LIMIT 1`;
|
|
18
|
+
return row?.migration_name ?? null;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/adapters/prisma/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,OAAO,EAAE,YAAY,EAAe,MAAM,uBAAuB,CAAC;AAOlE,8EAA8E;AAC9E,MAAM,UAAU,kBAAkB,CAAC,WAAmB;IACpD,OAAO,IAAI,YAAY,CAAC,EAAE,OAAO,EAAE,IAAI,QAAQ,CAAC,EAAE,gBAAgB,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC,CAAC;AACxF,CAAC;AAED,8DAA8D;AAC9D,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAoB;IACtD,MAAM,MAAM,CAAC,SAAS,CAAA,UAAU,CAAC;AACnC,CAAC;AAED,oFAAoF;AACpF,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,EAAgB;IACpD,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,EAAE,CAAC,SAAS,CAA8B;;;;YAIpD,CAAC;IACX,OAAO,GAAG,EAAE,cAAc,IAAI,IAAI,CAAC;AACrC,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { FleetEventNotice } from '../../domain/shared/events.js';
|
|
2
|
+
import type { DeliveryNotice, Notifier } from '../../domain/shared/notifier.js';
|
|
3
|
+
import type { Db } from './client.js';
|
|
4
|
+
/** The one channel every pending delivery is announced on. */
|
|
5
|
+
export declare const DELIVERY_PENDING_CHANNEL = "aeolus_delivery_pending";
|
|
6
|
+
export declare function createPrismaNotifier(db: Db): Notifier;
|
|
7
|
+
/** How the listener names its connection in Postgres (`application_name`), so it can be found there. */
|
|
8
|
+
export declare const LISTENER_APPLICATION_NAME = "aeolus-delivery-listener";
|
|
9
|
+
export interface DeliveryListener {
|
|
10
|
+
/** Settles once the listener first listens: notices of later commits reach it. */
|
|
11
|
+
listening: Promise<void>;
|
|
12
|
+
close(): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Listens for pending deliveries on a connection of its own: LISTEN needs one
|
|
16
|
+
* that no pool hands to another query, and it must be direct, not through a
|
|
17
|
+
* transaction pooler. Waiting receives and live subscriptions are woken
|
|
18
|
+
* through it. Returns at once.
|
|
19
|
+
*
|
|
20
|
+
* It never throws: a failed connect or a lost connection goes to `onError`,
|
|
21
|
+
* and it tries again after a delay that doubles with each failure, up to 30
|
|
22
|
+
* seconds. Notices sent while it did not listen are gone, so `onListening`
|
|
23
|
+
* runs each time it starts listening, for the waiting receives to look again.
|
|
24
|
+
*/
|
|
25
|
+
export declare function listenForPendingDeliveries(options: {
|
|
26
|
+
databaseUrl: string;
|
|
27
|
+
onNotice: (notice: DeliveryNotice) => void;
|
|
28
|
+
/** Hears that a fleet's events up to a number have committed (event-log.ts), for live subscriptions. */
|
|
29
|
+
onFleetEvent?: (notice: FleetEventNotice) => void;
|
|
30
|
+
onListening?: () => void;
|
|
31
|
+
onError?: (error: Error) => void;
|
|
32
|
+
/** The first wait before trying again; 1 second unless a test says otherwise. */
|
|
33
|
+
reconnectDelayMs?: number;
|
|
34
|
+
}): DeliveryListener;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wakes receivers with Postgres LISTEN/NOTIFY (ADR 0003). A send notifies on
|
|
3
|
+
* one channel inside its transaction; Postgres hands the notice to listeners
|
|
4
|
+
* only when that transaction commits, and drops it when it rolls back. The
|
|
5
|
+
* payload says which delivery is pending and for whom, never the message's
|
|
6
|
+
* payload. The same connection hears committed events (event-log.ts) for the
|
|
7
|
+
* live subscriptions.
|
|
8
|
+
*/
|
|
9
|
+
import pg from 'pg';
|
|
10
|
+
import { FLEET_EVENT_CHANNEL } from './event-log.js';
|
|
11
|
+
import { toDeliveryNotice, toFleetEventNotice } from './rows.js';
|
|
12
|
+
/** The one channel every pending delivery is announced on. */
|
|
13
|
+
export const DELIVERY_PENDING_CHANNEL = 'aeolus_delivery_pending';
|
|
14
|
+
export function createPrismaNotifier(db) {
|
|
15
|
+
return {
|
|
16
|
+
deliveryPending: async (notice) => {
|
|
17
|
+
await db.$executeRaw `SELECT pg_notify(${DELIVERY_PENDING_CHANNEL}, ${JSON.stringify(notice)})`;
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/** How the listener names its connection in Postgres (`application_name`), so it can be found there. */
|
|
22
|
+
export const LISTENER_APPLICATION_NAME = 'aeolus-delivery-listener';
|
|
23
|
+
/** The first wait before the listener tries again after losing its connection; each failure doubles it. */
|
|
24
|
+
const RECONNECT_DELAY_MS = 1_000;
|
|
25
|
+
/** The longest wait between two tries. */
|
|
26
|
+
const RECONNECT_DELAY_MAX_MS = 30_000;
|
|
27
|
+
/**
|
|
28
|
+
* Listens for pending deliveries on a connection of its own: LISTEN needs one
|
|
29
|
+
* that no pool hands to another query, and it must be direct, not through a
|
|
30
|
+
* transaction pooler. Waiting receives and live subscriptions are woken
|
|
31
|
+
* through it. Returns at once.
|
|
32
|
+
*
|
|
33
|
+
* It never throws: a failed connect or a lost connection goes to `onError`,
|
|
34
|
+
* and it tries again after a delay that doubles with each failure, up to 30
|
|
35
|
+
* seconds. Notices sent while it did not listen are gone, so `onListening`
|
|
36
|
+
* runs each time it starts listening, for the waiting receives to look again.
|
|
37
|
+
*/
|
|
38
|
+
export function listenForPendingDeliveries(options) {
|
|
39
|
+
const firstDelayMs = options.reconnectDelayMs ?? RECONNECT_DELAY_MS;
|
|
40
|
+
const listening = Promise.withResolvers();
|
|
41
|
+
const report = (error) => {
|
|
42
|
+
options.onError?.(error instanceof Error ? error : new Error(String(error)));
|
|
43
|
+
};
|
|
44
|
+
let current;
|
|
45
|
+
let retry;
|
|
46
|
+
let delayMs = firstDelayMs;
|
|
47
|
+
let isClosed = false;
|
|
48
|
+
/** Gives up a client that failed and tries again later: once per client, and never after close. */
|
|
49
|
+
const tryAgainLater = (failed) => {
|
|
50
|
+
if (isClosed || failed !== current) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
current = undefined;
|
|
54
|
+
failed.end().catch(() => undefined);
|
|
55
|
+
retry = setTimeout(connect, delayMs);
|
|
56
|
+
delayMs = Math.min(delayMs * 2, RECONNECT_DELAY_MAX_MS);
|
|
57
|
+
};
|
|
58
|
+
const connect = () => {
|
|
59
|
+
retry = undefined;
|
|
60
|
+
const client = new pg.Client({ connectionString: options.databaseUrl, application_name: LISTENER_APPLICATION_NAME });
|
|
61
|
+
current = client;
|
|
62
|
+
client.on('error', (error) => {
|
|
63
|
+
report(error);
|
|
64
|
+
tryAgainLater(client);
|
|
65
|
+
});
|
|
66
|
+
client.on('end', () => {
|
|
67
|
+
tryAgainLater(client);
|
|
68
|
+
});
|
|
69
|
+
client.on('notification', ({ channel, payload }) => {
|
|
70
|
+
if (payload === undefined) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
if (channel === DELIVERY_PENDING_CHANNEL) {
|
|
75
|
+
options.onNotice(toDeliveryNotice(JSON.parse(payload)));
|
|
76
|
+
}
|
|
77
|
+
else if (channel === FLEET_EVENT_CHANNEL) {
|
|
78
|
+
options.onFleetEvent?.(toFleetEventNotice(JSON.parse(payload)));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
report(error);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
client
|
|
86
|
+
.connect()
|
|
87
|
+
// The channels are constants, never outside input.
|
|
88
|
+
.then(() => client.query(`LISTEN ${DELIVERY_PENDING_CHANNEL}; LISTEN ${FLEET_EVENT_CHANNEL}`))
|
|
89
|
+
.then(() => {
|
|
90
|
+
if (client !== current) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
delayMs = firstDelayMs;
|
|
94
|
+
listening.resolve(undefined);
|
|
95
|
+
options.onListening?.();
|
|
96
|
+
}, (error) => {
|
|
97
|
+
report(error);
|
|
98
|
+
tryAgainLater(client);
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
connect();
|
|
102
|
+
return {
|
|
103
|
+
listening: listening.promise,
|
|
104
|
+
close: async () => {
|
|
105
|
+
isClosed = true;
|
|
106
|
+
clearTimeout(retry);
|
|
107
|
+
const client = current;
|
|
108
|
+
current = undefined;
|
|
109
|
+
await client?.end().catch(() => undefined);
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=delivery-notices.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delivery-notices.js","sourceRoot":"","sources":["../../../src/adapters/prisma/delivery-notices.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,MAAM,IAAI,CAAC;AAKpB,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAEjE,8DAA8D;AAC9D,MAAM,CAAC,MAAM,wBAAwB,GAAG,yBAAyB,CAAC;AAElE,MAAM,UAAU,oBAAoB,CAAC,EAAM;IACzC,OAAO;QACL,eAAe,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;YAChC,MAAM,EAAE,CAAC,WAAW,CAAA,oBAAoB,wBAAwB,KAAK,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC;QACjG,CAAC;KACF,CAAC;AACJ,CAAC;AAED,wGAAwG;AACxG,MAAM,CAAC,MAAM,yBAAyB,GAAG,0BAA0B,CAAC;AAEpE,2GAA2G;AAC3G,MAAM,kBAAkB,GAAG,KAAK,CAAC;AAEjC,0CAA0C;AAC1C,MAAM,sBAAsB,GAAG,MAAM,CAAC;AAQtC;;;;;;;;;;GAUG;AACH,MAAM,UAAU,0BAA0B,CAAC,OAS1C;IACC,MAAM,YAAY,GAAG,OAAO,CAAC,gBAAgB,IAAI,kBAAkB,CAAC;IACpE,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,EAAa,CAAC;IACrD,MAAM,MAAM,GAAG,CAAC,KAAc,EAAE,EAAE;QAChC,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC/E,CAAC,CAAC;IAEF,IAAI,OAA8B,CAAC;IACnC,IAAI,KAAiC,CAAC;IACtC,IAAI,OAAO,GAAG,YAAY,CAAC;IAC3B,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,mGAAmG;IACnG,MAAM,aAAa,GAAG,CAAC,MAAiB,EAAE,EAAE;QAC1C,IAAI,QAAQ,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;YACnC,OAAO;QACT,CAAC;QACD,OAAO,GAAG,SAAS,CAAC;QACpB,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACpC,KAAK,GAAG,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACrC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,CAAC,EAAE,sBAAsB,CAAC,CAAC;IAC1D,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,GAAG,EAAE;QACnB,KAAK,GAAG,SAAS,CAAC;QAClB,MAAM,MAAM,GAAG,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,gBAAgB,EAAE,OAAO,CAAC,WAAW,EAAE,gBAAgB,EAAE,yBAAyB,EAAE,CAAC,CAAC;QACrH,OAAO,GAAG,MAAM,CAAC;QACjB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YAC3B,MAAM,CAAC,KAAK,CAAC,CAAC;YACd,aAAa,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;YACpB,aAAa,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,cAAc,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE;YACjD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBAC1B,OAAO;YACT,CAAC;YACD,IAAI,CAAC;gBACH,IAAI,OAAO,KAAK,wBAAwB,EAAE,CAAC;oBACzC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;gBAC1D,CAAC;qBAAM,IAAI,OAAO,KAAK,mBAAmB,EAAE,CAAC;oBAC3C,OAAO,CAAC,YAAY,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;gBAClE,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,KAAK,CAAC,CAAC;YAChB,CAAC;QACH,CAAC,CAAC,CAAC;QACH,MAAM;aACH,OAAO,EAAE;YACV,mDAAmD;aAClD,IAAI,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,wBAAwB,YAAY,mBAAmB,EAAE,CAAC,CAAC;aAC7F,IAAI,CACH,GAAG,EAAE;YACH,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;gBACvB,OAAO;YACT,CAAC;YACD,OAAO,GAAG,YAAY,CAAC;YACvB,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YAC7B,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;QAC1B,CAAC,EACD,CAAC,KAAc,EAAE,EAAE;YACjB,MAAM,CAAC,KAAK,CAAC,CAAC;YACd,aAAa,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC,CACF,CAAC;IACN,CAAC,CAAC;IAEF,OAAO,EAAE,CAAC;IACV,OAAO;QACL,SAAS,EAAE,SAAS,CAAC,OAAO;QAC5B,KAAK,EAAE,KAAK,IAAI,EAAE;YAChB,QAAQ,GAAG,IAAI,CAAC;YAChB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,MAAM,MAAM,GAAG,OAAO,CAAC;YACvB,OAAO,GAAG,SAAS,CAAC;YACpB,MAAM,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC7C,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { EventLog, FleetEventFeed } from '../../domain/shared/events.js';
|
|
2
|
+
import type { Db } from './client.js';
|
|
3
|
+
/** The one channel every committed event is announced on, with its fleet and the last number. */
|
|
4
|
+
export declare const FLEET_EVENT_CHANNEL = "aeolus_event";
|
|
5
|
+
export interface BufferedEventLog extends EventLog {
|
|
6
|
+
/** Numbers and writes the held events and announces them. The unit of work's last step before commit. */
|
|
7
|
+
flush(): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
export declare function createPrismaEventLog(db: Db): BufferedEventLog;
|
|
10
|
+
/** Reads committed events by number. Each read is one statement, outside a unit of work. */
|
|
11
|
+
export declare function createPrismaFleetEventFeed(db: Db): FleetEventFeed;
|