@mastra/factory 0.0.0 → 0.1.0-alpha.3
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/CHANGELOG.md +23 -0
- package/LICENSE.md +30 -0
- package/dist/auth.d.ts +181 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +370 -0
- package/dist/auth.js.map +1 -0
- package/dist/capabilities/connection.d.ts +9 -0
- package/dist/capabilities/connection.d.ts.map +1 -0
- package/dist/capabilities/connection.js +1 -0
- package/dist/capabilities/connection.js.map +1 -0
- package/dist/capabilities/intake.d.ts +93 -0
- package/dist/capabilities/intake.d.ts.map +1 -0
- package/dist/capabilities/intake.js +1 -0
- package/dist/capabilities/intake.js.map +1 -0
- package/dist/capabilities/version-control.d.ts +239 -0
- package/dist/capabilities/version-control.d.ts.map +1 -0
- package/dist/capabilities/version-control.js +1 -0
- package/dist/capabilities/version-control.js.map +1 -0
- package/dist/factory.d.ts +145 -0
- package/dist/factory.d.ts.map +1 -0
- package/dist/factory.js +38245 -0
- package/dist/factory.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38245 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/base.d.ts +197 -0
- package/dist/integrations/base.d.ts.map +1 -0
- package/dist/integrations/base.js +1 -0
- package/dist/integrations/base.js.map +1 -0
- package/dist/integrations/github/config.d.ts +60 -0
- package/dist/integrations/github/config.d.ts.map +1 -0
- package/dist/integrations/github/config.js +28 -0
- package/dist/integrations/github/config.js.map +1 -0
- package/dist/integrations/github/factory-session.d.ts +12 -0
- package/dist/integrations/github/factory-session.d.ts.map +1 -0
- package/dist/integrations/github/factory-session.js +41 -0
- package/dist/integrations/github/factory-session.js.map +1 -0
- package/dist/integrations/github/integration.d.ts +191 -0
- package/dist/integrations/github/integration.d.ts.map +1 -0
- package/dist/integrations/github/integration.js +3001 -0
- package/dist/integrations/github/integration.js.map +1 -0
- package/dist/integrations/github/issue-triage.d.ts +27 -0
- package/dist/integrations/github/issue-triage.d.ts.map +1 -0
- package/dist/integrations/github/issue-triage.js +82 -0
- package/dist/integrations/github/issue-triage.js.map +1 -0
- package/dist/integrations/github/project-lock.d.ts +78 -0
- package/dist/integrations/github/project-lock.d.ts.map +1 -0
- package/dist/integrations/github/project-lock.js +70 -0
- package/dist/integrations/github/project-lock.js.map +1 -0
- package/dist/integrations/github/provenance.d.ts +27 -0
- package/dist/integrations/github/provenance.d.ts.map +1 -0
- package/dist/integrations/github/provenance.js +104 -0
- package/dist/integrations/github/provenance.js.map +1 -0
- package/dist/integrations/github/routes.d.ts +72 -0
- package/dist/integrations/github/routes.d.ts.map +1 -0
- package/dist/integrations/github/routes.js +1834 -0
- package/dist/integrations/github/routes.js.map +1 -0
- package/dist/integrations/github/sandbox.d.ts +268 -0
- package/dist/integrations/github/sandbox.d.ts.map +1 -0
- package/dist/integrations/github/sandbox.js +381 -0
- package/dist/integrations/github/sandbox.js.map +1 -0
- package/dist/integrations/github/session-subscriptions.d.ts +23 -0
- package/dist/integrations/github/session-subscriptions.d.ts.map +1 -0
- package/dist/integrations/github/session-subscriptions.js +190 -0
- package/dist/integrations/github/session-subscriptions.js.map +1 -0
- package/dist/integrations/github/subscriptions.d.ts +54 -0
- package/dist/integrations/github/subscriptions.d.ts.map +1 -0
- package/dist/integrations/github/subscriptions.js +70 -0
- package/dist/integrations/github/subscriptions.js.map +1 -0
- package/dist/integrations/github/webhook.d.ts +87 -0
- package/dist/integrations/github/webhook.d.ts.map +1 -0
- package/dist/integrations/github/webhook.js +381 -0
- package/dist/integrations/github/webhook.js.map +1 -0
- package/dist/integrations/linear/agent-tools.d.ts +34 -0
- package/dist/integrations/linear/agent-tools.d.ts.map +1 -0
- package/dist/integrations/linear/agent-tools.js +108 -0
- package/dist/integrations/linear/agent-tools.js.map +1 -0
- package/dist/integrations/linear/integration.d.ts +233 -0
- package/dist/integrations/linear/integration.d.ts.map +1 -0
- package/dist/integrations/linear/integration.js +962 -0
- package/dist/integrations/linear/integration.js.map +1 -0
- package/dist/integrations/linear/routes.d.ts +61 -0
- package/dist/integrations/linear/routes.d.ts.map +1 -0
- package/dist/integrations/linear/routes.js +242 -0
- package/dist/integrations/linear/routes.js.map +1 -0
- package/dist/integrations/linear/storage.d.ts +65 -0
- package/dist/integrations/linear/storage.d.ts.map +1 -0
- package/dist/integrations/linear/storage.js +1 -0
- package/dist/integrations/linear/storage.js.map +1 -0
- package/dist/integrations/platform/api-client.d.ts +24 -0
- package/dist/integrations/platform/api-client.d.ts.map +1 -0
- package/dist/integrations/platform/api-client.js +153 -0
- package/dist/integrations/platform/api-client.js.map +1 -0
- package/dist/integrations/platform/github/event-worker.d.ts +44 -0
- package/dist/integrations/platform/github/event-worker.d.ts.map +1 -0
- package/dist/integrations/platform/github/event-worker.js +585 -0
- package/dist/integrations/platform/github/event-worker.js.map +1 -0
- package/dist/integrations/platform/github/integration.d.ts +36 -0
- package/dist/integrations/platform/github/integration.d.ts.map +1 -0
- package/dist/integrations/platform/github/integration.js +3253 -0
- package/dist/integrations/platform/github/integration.js.map +1 -0
- package/dist/integrations/platform/linear/integration.d.ts +46 -0
- package/dist/integrations/platform/linear/integration.d.ts.map +1 -0
- package/dist/integrations/platform/linear/integration.js +891 -0
- package/dist/integrations/platform/linear/integration.js.map +1 -0
- package/dist/integrations/workos/integration.d.ts +39 -0
- package/dist/integrations/workos/integration.d.ts.map +1 -0
- package/dist/integrations/workos/integration.js +96 -0
- package/dist/integrations/workos/integration.js.map +1 -0
- package/dist/routes/config.d.ts +220 -0
- package/dist/routes/config.d.ts.map +1 -0
- package/dist/routes/config.js +770 -0
- package/dist/routes/config.js.map +1 -0
- package/dist/routes/fs.d.ts +105 -0
- package/dist/routes/fs.d.ts.map +1 -0
- package/dist/routes/fs.js +294 -0
- package/dist/routes/fs.js.map +1 -0
- package/dist/routes/intake.d.ts +23 -0
- package/dist/routes/intake.d.ts.map +1 -0
- package/dist/routes/intake.js +179 -0
- package/dist/routes/intake.js.map +1 -0
- package/dist/routes/oauth.d.ts +43 -0
- package/dist/routes/oauth.d.ts.map +1 -0
- package/dist/routes/oauth.js +25058 -0
- package/dist/routes/oauth.js.map +1 -0
- package/dist/routes/projects.d.ts +19 -0
- package/dist/routes/projects.d.ts.map +1 -0
- package/dist/routes/projects.js +395 -0
- package/dist/routes/projects.js.map +1 -0
- package/dist/routes/provider-credentials.d.ts +81 -0
- package/dist/routes/provider-credentials.d.ts.map +1 -0
- package/dist/routes/provider-credentials.js +68 -0
- package/dist/routes/provider-credentials.js.map +1 -0
- package/dist/routes/route.d.ts +48 -0
- package/dist/routes/route.d.ts.map +1 -0
- package/dist/routes/route.js +11 -0
- package/dist/routes/route.js.map +1 -0
- package/dist/routes/skills.d.ts +30 -0
- package/dist/routes/skills.d.ts.map +1 -0
- package/dist/routes/skills.js +181 -0
- package/dist/routes/skills.js.map +1 -0
- package/dist/routes/surface.d.ts +83 -0
- package/dist/routes/surface.d.ts.map +1 -0
- package/dist/routes/surface.js +28519 -0
- package/dist/routes/surface.js.map +1 -0
- package/dist/routes/tenant-credentials.d.ts +74 -0
- package/dist/routes/tenant-credentials.d.ts.map +1 -0
- package/dist/routes/tenant-credentials.js +181 -0
- package/dist/routes/tenant-credentials.js.map +1 -0
- package/dist/routes/work-items.d.ts +40 -0
- package/dist/routes/work-items.d.ts.map +1 -0
- package/dist/routes/work-items.js +902 -0
- package/dist/routes/work-items.js.map +1 -0
- package/dist/rules/binding-context.d.ts +5 -0
- package/dist/rules/binding-context.d.ts.map +1 -0
- package/dist/rules/binding-context.js +40 -0
- package/dist/rules/binding-context.js.map +1 -0
- package/dist/rules/defaults.d.ts +9 -0
- package/dist/rules/defaults.d.ts.map +1 -0
- package/dist/rules/defaults.js +334 -0
- package/dist/rules/defaults.js.map +1 -0
- package/dist/rules/dispatcher.d.ts +40 -0
- package/dist/rules/dispatcher.d.ts.map +1 -0
- package/dist/rules/dispatcher.js +695 -0
- package/dist/rules/dispatcher.js.map +1 -0
- package/dist/rules/github-service.d.ts +29 -0
- package/dist/rules/github-service.d.ts.map +1 -0
- package/dist/rules/github-service.js +474 -0
- package/dist/rules/github-service.js.map +1 -0
- package/dist/rules/index.d.ts +7 -0
- package/dist/rules/index.d.ts.map +1 -0
- package/dist/rules/index.js +583 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/rules/linear-service.d.ts +27 -0
- package/dist/rules/linear-service.d.ts.map +1 -0
- package/dist/rules/linear-service.js +343 -0
- package/dist/rules/linear-service.js.map +1 -0
- package/dist/rules/processor.d.ts +54 -0
- package/dist/rules/processor.d.ts.map +1 -0
- package/dist/rules/processor.js +629 -0
- package/dist/rules/processor.js.map +1 -0
- package/dist/rules/resolve.d.ts +17 -0
- package/dist/rules/resolve.d.ts.map +1 -0
- package/dist/rules/resolve.js +27 -0
- package/dist/rules/resolve.js.map +1 -0
- package/dist/rules/start-coordinator.d.ts +58 -0
- package/dist/rules/start-coordinator.d.ts.map +1 -0
- package/dist/rules/start-coordinator.js +136 -0
- package/dist/rules/start-coordinator.js.map +1 -0
- package/dist/rules/tools.d.ts +10 -0
- package/dist/rules/tools.d.ts.map +1 -0
- package/dist/rules/tools.js +93 -0
- package/dist/rules/tools.js.map +1 -0
- package/dist/rules/transition-service.d.ts +32 -0
- package/dist/rules/transition-service.d.ts.map +1 -0
- package/dist/rules/transition-service.js +474 -0
- package/dist/rules/transition-service.js.map +1 -0
- package/dist/rules/types.d.ts +225 -0
- package/dist/rules/types.d.ts.map +1 -0
- package/dist/rules/types.js +33 -0
- package/dist/rules/types.js.map +1 -0
- package/dist/rules/validation.d.ts +11 -0
- package/dist/rules/validation.d.ts.map +1 -0
- package/dist/rules/validation.js +310 -0
- package/dist/rules/validation.js.map +1 -0
- package/dist/sandbox/fleet.d.ts +208 -0
- package/dist/sandbox/fleet.d.ts.map +1 -0
- package/dist/sandbox/fleet.js +259 -0
- package/dist/sandbox/fleet.js.map +1 -0
- package/dist/sandbox/reattach.d.ts +3 -0
- package/dist/sandbox/reattach.d.ts.map +1 -0
- package/dist/sandbox/reattach.js +9 -0
- package/dist/sandbox/reattach.js.map +1 -0
- package/dist/server-error.d.ts +12 -0
- package/dist/server-error.d.ts.map +1 -0
- package/dist/server-error.js +20 -0
- package/dist/server-error.js.map +1 -0
- package/dist/skills/service.d.ts +48 -0
- package/dist/skills/service.d.ts.map +1 -0
- package/dist/skills/service.js +45 -0
- package/dist/skills/service.js.map +1 -0
- package/dist/spa-static.d.ts +34 -0
- package/dist/spa-static.d.ts.map +1 -0
- package/dist/spa-static.js +73 -0
- package/dist/spa-static.js.map +1 -0
- package/dist/state-signing.d.ts +48 -0
- package/dist/state-signing.d.ts.map +1 -0
- package/dist/state-signing.js +48 -0
- package/dist/state-signing.js.map +1 -0
- package/dist/storage/domains/audit/agent-audit.d.ts +27 -0
- package/dist/storage/domains/audit/agent-audit.d.ts.map +1 -0
- package/dist/storage/domains/audit/agent-audit.js +65 -0
- package/dist/storage/domains/audit/agent-audit.js.map +1 -0
- package/dist/storage/domains/audit/base.d.ts +140 -0
- package/dist/storage/domains/audit/base.d.ts.map +1 -0
- package/dist/storage/domains/audit/base.js +127 -0
- package/dist/storage/domains/audit/base.js.map +1 -0
- package/dist/storage/domains/audit/domain.d.ts +69 -0
- package/dist/storage/domains/audit/domain.d.ts.map +1 -0
- package/dist/storage/domains/audit/domain.js +165 -0
- package/dist/storage/domains/audit/domain.js.map +1 -0
- package/dist/storage/domains/credentials/base.d.ts +134 -0
- package/dist/storage/domains/credentials/base.d.ts.map +1 -0
- package/dist/storage/domains/credentials/base.js +257 -0
- package/dist/storage/domains/credentials/base.js.map +1 -0
- package/dist/storage/domains/intake/base.d.ts +38 -0
- package/dist/storage/domains/intake/base.d.ts.map +1 -0
- package/dist/storage/domains/intake/base.js +62 -0
- package/dist/storage/domains/intake/base.js.map +1 -0
- package/dist/storage/domains/integrations/base.d.ts +126 -0
- package/dist/storage/domains/integrations/base.d.ts.map +1 -0
- package/dist/storage/domains/integrations/base.js +252 -0
- package/dist/storage/domains/integrations/base.js.map +1 -0
- package/dist/storage/domains/model-packs/base.d.ts +49 -0
- package/dist/storage/domains/model-packs/base.d.ts.map +1 -0
- package/dist/storage/domains/model-packs/base.js +95 -0
- package/dist/storage/domains/model-packs/base.js.map +1 -0
- package/dist/storage/domains/projects/base.d.ts +55 -0
- package/dist/storage/domains/projects/base.d.ts.map +1 -0
- package/dist/storage/domains/projects/base.js +99 -0
- package/dist/storage/domains/projects/base.js.map +1 -0
- package/dist/storage/domains/queue-health/base.d.ts +52 -0
- package/dist/storage/domains/queue-health/base.d.ts.map +1 -0
- package/dist/storage/domains/queue-health/base.js +87 -0
- package/dist/storage/domains/queue-health/base.js.map +1 -0
- package/dist/storage/domains/source-control/base.d.ts +288 -0
- package/dist/storage/domains/source-control/base.d.ts.map +1 -0
- package/dist/storage/domains/source-control/base.js +722 -0
- package/dist/storage/domains/source-control/base.js.map +1 -0
- package/dist/storage/domains/source-control/inmemory.d.ts +158 -0
- package/dist/storage/domains/source-control/inmemory.d.ts.map +1 -0
- package/dist/storage/domains/source-control/inmemory.js +348 -0
- package/dist/storage/domains/source-control/inmemory.js.map +1 -0
- package/dist/storage/domains/work-items/base.d.ts +412 -0
- package/dist/storage/domains/work-items/base.d.ts.map +1 -0
- package/dist/storage/domains/work-items/base.js +1174 -0
- package/dist/storage/domains/work-items/base.js.map +1 -0
- package/dist/storage/domains/work-items/metrics.d.ts +101 -0
- package/dist/storage/domains/work-items/metrics.d.ts.map +1 -0
- package/dist/storage/domains/work-items/metrics.js +203 -0
- package/dist/storage/domains/work-items/metrics.js.map +1 -0
- package/dist/workspace.d.ts +20 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +364 -0
- package/dist/workspace.js.map +1 -0
- package/package.json +19 -19
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# @mastra/factory
|
|
2
2
|
|
|
3
|
+
## 0.1.0-alpha.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Forwarded closed Platform GitHub event-log deliveries into Factory governance before dispatching repository subscriptions, and kept default GitHub rules from auto-starting issues or pull requests created before the Factory. ([#19988](https://github.com/mastra-ai/mastra/pull/19988))
|
|
8
|
+
|
|
9
|
+
- Deployed factories now authenticate API and Studio requests with the same provider, so Studio sessions work without extra configuration. ([#19966](https://github.com/mastra-ai/mastra/pull/19966))
|
|
10
|
+
|
|
11
|
+
- Fixed cloned session threads reading from a previous storage instance. The dynamic memory cache now invalidates when the storage or vector instance changes, so thread cloning always uses the current database. ([#19966](https://github.com/mastra-ai/mastra/pull/19966))
|
|
12
|
+
|
|
13
|
+
- Updated dependencies [[`cc656b9`](https://github.com/mastra-ai/mastra/commit/cc656b92cc8fe40af3e2ea8bb796a6b406e96791), [`cc656b9`](https://github.com/mastra-ai/mastra/commit/cc656b92cc8fe40af3e2ea8bb796a6b406e96791), [`337d41d`](https://github.com/mastra-ai/mastra/commit/337d41d8aae0399d2bf42d42ebddac0c21953891)]:
|
|
14
|
+
- @mastra/code-sdk@1.0.0-alpha.15
|
|
15
|
+
|
|
16
|
+
## 0.1.0-alpha.2
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- Fixed Factory metrics windowing to use inclusive UTC calendar days. Date-only `from`/`to` bounds now include both selected days, an item completing at the current instant is counted in today's throughput (previously it could be dropped on the window's exclusive edge), and `windowDays` reflects the number of gap-filled day buckets. Cards feed the source mix only when created inside the window. ([#19971](https://github.com/mastra-ai/mastra/pull/19971))
|
|
21
|
+
|
|
22
|
+
- Fixed duplicate repositories in Factory source control settings. ([#19971](https://github.com/mastra-ai/mastra/pull/19971))
|
|
23
|
+
|
|
24
|
+
- Fixed Factory automation so polled GitHub events reach governance rules, authenticated sessions start with the correct ownership, and board moves reliably notify active or idle agents. ([#19979](https://github.com/mastra-ai/mastra/pull/19979))
|
|
25
|
+
|
|
3
26
|
## 0.1.0-alpha.1
|
|
4
27
|
|
|
5
28
|
### Minor Changes
|
package/LICENSE.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
Portions of this software are licensed as follows:
|
|
2
|
+
|
|
3
|
+
- All content that resides under any directory named "ee/" within this
|
|
4
|
+
repository, including but not limited to:
|
|
5
|
+
- `packages/core/src/auth/ee/`
|
|
6
|
+
- `packages/server/src/server/auth/ee/`
|
|
7
|
+
is licensed under the license defined in `ee/LICENSE`.
|
|
8
|
+
|
|
9
|
+
- All third-party components incorporated into the Mastra Software are
|
|
10
|
+
licensed under the original license provided by the owner of the
|
|
11
|
+
applicable component.
|
|
12
|
+
|
|
13
|
+
- Content outside of the above-mentioned directories or restrictions is
|
|
14
|
+
available under the "Apache License 2.0" as defined below.
|
|
15
|
+
|
|
16
|
+
# Apache License 2.0
|
|
17
|
+
|
|
18
|
+
Copyright (c) 2025 Kepler Software, Inc.
|
|
19
|
+
|
|
20
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
21
|
+
you may not use this file except in compliance with the License.
|
|
22
|
+
You may obtain a copy of the License at
|
|
23
|
+
|
|
24
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
25
|
+
|
|
26
|
+
Unless required by applicable law or agreed to in writing, software
|
|
27
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
28
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
29
|
+
See the License for the specific language governing permissions and
|
|
30
|
+
limitations under the License.
|
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { MastraAuthWorkos } from '@mastra/auth-workos';
|
|
2
|
+
import type { ApiRoute, IMastraAuthProvider } from '@mastra/core/server';
|
|
3
|
+
import type { Context, Hono } from 'hono';
|
|
4
|
+
import type { RouteAuth } from './routes/route.js';
|
|
5
|
+
/**
|
|
6
|
+
* Provider-neutral factory auth gating for the MastraCode web server.
|
|
7
|
+
*
|
|
8
|
+
* When an auth provider is active (a `MastraAuthProvider` instance passed to
|
|
9
|
+
* `MastraFactory`'s `auth` slot, or — back-compat for suites/paths that never
|
|
10
|
+
* boot the factory — implied by the WorkOS env vars), every route on the web
|
|
11
|
+
* server is placed behind it: unauthenticated browser navigations are
|
|
12
|
+
* redirected to the SPA's `/signin` page, API/XHR calls receive a 401, and a
|
|
13
|
+
* small set of public routes stay reachable while signed out — the provider's
|
|
14
|
+
* `/auth/*` routes plus `/auth/me`, the `/signin` page and its `/assets/*`
|
|
15
|
+
* bundle. When no provider is active, `mountFactoryAuth` is a no-op and the server
|
|
16
|
+
* behaves exactly as it does without auth.
|
|
17
|
+
*
|
|
18
|
+
* Provider specifics stay in the providers (`@mastra/auth-workos`,
|
|
19
|
+
* `@mastra/auth-better-auth`, or any custom `IMastraAuthProvider`); this
|
|
20
|
+
* module composes them capability-first via the core type guards:
|
|
21
|
+
* - `authenticateToken` — session/bearer validation (all providers)
|
|
22
|
+
* - `ISSOProvider` — hosted-login `/auth/login`, `/auth/callback`, `/auth/logout`
|
|
23
|
+
* - `IAuthHttpHandler` — provider-owned `/auth/api/*` endpoints (better-auth)
|
|
24
|
+
* - `IOrganizationsProvider` — personal-org bootstrap + admin checks
|
|
25
|
+
* - `ICredentialsProvider.isSignUpEnabled` — SPA sign-up affordance
|
|
26
|
+
* - `getClearSessionHeaders` — session cookie clearing on logout
|
|
27
|
+
*/
|
|
28
|
+
/** Minimal shape of the signed-in user surfaced to the SPA (no tokens). */
|
|
29
|
+
export interface FactoryAuthUser {
|
|
30
|
+
/** Stable WorkOS user id used to scope per-user data (GitHub installs etc.). */
|
|
31
|
+
workosId?: string;
|
|
32
|
+
/** Provider user id; WorkOS shapes may use `workosId` instead (see {@link workosId}). */
|
|
33
|
+
id?: string;
|
|
34
|
+
email?: string;
|
|
35
|
+
name?: string;
|
|
36
|
+
/**
|
|
37
|
+
* Organization id. The org is the top-level tenant: it owns the GitHub
|
|
38
|
+
* App installation and connected projects, while each user inside the org gets
|
|
39
|
+
* isolated building instances. Absent for personal (no-org) accounts.
|
|
40
|
+
*/
|
|
41
|
+
organizationId?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Tenant identity: the org is the top-level tenant, and each user inside it is
|
|
45
|
+
* an isolated builder. Agent state, worktrees and sandboxes are scoped per
|
|
46
|
+
* `(orgId, userId)`. Personal (no-org) users have `orgId === undefined`.
|
|
47
|
+
*/
|
|
48
|
+
export interface FactoryAuthTenant {
|
|
49
|
+
/** Organization id, or `undefined` for personal (no-org) accounts. */
|
|
50
|
+
orgId?: string;
|
|
51
|
+
/** Stable provider user id. */
|
|
52
|
+
userId: string;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Validate that a `returnTo` value is a safe same-site path, to prevent
|
|
56
|
+
* open-redirect attacks. Only absolute local paths (`/foo`) are allowed;
|
|
57
|
+
* protocol-relative (`//evil.com`) and absolute URLs are rejected.
|
|
58
|
+
*/
|
|
59
|
+
export declare function sanitizeReturnTo(raw: string | undefined): string;
|
|
60
|
+
/** Extract a bearer token from the Authorization header, if present. */
|
|
61
|
+
export declare function getBearerToken(authorization: string | undefined): string;
|
|
62
|
+
/**
|
|
63
|
+
* Whether the SPA is served cross-origin from this API (platform deploy). When
|
|
64
|
+
* `MASTRACODE_ALLOWED_ORIGINS` is set the browser talks to us cross-site, so
|
|
65
|
+
* session cookies must be `SameSite=None; Secure` for the browser to send them.
|
|
66
|
+
* Same-origin local dev leaves this unset and keeps the stricter `SameSite=Lax`.
|
|
67
|
+
*/
|
|
68
|
+
export declare function isCrossSiteAuth(): boolean;
|
|
69
|
+
/** Hono context variables set by the auth gate. */
|
|
70
|
+
export interface FactoryAuthVariables {
|
|
71
|
+
factoryAuthUser: FactoryAuthUser;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Read the authenticated user the gate stashed on the context, or
|
|
75
|
+
* `undefined` when unauthenticated / auth disabled. Used by downstream routes
|
|
76
|
+
* (e.g. GitHub) to scope rows per user.
|
|
77
|
+
*/
|
|
78
|
+
export declare function getFactoryAuthUser(c: Context): FactoryAuthUser | undefined;
|
|
79
|
+
/** Resolve the stable user id from an authenticated user shape. */
|
|
80
|
+
export declare function getFactoryAuthUserId(user: FactoryAuthUser | undefined): string | undefined;
|
|
81
|
+
/** Resolve the organization id from a user shape, if present. */
|
|
82
|
+
export declare function getFactoryAuthOrgId(user: FactoryAuthUser | undefined): string | undefined;
|
|
83
|
+
/**
|
|
84
|
+
* Resolve the tenant identity `(orgId, userId)` from the authenticated user on
|
|
85
|
+
* the context. Returns `undefined` when there is no signed-in user (auth
|
|
86
|
+
* disabled or unauthenticated). `orgId` is `undefined` for personal accounts;
|
|
87
|
+
* callers gate org-scoped GitHub features on its presence while agent state
|
|
88
|
+
* falls back to a user-only tenant.
|
|
89
|
+
*/
|
|
90
|
+
export declare function factoryAuthTenant(c: Context): FactoryAuthTenant | undefined;
|
|
91
|
+
/**
|
|
92
|
+
* Fail-closed authorization for organization-level administrative mutations.
|
|
93
|
+
* The caller must belong to the same active organization and the provider must
|
|
94
|
+
* explicitly confirm an admin/owner role.
|
|
95
|
+
*/
|
|
96
|
+
export declare function isOrganizationAdmin(provider: IMastraAuthProvider | undefined, c: Context, organizationId: string): Promise<boolean>;
|
|
97
|
+
/**
|
|
98
|
+
* Build the factory's implementation of the `RouteAuth` seam over the
|
|
99
|
+
* resolved provider (`undefined` = auth disabled). Constructed once per boot
|
|
100
|
+
* by `MastraFactory.prepare()` and handed to factory route modules at
|
|
101
|
+
* construction — they never import the factory auth module directly.
|
|
102
|
+
*/
|
|
103
|
+
export declare function createFactoryRouteAuth(provider: IMastraAuthProvider | undefined): RouteAuth;
|
|
104
|
+
/** True when the given provider is WorkOS. Gates WorkOS-only capabilities. */
|
|
105
|
+
export declare function isWorkOSAuth(provider: IMastraAuthProvider | undefined): boolean;
|
|
106
|
+
/**
|
|
107
|
+
* The raw WorkOS provider, for features that need the WorkOS client directly
|
|
108
|
+
* (audit-log export, Admin Portal links). Callers must gate on
|
|
109
|
+
* {@link isWorkOSAuth} first — throws when the provider is not WorkOS.
|
|
110
|
+
*/
|
|
111
|
+
export declare function getWorkOSProvider(provider: IMastraAuthProvider | undefined): MastraAuthWorkos;
|
|
112
|
+
/**
|
|
113
|
+
* Resolve the authenticated user for a request, stashing it on the context.
|
|
114
|
+
*
|
|
115
|
+
* The gate only authenticates non-`/auth/*` requests via the `Authorization`
|
|
116
|
+
* header, so cookie-based browser navigations to public `/auth/*` routes (the
|
|
117
|
+
* GitHub connect/callback flow) arrive without a gate-stashed user. This reads
|
|
118
|
+
* the session cookie from the raw request the same way `/auth/me` does,
|
|
119
|
+
* caches the result on the context, and returns it so downstream helpers like
|
|
120
|
+
* {@link factoryAuthTenant} work uniformly on both gated and public routes.
|
|
121
|
+
*
|
|
122
|
+
* Returns `undefined` when there is no valid session (or auth is disabled).
|
|
123
|
+
*/
|
|
124
|
+
export declare function ensureFactoryAuthUser(provider: IMastraAuthProvider | undefined, c: Context): Promise<FactoryAuthUser | undefined>;
|
|
125
|
+
export interface MountFactoryAuthOptions {
|
|
126
|
+
/**
|
|
127
|
+
* Explicit auth provider to mount. When omitted, falls back to a WorkOS
|
|
128
|
+
* provider implied by the `WORKOS_*` env vars (back-compat for suites that
|
|
129
|
+
* never boot the factory).
|
|
130
|
+
*/
|
|
131
|
+
provider?: IMastraAuthProvider;
|
|
132
|
+
/**
|
|
133
|
+
* Absolute URL the identity provider redirects back to after login (WorkOS
|
|
134
|
+
* env-fallback path only). Defaults to the `WORKOS_REDIRECT_URI` env var.
|
|
135
|
+
*/
|
|
136
|
+
redirectUri?: string;
|
|
137
|
+
/** Browser-facing origin used to derive the SSO callback URL. */
|
|
138
|
+
publicUrl?: string;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Register the public `/auth/*` routes on a Hono app: the capability-derived
|
|
142
|
+
* provider routes (login/callback/logout/provider APIs) plus the
|
|
143
|
+
* provider-neutral `/auth/me`. Split out from `mountFactoryAuth` so both the local
|
|
144
|
+
* Hono server and the platform Mastra entry can reuse the exact same handlers.
|
|
145
|
+
*/
|
|
146
|
+
export declare function registerAuthRoutes(app: Hono<any>, provider: IMastraAuthProvider, options?: {
|
|
147
|
+
publicUrl?: string;
|
|
148
|
+
}): void;
|
|
149
|
+
/**
|
|
150
|
+
* Build the public `/auth/*` routes (provider routes + `/auth/me`) as Mastra
|
|
151
|
+
* `server.apiRoutes`. Used by the platform Mastra entry (`src/mastra/index.ts`),
|
|
152
|
+
* which can't register plain Hono routes on the deployer-generated app the way
|
|
153
|
+
* the local server does via {@link registerAuthRoutes}.
|
|
154
|
+
*
|
|
155
|
+
* Handlers are identical to {@link registerAuthRoutes}. All are `requiresAuth: false`
|
|
156
|
+
* (they must be reachable while unauthenticated), and the gate middleware skips
|
|
157
|
+
* `/auth/*` so it never blocks them. `/auth/*` is not under `/api`, so it is a
|
|
158
|
+
* valid custom-route path.
|
|
159
|
+
*/
|
|
160
|
+
export declare function buildAuthRoutes(provider: IMastraAuthProvider, options?: {
|
|
161
|
+
publicUrl?: string;
|
|
162
|
+
}): ApiRoute[];
|
|
163
|
+
/**
|
|
164
|
+
* Build the auth gate as a plain Hono middleware handler `(c, next)`. Protects
|
|
165
|
+
* everything that is not a public `/auth/*` route: authenticated requests stash
|
|
166
|
+
* the user on the context and continue; unauthenticated navigations redirect to
|
|
167
|
+
* login and XHR/API calls get a 401 JSON. Shared by the local Hono server
|
|
168
|
+
* (`mountFactoryAuth`) and the platform Mastra entry (`server.middleware`).
|
|
169
|
+
*/
|
|
170
|
+
export declare function createFactoryAuthGate(provider: IMastraAuthProvider): (c: Context, next: () => Promise<void>) => Promise<Response | void>;
|
|
171
|
+
/**
|
|
172
|
+
* Mount factory auth gating onto the host app. No-op when auth is disabled
|
|
173
|
+
* (no provider active).
|
|
174
|
+
*
|
|
175
|
+
* Must be called before the Mastra adapter routes, the `/web/*` routes, and
|
|
176
|
+
* the static UI handlers so the gate covers every request. Composes the shared
|
|
177
|
+
* `registerAuthRoutes` + `createFactoryAuthGate` factories so the local Hono server
|
|
178
|
+
* and the platform Mastra entry stay behavior-identical.
|
|
179
|
+
*/
|
|
180
|
+
export declare function mountFactoryAuth(app: Hono<any>, options?: MountFactoryAuthOptions): boolean;
|
|
181
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
// src/auth.ts
|
|
2
|
+
import { MastraAuthWorkos } from "@mastra/auth-workos";
|
|
3
|
+
import {
|
|
4
|
+
registerApiRoute,
|
|
5
|
+
isAuthHttpHandler,
|
|
6
|
+
isCredentialsProvider,
|
|
7
|
+
isOrganizationsProvider,
|
|
8
|
+
isSessionProvider,
|
|
9
|
+
isSSOProvider
|
|
10
|
+
} from "@mastra/core/server";
|
|
11
|
+
function sanitizeReturnTo(raw) {
|
|
12
|
+
if (!raw) return "/";
|
|
13
|
+
if (!raw.startsWith("/")) return "/";
|
|
14
|
+
if (raw.startsWith("//") || raw.startsWith("/\\")) return "/";
|
|
15
|
+
return raw;
|
|
16
|
+
}
|
|
17
|
+
function getBearerToken(authorization) {
|
|
18
|
+
if (!authorization) return "";
|
|
19
|
+
const match = /^Bearer\s+(.+)$/i.exec(authorization);
|
|
20
|
+
return match?.[1] ?? "";
|
|
21
|
+
}
|
|
22
|
+
function isCrossSiteAuth() {
|
|
23
|
+
return Boolean(process.env.MASTRACODE_ALLOWED_ORIGINS?.trim());
|
|
24
|
+
}
|
|
25
|
+
var FACTORY_AUTH_USER_KEY = "factoryAuthUser";
|
|
26
|
+
function getFactoryAuthUser(c) {
|
|
27
|
+
return c.get(FACTORY_AUTH_USER_KEY);
|
|
28
|
+
}
|
|
29
|
+
function getFactoryAuthUserId(user) {
|
|
30
|
+
return user?.workosId ?? user?.id;
|
|
31
|
+
}
|
|
32
|
+
function getFactoryAuthOrgId(user) {
|
|
33
|
+
return user?.organizationId;
|
|
34
|
+
}
|
|
35
|
+
function factoryAuthTenant(c) {
|
|
36
|
+
const user = getFactoryAuthUser(c);
|
|
37
|
+
const userId = getFactoryAuthUserId(user);
|
|
38
|
+
if (!userId) return void 0;
|
|
39
|
+
return { orgId: getFactoryAuthOrgId(user), userId };
|
|
40
|
+
}
|
|
41
|
+
function envWorkosConfigured() {
|
|
42
|
+
return Boolean(process.env.WORKOS_API_KEY && process.env.WORKOS_CLIENT_ID);
|
|
43
|
+
}
|
|
44
|
+
function envFallbackAuthProvider(redirectUri) {
|
|
45
|
+
if (!envWorkosConfigured()) return void 0;
|
|
46
|
+
return new MastraAuthWorkos({
|
|
47
|
+
redirectUri: redirectUri ?? process.env.WORKOS_REDIRECT_URI,
|
|
48
|
+
fetchMemberships: true
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
function toFactoryAuthUser(result) {
|
|
52
|
+
if (!result || typeof result !== "object") return null;
|
|
53
|
+
const record = result;
|
|
54
|
+
if (record.user && typeof record.user === "object" && record.session && typeof record.session === "object") {
|
|
55
|
+
const user = record.user;
|
|
56
|
+
const session = record.session;
|
|
57
|
+
if (typeof user.id !== "string") return null;
|
|
58
|
+
return {
|
|
59
|
+
id: user.id,
|
|
60
|
+
email: typeof user.email === "string" ? user.email : void 0,
|
|
61
|
+
name: typeof user.name === "string" ? user.name : void 0,
|
|
62
|
+
organizationId: typeof session.activeOrganizationId === "string" ? session.activeOrganizationId : void 0
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
const flat = record;
|
|
66
|
+
const id = typeof flat.id === "string" ? flat.id : void 0;
|
|
67
|
+
const workosId = typeof flat.workosId === "string" ? flat.workosId : void 0;
|
|
68
|
+
if (!id && !workosId) return null;
|
|
69
|
+
return {
|
|
70
|
+
id,
|
|
71
|
+
workosId,
|
|
72
|
+
email: typeof flat.email === "string" ? flat.email : void 0,
|
|
73
|
+
name: typeof flat.name === "string" ? flat.name : void 0,
|
|
74
|
+
organizationId: typeof flat.organizationId === "string" ? flat.organizationId : void 0
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
async function authenticateRequest(provider, token, raw) {
|
|
78
|
+
try {
|
|
79
|
+
const result = await provider.authenticateToken(token, raw);
|
|
80
|
+
return toFactoryAuthUser(result);
|
|
81
|
+
} catch {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async function ensureUserOrg(provider, user) {
|
|
86
|
+
if (getFactoryAuthOrgId(user)) return;
|
|
87
|
+
if (!isOrganizationsProvider(provider)) return;
|
|
88
|
+
const userId = getFactoryAuthUserId(user);
|
|
89
|
+
if (!userId) return;
|
|
90
|
+
try {
|
|
91
|
+
const orgId = await provider.ensureOrganization(userId);
|
|
92
|
+
if (orgId) user.organizationId = orgId;
|
|
93
|
+
} catch {
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function providerClearCookies(provider) {
|
|
97
|
+
const getClearSessionHeaders = provider.getClearSessionHeaders;
|
|
98
|
+
if (typeof getClearSessionHeaders !== "function") return [];
|
|
99
|
+
const headers = getClearSessionHeaders.call(provider) ?? {};
|
|
100
|
+
const setCookie = headers["Set-Cookie"];
|
|
101
|
+
if (!setCookie) return [];
|
|
102
|
+
return setCookie.split(/,(?=\s*[^;=,\s]+=)/).map((cookie) => cookie.trim());
|
|
103
|
+
}
|
|
104
|
+
async function isOrganizationAdmin(provider, c, organizationId) {
|
|
105
|
+
const user = await ensureFactoryAuthUser(provider, c);
|
|
106
|
+
if (!user || user.organizationId !== organizationId || !provider || !isOrganizationsProvider(provider)) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
const userId = getFactoryAuthUserId(user);
|
|
110
|
+
if (!userId) return false;
|
|
111
|
+
try {
|
|
112
|
+
return await provider.isOrganizationAdmin(organizationId, userId);
|
|
113
|
+
} catch {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function createFactoryRouteAuth(provider) {
|
|
118
|
+
return {
|
|
119
|
+
enabled: () => provider !== void 0,
|
|
120
|
+
ensureUser: (c) => ensureFactoryAuthUser(provider, c),
|
|
121
|
+
tenant: (c) => factoryAuthTenant(c),
|
|
122
|
+
isOrganizationAdmin: (c, organizationId) => isOrganizationAdmin(provider, c, organizationId)
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
function isWorkOSAuth(provider) {
|
|
126
|
+
return provider instanceof MastraAuthWorkos;
|
|
127
|
+
}
|
|
128
|
+
function getWorkOSProvider(provider) {
|
|
129
|
+
if (provider instanceof MastraAuthWorkos) return provider;
|
|
130
|
+
throw new Error("WorkOS provider requested but the active factory auth provider is not WorkOS");
|
|
131
|
+
}
|
|
132
|
+
async function ensureFactoryAuthUser(provider, c) {
|
|
133
|
+
const existing = getFactoryAuthUser(c);
|
|
134
|
+
if (existing) return existing;
|
|
135
|
+
if (!provider) return void 0;
|
|
136
|
+
const token = getBearerToken(c.req.header("Authorization"));
|
|
137
|
+
const user = await authenticateRequest(provider, token, c.req.raw);
|
|
138
|
+
if (!user) return void 0;
|
|
139
|
+
await ensureUserOrg(provider, user);
|
|
140
|
+
c.set(FACTORY_AUTH_USER_KEY, user);
|
|
141
|
+
return user;
|
|
142
|
+
}
|
|
143
|
+
function isNavigationRequest(path, accept) {
|
|
144
|
+
if (path.startsWith("/api/")) return false;
|
|
145
|
+
return (accept ?? "").includes("text/html");
|
|
146
|
+
}
|
|
147
|
+
async function handleAuthMe(provider, c) {
|
|
148
|
+
const token = getBearerToken(c.req.header("Authorization"));
|
|
149
|
+
const user = await authenticateRequest(provider, token, c.req.raw);
|
|
150
|
+
const signUpDisabled = isCredentialsProvider(provider) && provider.isSignUpEnabled?.() === false;
|
|
151
|
+
const meta = { provider: provider.name, ...signUpDisabled ? { signUpDisabled: true } : {} };
|
|
152
|
+
if (!user) {
|
|
153
|
+
return c.json({ authenticated: false, user: null, ...meta });
|
|
154
|
+
}
|
|
155
|
+
await ensureUserOrg(provider, user);
|
|
156
|
+
return c.json({
|
|
157
|
+
authenticated: true,
|
|
158
|
+
user: {
|
|
159
|
+
userId: getFactoryAuthUserId(user),
|
|
160
|
+
email: user.email,
|
|
161
|
+
name: user.name,
|
|
162
|
+
organizationId: user.organizationId
|
|
163
|
+
},
|
|
164
|
+
...meta
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
function encodeState(returnTo) {
|
|
168
|
+
return Buffer.from(JSON.stringify({ returnTo }), "utf8").toString("base64url");
|
|
169
|
+
}
|
|
170
|
+
function decodeState(state) {
|
|
171
|
+
if (!state) return "/";
|
|
172
|
+
try {
|
|
173
|
+
const parsed = JSON.parse(Buffer.from(state, "base64url").toString("utf8"));
|
|
174
|
+
return sanitizeReturnTo(parsed.returnTo);
|
|
175
|
+
} catch {
|
|
176
|
+
return "/";
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
function providerAuthRoutes(provider, publicUrl) {
|
|
180
|
+
const routes = [];
|
|
181
|
+
if (isAuthHttpHandler(provider)) {
|
|
182
|
+
routes.push({
|
|
183
|
+
path: "/auth/api/*",
|
|
184
|
+
method: "ALL",
|
|
185
|
+
handler: (c) => provider.handleAuthRequest(c.req.raw)
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
if (isSSOProvider(provider)) {
|
|
189
|
+
routes.push(
|
|
190
|
+
{
|
|
191
|
+
path: "/auth/login",
|
|
192
|
+
method: "GET",
|
|
193
|
+
handler: async (c) => {
|
|
194
|
+
const returnTo = sanitizeReturnTo(c.req.query("returnTo"));
|
|
195
|
+
const state = encodeState(returnTo);
|
|
196
|
+
const redirectUri = publicUrl ? new URL("/auth/callback", publicUrl).toString() : "";
|
|
197
|
+
const loginUrl = await provider.getLoginUrl(redirectUri, state);
|
|
198
|
+
for (const cookie of await provider.getLoginCookies?.(redirectUri, state) ?? []) {
|
|
199
|
+
c.header("Set-Cookie", cookie, { append: true });
|
|
200
|
+
}
|
|
201
|
+
return c.redirect(loginUrl);
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
path: "/auth/callback",
|
|
206
|
+
method: "GET",
|
|
207
|
+
handler: async (c) => {
|
|
208
|
+
const code = c.req.query("code");
|
|
209
|
+
const returnTo = decodeState(c.req.query("state"));
|
|
210
|
+
if (!code) {
|
|
211
|
+
return c.redirect("/auth/login");
|
|
212
|
+
}
|
|
213
|
+
try {
|
|
214
|
+
const result = await provider.handleCallback(code, c.req.query("state") ?? "");
|
|
215
|
+
if (result.cookies?.length) {
|
|
216
|
+
for (const cookie of result.cookies) {
|
|
217
|
+
c.header("Set-Cookie", cookie, { append: true });
|
|
218
|
+
}
|
|
219
|
+
} else if (isSessionProvider(provider) && result.tokens) {
|
|
220
|
+
const resultUser = result.user;
|
|
221
|
+
const session = await provider.createSession(resultUser.id, {
|
|
222
|
+
accessToken: result.tokens.accessToken,
|
|
223
|
+
refreshToken: result.tokens.refreshToken,
|
|
224
|
+
expiresAt: result.tokens.expiresAt,
|
|
225
|
+
organizationId: resultUser.organizationId
|
|
226
|
+
});
|
|
227
|
+
for (const [key, value] of Object.entries(provider.getSessionHeaders(session))) {
|
|
228
|
+
c.header(key, value, { append: true });
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return c.redirect(returnTo);
|
|
232
|
+
} catch {
|
|
233
|
+
return c.redirect("/auth/login");
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
path: "/auth/logout",
|
|
239
|
+
method: "GET",
|
|
240
|
+
handler: async (c) => {
|
|
241
|
+
let logoutUrl = null;
|
|
242
|
+
try {
|
|
243
|
+
logoutUrl = await provider.getLogoutUrl?.("/", c.req.raw) ?? null;
|
|
244
|
+
} catch {
|
|
245
|
+
logoutUrl = null;
|
|
246
|
+
}
|
|
247
|
+
for (const cookie of providerClearCookies(provider)) {
|
|
248
|
+
c.header("Set-Cookie", cookie, { append: true });
|
|
249
|
+
}
|
|
250
|
+
return c.redirect(logoutUrl ?? "/");
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
);
|
|
254
|
+
} else if (isAuthHttpHandler(provider)) {
|
|
255
|
+
routes.push(
|
|
256
|
+
{
|
|
257
|
+
// Hosted-login equivalent: no hosted page, so send the browser to the
|
|
258
|
+
// SPA's /signin form, preserving returnTo.
|
|
259
|
+
path: "/auth/login",
|
|
260
|
+
method: "GET",
|
|
261
|
+
handler: (c) => {
|
|
262
|
+
const returnTo = sanitizeReturnTo(c.req.query("returnTo"));
|
|
263
|
+
return c.redirect(`/signin?returnTo=${encodeURIComponent(returnTo)}`);
|
|
264
|
+
}
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
path: "/auth/logout",
|
|
268
|
+
method: "GET",
|
|
269
|
+
handler: async (c) => {
|
|
270
|
+
try {
|
|
271
|
+
const origin = new URL(c.req.url).origin;
|
|
272
|
+
const response = await provider.handleAuthRequest(
|
|
273
|
+
new Request(`${origin}/auth/api/sign-out`, { method: "POST", headers: c.req.raw.headers })
|
|
274
|
+
);
|
|
275
|
+
for (const cookie of response.headers.getSetCookie()) {
|
|
276
|
+
c.header("Set-Cookie", cookie, { append: true });
|
|
277
|
+
}
|
|
278
|
+
} catch {
|
|
279
|
+
}
|
|
280
|
+
for (const cookie of providerClearCookies(provider)) {
|
|
281
|
+
c.header("Set-Cookie", cookie, { append: true });
|
|
282
|
+
}
|
|
283
|
+
return c.redirect("/");
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
return routes;
|
|
289
|
+
}
|
|
290
|
+
function registerAuthRoutes(app, provider, options = {}) {
|
|
291
|
+
for (const route of providerAuthRoutes(provider, options.publicUrl)) {
|
|
292
|
+
const methods = route.method === "ALL" ? ["GET", "POST", "PUT", "DELETE", "PATCH"] : [route.method];
|
|
293
|
+
app.on(methods, route.path, (c) => route.handler(c));
|
|
294
|
+
}
|
|
295
|
+
app.get("/auth/me", (c) => handleAuthMe(provider, c));
|
|
296
|
+
}
|
|
297
|
+
function buildAuthRoutes(provider, options = {}) {
|
|
298
|
+
return [
|
|
299
|
+
// `registerApiRoute` handlers see @mastra/core's bundled hono Context type,
|
|
300
|
+
// which is structurally identical to (but nominally distinct from) the
|
|
301
|
+
// local hono version the route handlers are typed against — cast across
|
|
302
|
+
// the seam.
|
|
303
|
+
...providerAuthRoutes(provider, options.publicUrl).map(
|
|
304
|
+
(route) => registerApiRoute(route.path, {
|
|
305
|
+
method: route.method,
|
|
306
|
+
requiresAuth: false,
|
|
307
|
+
handler: (c) => route.handler(c)
|
|
308
|
+
})
|
|
309
|
+
),
|
|
310
|
+
registerApiRoute("/auth/me", {
|
|
311
|
+
method: "GET",
|
|
312
|
+
requiresAuth: false,
|
|
313
|
+
handler: (c) => handleAuthMe(provider, c)
|
|
314
|
+
})
|
|
315
|
+
];
|
|
316
|
+
}
|
|
317
|
+
function createFactoryAuthGate(provider) {
|
|
318
|
+
return async (c, next) => {
|
|
319
|
+
const path = c.req.path;
|
|
320
|
+
if (path.startsWith("/auth/")) {
|
|
321
|
+
return next();
|
|
322
|
+
}
|
|
323
|
+
if (c.req.method === "POST" && path === "/web/github/webhook") {
|
|
324
|
+
return next();
|
|
325
|
+
}
|
|
326
|
+
if (path === "/signin" || path.startsWith("/assets/")) {
|
|
327
|
+
return next();
|
|
328
|
+
}
|
|
329
|
+
const token = getBearerToken(c.req.header("Authorization"));
|
|
330
|
+
const user = await authenticateRequest(provider, token, c.req.raw);
|
|
331
|
+
if (user) {
|
|
332
|
+
await ensureUserOrg(provider, user);
|
|
333
|
+
c.set(FACTORY_AUTH_USER_KEY, user);
|
|
334
|
+
c.get("requestContext")?.set("user", user);
|
|
335
|
+
return next();
|
|
336
|
+
}
|
|
337
|
+
if (isNavigationRequest(path, c.req.header("Accept"))) {
|
|
338
|
+
const url = new URL(c.req.url);
|
|
339
|
+
const returnTo = sanitizeReturnTo(url.pathname + url.search);
|
|
340
|
+
return c.redirect(`/signin?returnTo=${encodeURIComponent(returnTo)}`);
|
|
341
|
+
}
|
|
342
|
+
return c.json({ error: "unauthorized" }, 401);
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
function mountFactoryAuth(app, options = {}) {
|
|
346
|
+
const provider = options.provider ?? envFallbackAuthProvider(options.redirectUri);
|
|
347
|
+
if (!provider) return false;
|
|
348
|
+
registerAuthRoutes(app, provider, { publicUrl: options.publicUrl });
|
|
349
|
+
app.use("*", createFactoryAuthGate(provider));
|
|
350
|
+
return true;
|
|
351
|
+
}
|
|
352
|
+
export {
|
|
353
|
+
buildAuthRoutes,
|
|
354
|
+
createFactoryAuthGate,
|
|
355
|
+
createFactoryRouteAuth,
|
|
356
|
+
ensureFactoryAuthUser,
|
|
357
|
+
factoryAuthTenant,
|
|
358
|
+
getBearerToken,
|
|
359
|
+
getFactoryAuthOrgId,
|
|
360
|
+
getFactoryAuthUser,
|
|
361
|
+
getFactoryAuthUserId,
|
|
362
|
+
getWorkOSProvider,
|
|
363
|
+
isCrossSiteAuth,
|
|
364
|
+
isOrganizationAdmin,
|
|
365
|
+
isWorkOSAuth,
|
|
366
|
+
mountFactoryAuth,
|
|
367
|
+
registerAuthRoutes,
|
|
368
|
+
sanitizeReturnTo
|
|
369
|
+
};
|
|
370
|
+
//# sourceMappingURL=auth.js.map
|