@de-otio/trellis 0.6.0 → 0.7.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/dist/env.d.ts +21 -0
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +12 -0
- package/dist/env.js.map +1 -1
- package/dist/lambda/nightly-cron.d.ts.map +1 -1
- package/dist/lambda/nightly-cron.js +5 -2
- package/dist/lambda/nightly-cron.js.map +1 -1
- package/dist/lambda/post-confirmation.d.ts +30 -0
- package/dist/lambda/post-confirmation.d.ts.map +1 -1
- package/dist/lambda/post-confirmation.js +333 -29
- package/dist/lambda/post-confirmation.js.map +1 -1
- package/dist/lambda/pre-token-generation.d.ts +20 -0
- package/dist/lambda/pre-token-generation.d.ts.map +1 -1
- package/dist/lambda/pre-token-generation.js +233 -48
- package/dist/lambda/pre-token-generation.js.map +1 -1
- package/dist/lib/activitypub/activity-processor.d.ts.map +1 -1
- package/dist/lib/activitypub/activity-processor.js +2 -1
- package/dist/lib/activitypub/activity-processor.js.map +1 -1
- package/dist/lib/activitypub/group-service.d.ts +2 -2
- package/dist/lib/activitypub/group-service.d.ts.map +1 -1
- package/dist/lib/activitypub/group-service.js +5 -2
- package/dist/lib/activitypub/group-service.js.map +1 -1
- package/dist/lib/age-tier-transition.d.ts.map +1 -1
- package/dist/lib/age-tier-transition.js +19 -10
- package/dist/lib/age-tier-transition.js.map +1 -1
- package/dist/lib/audit/csv-export.d.ts +25 -0
- package/dist/lib/audit/csv-export.d.ts.map +1 -0
- package/dist/lib/audit/csv-export.js +54 -0
- package/dist/lib/audit/csv-export.js.map +1 -0
- package/dist/lib/audit/emit.d.ts +56 -0
- package/dist/lib/audit/emit.d.ts.map +1 -0
- package/dist/lib/audit/emit.js +124 -0
- package/dist/lib/audit/emit.js.map +1 -0
- package/dist/lib/audit/event-types.d.ts +36 -0
- package/dist/lib/audit/event-types.d.ts.map +1 -0
- package/dist/lib/audit/event-types.js +69 -0
- package/dist/lib/audit/event-types.js.map +1 -0
- package/dist/lib/audit/pii-filter.d.ts +22 -0
- package/dist/lib/audit/pii-filter.d.ts.map +1 -0
- package/dist/lib/audit/pii-filter.js +51 -0
- package/dist/lib/audit/pii-filter.js.map +1 -0
- package/dist/lib/audit-logger.js +1 -1
- package/dist/lib/audit-logger.js.map +1 -1
- package/dist/lib/auth/auth-context.d.ts +34 -0
- package/dist/lib/auth/auth-context.d.ts.map +1 -0
- package/dist/lib/auth/auth-context.js +10 -0
- package/dist/lib/auth/auth-context.js.map +1 -0
- package/dist/lib/auth/auth-middleware.d.ts +50 -0
- package/dist/lib/auth/auth-middleware.d.ts.map +1 -0
- package/dist/lib/auth/auth-middleware.js +153 -0
- package/dist/lib/auth/auth-middleware.js.map +1 -0
- package/dist/lib/auth/capabilities.d.ts +40 -0
- package/dist/lib/auth/capabilities.d.ts.map +1 -0
- package/dist/lib/auth/capabilities.js +44 -0
- package/dist/lib/auth/capabilities.js.map +1 -0
- package/dist/lib/auth/claims-cache.d.ts +70 -0
- package/dist/lib/auth/claims-cache.d.ts.map +1 -0
- package/dist/lib/auth/claims-cache.js +139 -0
- package/dist/lib/auth/claims-cache.js.map +1 -0
- package/dist/lib/auth/cognito-jwt.d.ts +6 -0
- package/dist/lib/auth/cognito-jwt.d.ts.map +1 -1
- package/dist/lib/auth/cognito-jwt.js.map +1 -1
- package/dist/lib/auth/idp-redirect-builder.d.ts +43 -0
- package/dist/lib/auth/idp-redirect-builder.d.ts.map +1 -0
- package/dist/lib/auth/idp-redirect-builder.js +48 -0
- package/dist/lib/auth/idp-redirect-builder.js.map +1 -0
- package/dist/lib/auth/require.d.ts +51 -0
- package/dist/lib/auth/require.d.ts.map +1 -0
- package/dist/lib/auth/require.js +99 -0
- package/dist/lib/auth/require.js.map +1 -0
- package/dist/lib/auth/role-grants.d.ts +18 -0
- package/dist/lib/auth/role-grants.d.ts.map +1 -0
- package/dist/lib/auth/role-grants.js +62 -0
- package/dist/lib/auth/role-grants.js.map +1 -0
- package/dist/lib/cognito/idp-sdk.d.ts +80 -0
- package/dist/lib/cognito/idp-sdk.d.ts.map +1 -0
- package/dist/lib/cognito/idp-sdk.js +186 -0
- package/dist/lib/cognito/idp-sdk.js.map +1 -0
- package/dist/lib/cognito/issuer-probe.d.ts +47 -0
- package/dist/lib/cognito/issuer-probe.d.ts.map +1 -0
- package/dist/lib/cognito/issuer-probe.js +319 -0
- package/dist/lib/cognito/issuer-probe.js.map +1 -0
- package/dist/lib/comment-handler.d.ts +7 -7
- package/dist/lib/comment-handler.d.ts.map +1 -1
- package/dist/lib/comment-handler.js +23 -20
- package/dist/lib/comment-handler.js.map +1 -1
- package/dist/lib/compliance/baseline.d.ts +15 -0
- package/dist/lib/compliance/baseline.d.ts.map +1 -0
- package/dist/lib/compliance/baseline.js +205 -0
- package/dist/lib/compliance/baseline.js.map +1 -0
- package/dist/lib/compliance/tenant-merge.d.ts +35 -0
- package/dist/lib/compliance/tenant-merge.d.ts.map +1 -0
- package/dist/lib/compliance/tenant-merge.js +80 -0
- package/dist/lib/compliance/tenant-merge.js.map +1 -0
- package/dist/lib/compliance/types.d.ts +135 -0
- package/dist/lib/compliance/types.d.ts.map +1 -0
- package/dist/lib/compliance/types.js +9 -0
- package/dist/lib/compliance/types.js.map +1 -0
- package/dist/lib/connection-code-handler.d.ts +4 -4
- package/dist/lib/connection-code-handler.d.ts.map +1 -1
- package/dist/lib/connection-code-handler.js +21 -11
- package/dist/lib/connection-code-handler.js.map +1 -1
- package/dist/lib/feed-handler.d.ts +2 -2
- package/dist/lib/feed-handler.d.ts.map +1 -1
- package/dist/lib/feed-handler.js +5 -9
- package/dist/lib/feed-handler.js.map +1 -1
- package/dist/lib/middleware/idempotency-store.d.ts +86 -0
- package/dist/lib/middleware/idempotency-store.d.ts.map +1 -0
- package/dist/lib/middleware/idempotency-store.js +109 -0
- package/dist/lib/middleware/idempotency-store.js.map +1 -0
- package/dist/lib/middleware/idempotency.d.ts +37 -0
- package/dist/lib/middleware/idempotency.d.ts.map +1 -0
- package/dist/lib/middleware/idempotency.js +358 -0
- package/dist/lib/middleware/idempotency.js.map +1 -0
- package/dist/lib/net/trusted-client-ip.d.ts +39 -0
- package/dist/lib/net/trusted-client-ip.d.ts.map +1 -0
- package/dist/lib/net/trusted-client-ip.js +100 -0
- package/dist/lib/net/trusted-client-ip.js.map +1 -0
- package/dist/lib/notification-handler.d.ts +5 -5
- package/dist/lib/notification-handler.d.ts.map +1 -1
- package/dist/lib/notification-handler.js +11 -9
- package/dist/lib/notification-handler.js.map +1 -1
- package/dist/lib/oauth/cognito-issuer.d.ts +34 -0
- package/dist/lib/oauth/cognito-issuer.d.ts.map +1 -0
- package/dist/lib/oauth/cognito-issuer.js +53 -0
- package/dist/lib/oauth/cognito-issuer.js.map +1 -0
- package/dist/lib/oauth/device-authorization.d.ts +145 -0
- package/dist/lib/oauth/device-authorization.d.ts.map +1 -0
- package/dist/lib/oauth/device-authorization.js +312 -0
- package/dist/lib/oauth/device-authorization.js.map +1 -0
- package/dist/lib/oauth/envelope-crypto.d.ts +101 -0
- package/dist/lib/oauth/envelope-crypto.d.ts.map +1 -0
- package/dist/lib/oauth/envelope-crypto.js +223 -0
- package/dist/lib/oauth/envelope-crypto.js.map +1 -0
- package/dist/lib/oauth/refresh-detection.d.ts +126 -0
- package/dist/lib/oauth/refresh-detection.d.ts.map +1 -0
- package/dist/lib/oauth/refresh-detection.js +248 -0
- package/dist/lib/oauth/refresh-detection.js.map +1 -0
- package/dist/lib/openapi/generator.d.ts +78 -0
- package/dist/lib/openapi/generator.d.ts.map +1 -0
- package/dist/lib/openapi/generator.js +201 -0
- package/dist/lib/openapi/generator.js.map +1 -0
- package/dist/lib/post-handler.d.ts +1 -1
- package/dist/lib/post-handler.d.ts.map +1 -1
- package/dist/lib/post-handler.js +4 -15
- package/dist/lib/post-handler.js.map +1 -1
- package/dist/lib/rate-limit.d.ts.map +1 -1
- package/dist/lib/rate-limit.js +11 -3
- package/dist/lib/rate-limit.js.map +1 -1
- package/dist/lib/routes/agent-authorize.d.ts +32 -0
- package/dist/lib/routes/agent-authorize.d.ts.map +1 -0
- package/dist/lib/routes/agent-authorize.js +479 -0
- package/dist/lib/routes/agent-authorize.js.map +1 -0
- package/dist/lib/routes/agent-sessions.d.ts +20 -0
- package/dist/lib/routes/agent-sessions.d.ts.map +1 -0
- package/dist/lib/routes/agent-sessions.js +124 -0
- package/dist/lib/routes/agent-sessions.js.map +1 -0
- package/dist/lib/routes/agent-surface.d.ts +37 -0
- package/dist/lib/routes/agent-surface.d.ts.map +1 -0
- package/dist/lib/routes/agent-surface.js +208 -0
- package/dist/lib/routes/agent-surface.js.map +1 -0
- package/dist/lib/routes/auth-discover.d.ts +18 -0
- package/dist/lib/routes/auth-discover.d.ts.map +1 -0
- package/dist/lib/routes/auth-discover.js +177 -0
- package/dist/lib/routes/auth-discover.js.map +1 -0
- package/dist/lib/routes/comments.d.ts.map +1 -1
- package/dist/lib/routes/comments.js +36 -7
- package/dist/lib/routes/comments.js.map +1 -1
- package/dist/lib/routes/connection-codes.d.ts.map +1 -1
- package/dist/lib/routes/connection-codes.js +21 -4
- package/dist/lib/routes/connection-codes.js.map +1 -1
- package/dist/lib/routes/content-discovery.d.ts.map +1 -1
- package/dist/lib/routes/content-discovery.js +18 -13
- package/dist/lib/routes/content-discovery.js.map +1 -1
- package/dist/lib/routes/dashboard.js +1 -1
- package/dist/lib/routes/dashboard.js.map +1 -1
- package/dist/lib/routes/employees.d.ts.map +1 -1
- package/dist/lib/routes/employees.js +57 -15
- package/dist/lib/routes/employees.js.map +1 -1
- package/dist/lib/routes/entities.d.ts.map +1 -1
- package/dist/lib/routes/entities.js +35 -19
- package/dist/lib/routes/entities.js.map +1 -1
- package/dist/lib/routes/errors.d.ts +34 -0
- package/dist/lib/routes/errors.d.ts.map +1 -0
- package/dist/lib/routes/errors.js +57 -0
- package/dist/lib/routes/errors.js.map +1 -0
- package/dist/lib/routes/feeds.d.ts.map +1 -1
- package/dist/lib/routes/feeds.js +12 -2
- package/dist/lib/routes/feeds.js.map +1 -1
- package/dist/lib/routes/index.d.ts.map +1 -1
- package/dist/lib/routes/index.js +50 -0
- package/dist/lib/routes/index.js.map +1 -1
- package/dist/lib/routes/mfa.d.ts.map +1 -1
- package/dist/lib/routes/mfa.js +1 -0
- package/dist/lib/routes/mfa.js.map +1 -1
- package/dist/lib/routes/notifications.d.ts.map +1 -1
- package/dist/lib/routes/notifications.js +21 -4
- package/dist/lib/routes/notifications.js.map +1 -1
- package/dist/lib/routes/oauth.d.ts +15 -0
- package/dist/lib/routes/oauth.d.ts.map +1 -0
- package/dist/lib/routes/oauth.js +139 -0
- package/dist/lib/routes/oauth.js.map +1 -0
- package/dist/lib/routes/posts.d.ts.map +1 -1
- package/dist/lib/routes/posts.js +30 -19
- package/dist/lib/routes/posts.js.map +1 -1
- package/dist/lib/routes/products.d.ts.map +1 -1
- package/dist/lib/routes/products.js +19 -22
- package/dist/lib/routes/products.js.map +1 -1
- package/dist/lib/routes/setup-status.d.ts +34 -0
- package/dist/lib/routes/setup-status.d.ts.map +1 -0
- package/dist/lib/routes/setup-status.js +87 -0
- package/dist/lib/routes/setup-status.js.map +1 -0
- package/dist/lib/routes/taxonomy-analytics.d.ts.map +1 -1
- package/dist/lib/routes/taxonomy-analytics.js +15 -14
- package/dist/lib/routes/taxonomy-analytics.js.map +1 -1
- package/dist/lib/routes/taxonomy.d.ts.map +1 -1
- package/dist/lib/routes/taxonomy.js +19 -16
- package/dist/lib/routes/taxonomy.js.map +1 -1
- package/dist/lib/routes/tenant-audit.d.ts +19 -0
- package/dist/lib/routes/tenant-audit.d.ts.map +1 -0
- package/dist/lib/routes/tenant-audit.js +244 -0
- package/dist/lib/routes/tenant-audit.js.map +1 -0
- package/dist/lib/routes/tenant-compliance.d.ts +21 -0
- package/dist/lib/routes/tenant-compliance.d.ts.map +1 -0
- package/dist/lib/routes/tenant-compliance.js +122 -0
- package/dist/lib/routes/tenant-compliance.js.map +1 -0
- package/dist/lib/routes/tenant-domains.d.ts +11 -0
- package/dist/lib/routes/tenant-domains.d.ts.map +1 -0
- package/dist/lib/routes/tenant-domains.js +95 -0
- package/dist/lib/routes/tenant-domains.js.map +1 -0
- package/dist/lib/routes/tenant-idp.d.ts +3 -0
- package/dist/lib/routes/tenant-idp.d.ts.map +1 -0
- package/dist/lib/routes/tenant-idp.js +89 -0
- package/dist/lib/routes/tenant-idp.js.map +1 -0
- package/dist/lib/routes/tenant-members.d.ts +13 -0
- package/dist/lib/routes/tenant-members.d.ts.map +1 -0
- package/dist/lib/routes/tenant-members.js +75 -0
- package/dist/lib/routes/tenant-members.js.map +1 -0
- package/dist/lib/routes/tenant-role-mappings.d.ts +11 -0
- package/dist/lib/routes/tenant-role-mappings.d.ts.map +1 -0
- package/dist/lib/routes/tenant-role-mappings.js +90 -0
- package/dist/lib/routes/tenant-role-mappings.js.map +1 -0
- package/dist/lib/routes/tenants.d.ts +13 -0
- package/dist/lib/routes/tenants.d.ts.map +1 -0
- package/dist/lib/routes/tenants.js +121 -0
- package/dist/lib/routes/tenants.js.map +1 -0
- package/dist/lib/routes/types.d.ts +9 -0
- package/dist/lib/routes/types.d.ts.map +1 -1
- package/dist/lib/schemas.d.ts +2 -2
- package/dist/lib/secrets/idp-secrets.d.ts +51 -0
- package/dist/lib/secrets/idp-secrets.d.ts.map +1 -0
- package/dist/lib/secrets/idp-secrets.js +111 -0
- package/dist/lib/secrets/idp-secrets.js.map +1 -0
- package/dist/lib/security-monitor.d.ts.map +1 -1
- package/dist/lib/security-monitor.js +6 -1
- package/dist/lib/security-monitor.js.map +1 -1
- package/dist/lib/session-manager.d.ts +1 -0
- package/dist/lib/session-manager.d.ts.map +1 -1
- package/dist/lib/session-manager.js.map +1 -1
- package/dist/lib/taxonomy-handler-factory.d.ts +4 -2
- package/dist/lib/taxonomy-handler-factory.d.ts.map +1 -1
- package/dist/lib/taxonomy-handler-factory.js +8 -7
- package/dist/lib/taxonomy-handler-factory.js.map +1 -1
- package/dist/lib/tenant/audit-emit.d.ts +18 -0
- package/dist/lib/tenant/audit-emit.d.ts.map +1 -0
- package/dist/lib/tenant/audit-emit.js +16 -0
- package/dist/lib/tenant/audit-emit.js.map +1 -0
- package/dist/lib/tenant/derive-domain.d.ts +19 -0
- package/dist/lib/tenant/derive-domain.d.ts.map +1 -0
- package/dist/lib/tenant/derive-domain.js +38 -0
- package/dist/lib/tenant/derive-domain.js.map +1 -0
- package/dist/lib/tenant/domain-handler.d.ts +42 -0
- package/dist/lib/tenant/domain-handler.d.ts.map +1 -0
- package/dist/lib/tenant/domain-handler.js +344 -0
- package/dist/lib/tenant/domain-handler.js.map +1 -0
- package/dist/lib/tenant/domain-validator.d.ts +28 -0
- package/dist/lib/tenant/domain-validator.d.ts.map +1 -0
- package/dist/lib/tenant/domain-validator.js +145 -0
- package/dist/lib/tenant/domain-validator.js.map +1 -0
- package/dist/lib/tenant/domain-verifier.d.ts +30 -0
- package/dist/lib/tenant/domain-verifier.d.ts.map +1 -0
- package/dist/lib/tenant/domain-verifier.js +53 -0
- package/dist/lib/tenant/domain-verifier.js.map +1 -0
- package/dist/lib/tenant/idp-handler.d.ts +29 -0
- package/dist/lib/tenant/idp-handler.d.ts.map +1 -0
- package/dist/lib/tenant/idp-handler.js +693 -0
- package/dist/lib/tenant/idp-handler.js.map +1 -0
- package/dist/lib/tenant/idp-name.d.ts +2 -0
- package/dist/lib/tenant/idp-name.d.ts.map +1 -0
- package/dist/lib/tenant/idp-name.js +20 -0
- package/dist/lib/tenant/idp-name.js.map +1 -0
- package/dist/lib/tenant/member-handler.d.ts +31 -0
- package/dist/lib/tenant/member-handler.d.ts.map +1 -0
- package/dist/lib/tenant/member-handler.js +343 -0
- package/dist/lib/tenant/member-handler.js.map +1 -0
- package/dist/lib/tenant/reserved-slugs.d.ts +37 -0
- package/dist/lib/tenant/reserved-slugs.d.ts.map +1 -0
- package/dist/lib/tenant/reserved-slugs.js +116 -0
- package/dist/lib/tenant/reserved-slugs.js.map +1 -0
- package/dist/lib/tenant/resolve-role.d.ts +39 -0
- package/dist/lib/tenant/resolve-role.d.ts.map +1 -0
- package/dist/lib/tenant/resolve-role.js +60 -0
- package/dist/lib/tenant/resolve-role.js.map +1 -0
- package/dist/lib/tenant/role-mapping-handler.d.ts +26 -0
- package/dist/lib/tenant/role-mapping-handler.d.ts.map +1 -0
- package/dist/lib/tenant/role-mapping-handler.js +260 -0
- package/dist/lib/tenant/role-mapping-handler.js.map +1 -0
- package/dist/lib/tenant/setup-status.d.ts +83 -0
- package/dist/lib/tenant/setup-status.d.ts.map +1 -0
- package/dist/lib/tenant/setup-status.js +201 -0
- package/dist/lib/tenant/setup-status.js.map +1 -0
- package/dist/lib/tenant/slug-validator.d.ts +31 -0
- package/dist/lib/tenant/slug-validator.d.ts.map +1 -0
- package/dist/lib/tenant/slug-validator.js +42 -0
- package/dist/lib/tenant/slug-validator.js.map +1 -0
- package/dist/lib/tenant/tenant-handler.d.ts +49 -0
- package/dist/lib/tenant/tenant-handler.d.ts.map +1 -0
- package/dist/lib/tenant/tenant-handler.js +377 -0
- package/dist/lib/tenant/tenant-handler.js.map +1 -0
- package/dist/lib/tenant/transfer-ownership.d.ts +39 -0
- package/dist/lib/tenant/transfer-ownership.d.ts.map +1 -0
- package/dist/lib/tenant/transfer-ownership.js +66 -0
- package/dist/lib/tenant/transfer-ownership.js.map +1 -0
- package/dist/lib/user/derive-handle.d.ts +29 -0
- package/dist/lib/user/derive-handle.d.ts.map +1 -0
- package/dist/lib/user/derive-handle.js +65 -0
- package/dist/lib/user/derive-handle.js.map +1 -0
- package/dist/lib/user-deprovisioning.d.ts +11 -1
- package/dist/lib/user-deprovisioning.d.ts.map +1 -1
- package/dist/lib/user-deprovisioning.js +46 -2
- package/dist/lib/user-deprovisioning.js.map +1 -1
- package/dist/lib/validation/feature-toggle-schemas.d.ts +10 -10
- package/package.json +6 -3
- package/prisma/migrations/20260502094501_add_tenancy_model/migration.sql +334 -0
- package/prisma/migrations/20260503000000_add_tenant_region/migration.sql +4 -0
- package/prisma/schema.prisma +324 -74
- package/src/lambda/nightly-cron.ts +4 -1
- package/src/lambda/post-confirmation.ts +405 -29
- package/src/lambda/pre-token-generation.ts +300 -59
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth Middleware
|
|
3
|
+
*
|
|
4
|
+
* Resolves an authenticated request's Cognito JWT into a typed AuthContext.
|
|
5
|
+
* Returns null if the token is absent or invalid — callers treat null as 401.
|
|
6
|
+
*
|
|
7
|
+
* Requires COGNITO_USER_POOL_ID and COGNITO_APP_CLIENT_ID in env.
|
|
8
|
+
*/
|
|
9
|
+
import type { Env } from "../../env";
|
|
10
|
+
import type { AuthContext } from "./auth-context";
|
|
11
|
+
/**
|
|
12
|
+
* Extract and verify the Bearer token from the request, then assemble an
|
|
13
|
+
* AuthContext from the JWT claims written by the pre-token-generation Lambda.
|
|
14
|
+
*
|
|
15
|
+
* Returns null when:
|
|
16
|
+
* - No Authorization header is present.
|
|
17
|
+
* - The token fails verification (expired, bad signature, wrong pool/client).
|
|
18
|
+
* - Required claims are missing (userId, activeTenantId).
|
|
19
|
+
*/
|
|
20
|
+
export declare function authMiddleware(request: Request, env: Env): Promise<AuthContext | null>;
|
|
21
|
+
/**
|
|
22
|
+
* Assert that the caller's active tenant matches the tenant referenced by
|
|
23
|
+
* the path parameter.
|
|
24
|
+
*
|
|
25
|
+
* Returns a 403 Response when the tenants don't match (unless the caller
|
|
26
|
+
* is a SUPER_ADMIN, who bypasses tenant scope by design).
|
|
27
|
+
* Returns null when the check passes.
|
|
28
|
+
*
|
|
29
|
+
* Use this for ADMIN endpoints (POST/PATCH/DELETE on /api/tenants/:id/...
|
|
30
|
+
* where the attacker already knows the ID and 403 is acceptable per
|
|
31
|
+
* security-and-isolation §"Privilege boundary at the API").
|
|
32
|
+
*
|
|
33
|
+
* G4 MEDIUM-4: this helper deliberately returns 403 (not 404) when the
|
|
34
|
+
* caller is authenticated but acting on a tenant other than their own.
|
|
35
|
+
* That makes the response distinguishable from "tenant does not exist"
|
|
36
|
+
* (which surfaces as 404). The federation onboarding flow depends on
|
|
37
|
+
* that distinction — a caller scripting setup needs to be able to tell
|
|
38
|
+
* whether their target id is unused vs out of reach. Data-side cross-
|
|
39
|
+
* tenant reads should use `requireOwnTenant` (404 for both conditions)
|
|
40
|
+
* instead.
|
|
41
|
+
*/
|
|
42
|
+
export declare function requireActiveTenant(auth: AuthContext, tenantIdFromPath: string): Response | null;
|
|
43
|
+
/**
|
|
44
|
+
* Same as requireActiveTenant but returns 404 instead of 403, so the response
|
|
45
|
+
* does not distinguish "tenant exists but you can't see it" from "tenant
|
|
46
|
+
* does not exist". Use this for DATA endpoints (GET /api/tenants/:id and
|
|
47
|
+
* any cross-tenant resource lookup) where existence-leak is the concern.
|
|
48
|
+
*/
|
|
49
|
+
export declare function requireOwnTenant(auth: AuthContext, tenantIdFromPath: string): Response | null;
|
|
50
|
+
//# sourceMappingURL=auth-middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-middleware.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/auth-middleware.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAOlD;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,GAAG,GACP,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAsD7B;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,WAAW,EACjB,gBAAgB,EAAE,MAAM,GACvB,QAAQ,GAAG,IAAI,CAOjB;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,WAAW,EACjB,gBAAgB,EAAE,MAAM,GACvB,QAAQ,GAAG,IAAI,CAOjB"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Auth Middleware
|
|
4
|
+
*
|
|
5
|
+
* Resolves an authenticated request's Cognito JWT into a typed AuthContext.
|
|
6
|
+
* Returns null if the token is absent or invalid — callers treat null as 401.
|
|
7
|
+
*
|
|
8
|
+
* Requires COGNITO_USER_POOL_ID and COGNITO_APP_CLIENT_ID in env.
|
|
9
|
+
*/
|
|
10
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}) : (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
o[k2] = m[k];
|
|
20
|
+
}));
|
|
21
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
22
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
23
|
+
}) : function(o, v) {
|
|
24
|
+
o["default"] = v;
|
|
25
|
+
});
|
|
26
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
27
|
+
var ownKeys = function(o) {
|
|
28
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
29
|
+
var ar = [];
|
|
30
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
31
|
+
return ar;
|
|
32
|
+
};
|
|
33
|
+
return ownKeys(o);
|
|
34
|
+
};
|
|
35
|
+
return function (mod) {
|
|
36
|
+
if (mod && mod.__esModule) return mod;
|
|
37
|
+
var result = {};
|
|
38
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
39
|
+
__setModuleDefault(result, mod);
|
|
40
|
+
return result;
|
|
41
|
+
};
|
|
42
|
+
})();
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.authMiddleware = authMiddleware;
|
|
45
|
+
exports.requireActiveTenant = requireActiveTenant;
|
|
46
|
+
exports.requireOwnTenant = requireOwnTenant;
|
|
47
|
+
const cognito_jwt_1 = require("./cognito-jwt");
|
|
48
|
+
// cuid v1 is `c[a-z0-9]{24}`. Allow up to 40 chars to absorb future widening
|
|
49
|
+
// and any cuid v2 / nanoid variants without re-issuing every JWT.
|
|
50
|
+
const CUID_RE = /^c[a-z0-9]{24,40}$/;
|
|
51
|
+
/**
|
|
52
|
+
* Extract and verify the Bearer token from the request, then assemble an
|
|
53
|
+
* AuthContext from the JWT claims written by the pre-token-generation Lambda.
|
|
54
|
+
*
|
|
55
|
+
* Returns null when:
|
|
56
|
+
* - No Authorization header is present.
|
|
57
|
+
* - The token fails verification (expired, bad signature, wrong pool/client).
|
|
58
|
+
* - Required claims are missing (userId, activeTenantId).
|
|
59
|
+
*/
|
|
60
|
+
async function authMiddleware(request, env) {
|
|
61
|
+
const token = (0, cognito_jwt_1.extractBearerToken)(request.headers.get("Authorization"));
|
|
62
|
+
if (!token)
|
|
63
|
+
return null;
|
|
64
|
+
let claims;
|
|
65
|
+
try {
|
|
66
|
+
claims = await (0, cognito_jwt_1.verifyCognitoJwt)(token);
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
const userId = claims["custom:userId"];
|
|
72
|
+
const activeTenantId = claims["custom:activeTenantId"];
|
|
73
|
+
// Both are non-negotiable — pre-token-gen Lambda always writes them.
|
|
74
|
+
if (!userId || !activeTenantId)
|
|
75
|
+
return null;
|
|
76
|
+
// Reject malformed claim values: cuid v1 is c[a-z0-9]{24}. We accept up
|
|
77
|
+
// to 40 chars to leave headroom for the slug-max widening done in T3.
|
|
78
|
+
if (!CUID_RE.test(userId) || !CUID_RE.test(activeTenantId))
|
|
79
|
+
return null;
|
|
80
|
+
// Support both the T2-era single "custom:role" and the T3+ "custom:globalRole".
|
|
81
|
+
const globalRole = (claims["custom:globalRole"] ?? claims["custom:role"] ?? "END_USER");
|
|
82
|
+
// Default to GUEST (least privilege) when the tenantRole claim is missing,
|
|
83
|
+
// so a malformed token never silently confers MEMBER capabilities.
|
|
84
|
+
const tenantRole = (claims["custom:tenantRole"] ?? "GUEST");
|
|
85
|
+
const tenantSlug = claims["custom:tenantSlug"] ?? "";
|
|
86
|
+
const handle = claims["custom:handle"] ?? "";
|
|
87
|
+
const cognitoSub = claims.sub;
|
|
88
|
+
// Memberships are loaded lazily — most requests don't need the full list.
|
|
89
|
+
let membershipsCache = null;
|
|
90
|
+
const membershipsLoader = async () => {
|
|
91
|
+
if (membershipsCache)
|
|
92
|
+
return membershipsCache;
|
|
93
|
+
const { createPrisma } = await Promise.resolve().then(() => __importStar(require("../../db")));
|
|
94
|
+
const db = createPrisma(env);
|
|
95
|
+
membershipsCache = await db.tenantMember.findMany({
|
|
96
|
+
where: { userId, status: "ACTIVE" },
|
|
97
|
+
include: { tenant: true },
|
|
98
|
+
});
|
|
99
|
+
return membershipsCache;
|
|
100
|
+
};
|
|
101
|
+
return {
|
|
102
|
+
cognitoSub,
|
|
103
|
+
userId,
|
|
104
|
+
globalRole,
|
|
105
|
+
activeTenantId,
|
|
106
|
+
tenantSlug,
|
|
107
|
+
tenantRole,
|
|
108
|
+
handle,
|
|
109
|
+
membershipsLoader,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Assert that the caller's active tenant matches the tenant referenced by
|
|
114
|
+
* the path parameter.
|
|
115
|
+
*
|
|
116
|
+
* Returns a 403 Response when the tenants don't match (unless the caller
|
|
117
|
+
* is a SUPER_ADMIN, who bypasses tenant scope by design).
|
|
118
|
+
* Returns null when the check passes.
|
|
119
|
+
*
|
|
120
|
+
* Use this for ADMIN endpoints (POST/PATCH/DELETE on /api/tenants/:id/...
|
|
121
|
+
* where the attacker already knows the ID and 403 is acceptable per
|
|
122
|
+
* security-and-isolation §"Privilege boundary at the API").
|
|
123
|
+
*
|
|
124
|
+
* G4 MEDIUM-4: this helper deliberately returns 403 (not 404) when the
|
|
125
|
+
* caller is authenticated but acting on a tenant other than their own.
|
|
126
|
+
* That makes the response distinguishable from "tenant does not exist"
|
|
127
|
+
* (which surfaces as 404). The federation onboarding flow depends on
|
|
128
|
+
* that distinction — a caller scripting setup needs to be able to tell
|
|
129
|
+
* whether their target id is unused vs out of reach. Data-side cross-
|
|
130
|
+
* tenant reads should use `requireOwnTenant` (404 for both conditions)
|
|
131
|
+
* instead.
|
|
132
|
+
*/
|
|
133
|
+
function requireActiveTenant(auth, tenantIdFromPath) {
|
|
134
|
+
if (auth.globalRole === "SUPER_ADMIN")
|
|
135
|
+
return null;
|
|
136
|
+
if (auth.activeTenantId === tenantIdFromPath)
|
|
137
|
+
return null;
|
|
138
|
+
return new Response(JSON.stringify({ error: "FORBIDDEN", message: "Active tenant does not match requested resource" }), { status: 403, headers: { "content-type": "application/json" } });
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Same as requireActiveTenant but returns 404 instead of 403, so the response
|
|
142
|
+
* does not distinguish "tenant exists but you can't see it" from "tenant
|
|
143
|
+
* does not exist". Use this for DATA endpoints (GET /api/tenants/:id and
|
|
144
|
+
* any cross-tenant resource lookup) where existence-leak is the concern.
|
|
145
|
+
*/
|
|
146
|
+
function requireOwnTenant(auth, tenantIdFromPath) {
|
|
147
|
+
if (auth.globalRole === "SUPER_ADMIN")
|
|
148
|
+
return null;
|
|
149
|
+
if (auth.activeTenantId === tenantIdFromPath)
|
|
150
|
+
return null;
|
|
151
|
+
return new Response(JSON.stringify({ error: "NOT_FOUND", message: "Tenant not found" }), { status: 404, headers: { "content-type": "application/json" } });
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=auth-middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-middleware.js","sourceRoot":"","sources":["../../../src/lib/auth/auth-middleware.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capability catalog — every action a tenant member can be authorized to do.
|
|
3
|
+
*
|
|
4
|
+
* Naming: `<resource>.<verb>`, lowercase, dot-separated, no abbreviations.
|
|
5
|
+
* Capabilities are tenant-scoped unless prefixed `platform.` (none in MVP).
|
|
6
|
+
*
|
|
7
|
+
* Source of truth: doc/02-technical/identity-federation/05-roles-and-permissions.md.
|
|
8
|
+
*/
|
|
9
|
+
export declare const Capability: {
|
|
10
|
+
readonly TenantUpdate: "tenant.update";
|
|
11
|
+
readonly TenantDelete: "tenant.delete";
|
|
12
|
+
readonly TenantSuspend: "tenant.suspend";
|
|
13
|
+
readonly MemberInvite: "member.invite";
|
|
14
|
+
readonly MemberRemove: "member.remove";
|
|
15
|
+
readonly MemberChangeRole: "member.change_role";
|
|
16
|
+
readonly MemberSuspend: "member.suspend";
|
|
17
|
+
readonly MemberView: "member.view";
|
|
18
|
+
readonly IdpConfigure: "idp.configure";
|
|
19
|
+
readonly IdpView: "idp.view";
|
|
20
|
+
readonly RoleMappingEdit: "role_mapping.edit";
|
|
21
|
+
readonly DomainAdd: "domain.add";
|
|
22
|
+
readonly DomainVerify: "domain.verify";
|
|
23
|
+
readonly DomainRemove: "domain.remove";
|
|
24
|
+
readonly DomainView: "domain.view";
|
|
25
|
+
readonly EntityCreate: "entity.create";
|
|
26
|
+
readonly EntityUpdate: "entity.update";
|
|
27
|
+
readonly EntityDelete: "entity.delete";
|
|
28
|
+
readonly EntityView: "entity.view";
|
|
29
|
+
readonly PostCreate: "post.create";
|
|
30
|
+
readonly PostUpdate: "post.update";
|
|
31
|
+
readonly PostDelete: "post.delete";
|
|
32
|
+
readonly PostModerate: "post.moderate";
|
|
33
|
+
readonly PostView: "post.view";
|
|
34
|
+
readonly AuditView: "audit.view";
|
|
35
|
+
readonly ManageAgentSessions: "manage:agent_sessions";
|
|
36
|
+
};
|
|
37
|
+
export type CapabilityValue = (typeof Capability)[keyof typeof Capability];
|
|
38
|
+
/** All capabilities, used by tests + reflection helpers. */
|
|
39
|
+
export declare const ALL_CAPABILITIES: ReadonlyArray<CapabilityValue>;
|
|
40
|
+
//# sourceMappingURL=capabilities.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/capabilities.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoCb,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,OAAO,UAAU,CAAC,CAAC;AAE3E,4DAA4D;AAC5D,eAAO,MAAM,gBAAgB,EAAE,aAAa,CAAC,eAAe,CACC,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Capability catalog — every action a tenant member can be authorized to do.
|
|
4
|
+
*
|
|
5
|
+
* Naming: `<resource>.<verb>`, lowercase, dot-separated, no abbreviations.
|
|
6
|
+
* Capabilities are tenant-scoped unless prefixed `platform.` (none in MVP).
|
|
7
|
+
*
|
|
8
|
+
* Source of truth: doc/02-technical/identity-federation/05-roles-and-permissions.md.
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.ALL_CAPABILITIES = exports.Capability = void 0;
|
|
12
|
+
exports.Capability = {
|
|
13
|
+
TenantUpdate: "tenant.update",
|
|
14
|
+
TenantDelete: "tenant.delete",
|
|
15
|
+
TenantSuspend: "tenant.suspend",
|
|
16
|
+
MemberInvite: "member.invite",
|
|
17
|
+
MemberRemove: "member.remove",
|
|
18
|
+
MemberChangeRole: "member.change_role",
|
|
19
|
+
MemberSuspend: "member.suspend",
|
|
20
|
+
MemberView: "member.view",
|
|
21
|
+
IdpConfigure: "idp.configure",
|
|
22
|
+
IdpView: "idp.view",
|
|
23
|
+
RoleMappingEdit: "role_mapping.edit",
|
|
24
|
+
DomainAdd: "domain.add",
|
|
25
|
+
DomainVerify: "domain.verify",
|
|
26
|
+
DomainRemove: "domain.remove",
|
|
27
|
+
DomainView: "domain.view",
|
|
28
|
+
EntityCreate: "entity.create",
|
|
29
|
+
EntityUpdate: "entity.update",
|
|
30
|
+
EntityDelete: "entity.delete",
|
|
31
|
+
EntityView: "entity.view",
|
|
32
|
+
PostCreate: "post.create",
|
|
33
|
+
PostUpdate: "post.update",
|
|
34
|
+
PostDelete: "post.delete",
|
|
35
|
+
PostModerate: "post.moderate",
|
|
36
|
+
PostView: "post.view",
|
|
37
|
+
AuditView: "audit.view",
|
|
38
|
+
// Agent session management (T9b-d) — approve, list, revoke device-auth
|
|
39
|
+
// sessions on behalf of the tenant. Granted to ADMIN/OWNER.
|
|
40
|
+
ManageAgentSessions: "manage:agent_sessions",
|
|
41
|
+
};
|
|
42
|
+
/** All capabilities, used by tests + reflection helpers. */
|
|
43
|
+
exports.ALL_CAPABILITIES = Object.values(exports.Capability);
|
|
44
|
+
//# sourceMappingURL=capabilities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../../src/lib/auth/capabilities.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;AAEU,QAAA,UAAU,GAAG;IACxB,YAAY,EAAE,eAAe;IAC7B,YAAY,EAAE,eAAe;IAC7B,aAAa,EAAE,gBAAgB;IAE/B,YAAY,EAAE,eAAe;IAC7B,YAAY,EAAE,eAAe;IAC7B,gBAAgB,EAAE,oBAAoB;IACtC,aAAa,EAAE,gBAAgB;IAC/B,UAAU,EAAE,aAAa;IAEzB,YAAY,EAAE,eAAe;IAC7B,OAAO,EAAE,UAAU;IACnB,eAAe,EAAE,mBAAmB;IAEpC,SAAS,EAAE,YAAY;IACvB,YAAY,EAAE,eAAe;IAC7B,YAAY,EAAE,eAAe;IAC7B,UAAU,EAAE,aAAa;IAEzB,YAAY,EAAE,eAAe;IAC7B,YAAY,EAAE,eAAe;IAC7B,YAAY,EAAE,eAAe;IAC7B,UAAU,EAAE,aAAa;IAEzB,UAAU,EAAE,aAAa;IACzB,UAAU,EAAE,aAAa;IACzB,UAAU,EAAE,aAAa;IACzB,YAAY,EAAE,eAAe;IAC7B,QAAQ,EAAE,WAAW;IAErB,SAAS,EAAE,YAAY;IAEvB,uEAAuE;IACvE,4DAA4D;IAC5D,mBAAmB,EAAE,uBAAuB;CACpC,CAAC;AAIX,4DAA4D;AAC/C,QAAA,gBAAgB,GAC3B,MAAM,CAAC,MAAM,CAAC,kBAAU,CAAmC,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DynamoDB-backed claims cache for the pre-token-generation Lambda
|
|
3
|
+
* (T2 — JIT provisioning).
|
|
4
|
+
*
|
|
5
|
+
* Storage layout (single-table on the existing `{stage}-skybber` table):
|
|
6
|
+
* pk = `claims:{cognitoSub}`
|
|
7
|
+
* sk = `meta`
|
|
8
|
+
* ttl = epoch seconds; DynamoDB-managed expiry plus a manual check on read
|
|
9
|
+
* (DDB TTL deletes lag by up to 48h, so we never trust the row's
|
|
10
|
+
* existence alone)
|
|
11
|
+
*
|
|
12
|
+
* Concurrency: writes use a `ConditionExpression` that the existing row's
|
|
13
|
+
* `ttl` is missing or older than the incoming `ttl`. Two simultaneous
|
|
14
|
+
* pre-token-gen invocations for the same user (rare, but possible during a
|
|
15
|
+
* burst of token refreshes) cannot stale-overwrite a fresh entry.
|
|
16
|
+
*/
|
|
17
|
+
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
|
|
18
|
+
export interface CachedClaims {
|
|
19
|
+
/** Skybber `User.id` (cuid). May be empty string for drift sentinel. */
|
|
20
|
+
userId: string;
|
|
21
|
+
/** Global `UserRole` enum value. May be empty string for drift sentinel. */
|
|
22
|
+
globalRole: string;
|
|
23
|
+
/** `Tenant.id` of the user's currently-active tenant. */
|
|
24
|
+
activeTenantId: string;
|
|
25
|
+
/** `Tenant.slug` of the active tenant. */
|
|
26
|
+
tenantSlug: string;
|
|
27
|
+
/** `TenantRole` enum value within the active tenant. May be empty. */
|
|
28
|
+
tenantRole: string;
|
|
29
|
+
/** ActivityPub-style handle. May be empty. */
|
|
30
|
+
handle: string;
|
|
31
|
+
}
|
|
32
|
+
export declare const DEFAULT_CACHE_TTL_SECONDS = 3600;
|
|
33
|
+
export declare class ClaimsCache {
|
|
34
|
+
private readonly client;
|
|
35
|
+
private readonly tableName;
|
|
36
|
+
constructor(client: DynamoDBClient, tableName: string);
|
|
37
|
+
/**
|
|
38
|
+
* Returns cached claims if a fresh entry exists, else null. Stale rows
|
|
39
|
+
* (ttl in the past) are treated as a miss; we let DDB's own TTL sweep
|
|
40
|
+
* eventually delete them.
|
|
41
|
+
*/
|
|
42
|
+
get(cognitoSub: string): Promise<CachedClaims | null>;
|
|
43
|
+
/**
|
|
44
|
+
* Returns the user's last-known activeTenantId, regardless of TTL. Used by
|
|
45
|
+
* the pre-token-generation Lambda on cache miss so a user's explicit
|
|
46
|
+
* tenant-switch survives cache expiry rather than reverting to the
|
|
47
|
+
* first-org-tenant heuristic.
|
|
48
|
+
*/
|
|
49
|
+
getActiveTenantPreference(cognitoSub: string): Promise<string | null>;
|
|
50
|
+
/**
|
|
51
|
+
* Writes a cache entry. Uses a `ConditionExpression` so a stale write
|
|
52
|
+
* (e.g., one that started before a newer entry was written) cannot
|
|
53
|
+
* overwrite a fresher row. On collision we silently swallow the
|
|
54
|
+
* conditional-check failure — the cache still holds an acceptable value.
|
|
55
|
+
*/
|
|
56
|
+
put(cognitoSub: string, claims: CachedClaims, ttlSeconds?: number): Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* Forcibly remove a cache entry — used by admin paths (member-remove,
|
|
59
|
+
* role change, OWNER transfer) to make sure the next token refresh hits
|
|
60
|
+
* RDS rather than serving a stale role.
|
|
61
|
+
*/
|
|
62
|
+
invalidate(cognitoSub: string): Promise<void>;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Convenience constructor used by the Lambda handler. Reads the table name
|
|
66
|
+
* from `DYNAMODB_TABLE` and the region from `AWS_REGION`. Tests construct
|
|
67
|
+
* a `ClaimsCache` directly with a mock client.
|
|
68
|
+
*/
|
|
69
|
+
export declare function createClaimsCacheFromEnv(): ClaimsCache;
|
|
70
|
+
//# sourceMappingURL=claims-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claims-cache.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/claims-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EACL,cAAc,EAIf,MAAM,0BAA0B,CAAC;AAGlC,MAAM,WAAW,YAAY;IAC3B,wEAAwE;IACxE,MAAM,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,UAAU,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,cAAc,EAAE,MAAM,CAAC;IACvB,0CAA0C;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB,sEAAsE;IACtE,UAAU,EAAE,MAAM,CAAC;IACnB,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,yBAAyB,OAAO,CAAC;AAU9C,qBAAa,WAAW;IAEpB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS;gBADT,MAAM,EAAE,cAAc,EACtB,SAAS,EAAE,MAAM;IAGpC;;;;OAIG;IACG,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAqB3D;;;;;OAKG;IACG,yBAAyB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAa3E;;;;;OAKG;IACG,GAAG,CACP,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,YAAY,EACpB,UAAU,GAAE,MAAkC,GAC7C,OAAO,CAAC,IAAI,CAAC;IA6BhB;;;;OAIG;IACG,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAQpD;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,WAAW,CAOtD"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* DynamoDB-backed claims cache for the pre-token-generation Lambda
|
|
4
|
+
* (T2 — JIT provisioning).
|
|
5
|
+
*
|
|
6
|
+
* Storage layout (single-table on the existing `{stage}-skybber` table):
|
|
7
|
+
* pk = `claims:{cognitoSub}`
|
|
8
|
+
* sk = `meta`
|
|
9
|
+
* ttl = epoch seconds; DynamoDB-managed expiry plus a manual check on read
|
|
10
|
+
* (DDB TTL deletes lag by up to 48h, so we never trust the row's
|
|
11
|
+
* existence alone)
|
|
12
|
+
*
|
|
13
|
+
* Concurrency: writes use a `ConditionExpression` that the existing row's
|
|
14
|
+
* `ttl` is missing or older than the incoming `ttl`. Two simultaneous
|
|
15
|
+
* pre-token-gen invocations for the same user (rare, but possible during a
|
|
16
|
+
* burst of token refreshes) cannot stale-overwrite a fresh entry.
|
|
17
|
+
*/
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.ClaimsCache = exports.DEFAULT_CACHE_TTL_SECONDS = void 0;
|
|
20
|
+
exports.createClaimsCacheFromEnv = createClaimsCacheFromEnv;
|
|
21
|
+
const client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
|
|
22
|
+
const util_dynamodb_1 = require("@aws-sdk/util-dynamodb");
|
|
23
|
+
exports.DEFAULT_CACHE_TTL_SECONDS = 3600;
|
|
24
|
+
function pkFor(cognitoSub) {
|
|
25
|
+
return `claims:${cognitoSub}`;
|
|
26
|
+
}
|
|
27
|
+
function nowSeconds() {
|
|
28
|
+
return Math.floor(Date.now() / 1000);
|
|
29
|
+
}
|
|
30
|
+
class ClaimsCache {
|
|
31
|
+
client;
|
|
32
|
+
tableName;
|
|
33
|
+
constructor(client, tableName) {
|
|
34
|
+
this.client = client;
|
|
35
|
+
this.tableName = tableName;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Returns cached claims if a fresh entry exists, else null. Stale rows
|
|
39
|
+
* (ttl in the past) are treated as a miss; we let DDB's own TTL sweep
|
|
40
|
+
* eventually delete them.
|
|
41
|
+
*/
|
|
42
|
+
async get(cognitoSub) {
|
|
43
|
+
const result = await this.client.send(new client_dynamodb_1.GetItemCommand({
|
|
44
|
+
TableName: this.tableName,
|
|
45
|
+
Key: (0, util_dynamodb_1.marshall)({ pk: pkFor(cognitoSub), sk: "meta" }),
|
|
46
|
+
}));
|
|
47
|
+
if (!result.Item)
|
|
48
|
+
return null;
|
|
49
|
+
const item = (0, util_dynamodb_1.unmarshall)(result.Item);
|
|
50
|
+
const ttl = typeof item.ttl === "number" ? item.ttl : 0;
|
|
51
|
+
if (!ttl || ttl <= nowSeconds())
|
|
52
|
+
return null;
|
|
53
|
+
return {
|
|
54
|
+
userId: item.userId ?? "",
|
|
55
|
+
globalRole: item.globalRole ?? "",
|
|
56
|
+
activeTenantId: item.activeTenantId ?? "",
|
|
57
|
+
tenantSlug: item.tenantSlug ?? "",
|
|
58
|
+
tenantRole: item.tenantRole ?? "",
|
|
59
|
+
handle: item.handle ?? "",
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Returns the user's last-known activeTenantId, regardless of TTL. Used by
|
|
64
|
+
* the pre-token-generation Lambda on cache miss so a user's explicit
|
|
65
|
+
* tenant-switch survives cache expiry rather than reverting to the
|
|
66
|
+
* first-org-tenant heuristic.
|
|
67
|
+
*/
|
|
68
|
+
async getActiveTenantPreference(cognitoSub) {
|
|
69
|
+
const result = await this.client.send(new client_dynamodb_1.GetItemCommand({
|
|
70
|
+
TableName: this.tableName,
|
|
71
|
+
Key: (0, util_dynamodb_1.marshall)({ pk: pkFor(cognitoSub), sk: "meta" }),
|
|
72
|
+
}));
|
|
73
|
+
if (!result.Item)
|
|
74
|
+
return null;
|
|
75
|
+
const item = (0, util_dynamodb_1.unmarshall)(result.Item);
|
|
76
|
+
const activeTenantId = item.activeTenantId ?? "";
|
|
77
|
+
return activeTenantId || null;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Writes a cache entry. Uses a `ConditionExpression` so a stale write
|
|
81
|
+
* (e.g., one that started before a newer entry was written) cannot
|
|
82
|
+
* overwrite a fresher row. On collision we silently swallow the
|
|
83
|
+
* conditional-check failure — the cache still holds an acceptable value.
|
|
84
|
+
*/
|
|
85
|
+
async put(cognitoSub, claims, ttlSeconds = exports.DEFAULT_CACHE_TTL_SECONDS) {
|
|
86
|
+
const expiresAt = nowSeconds() + ttlSeconds;
|
|
87
|
+
try {
|
|
88
|
+
await this.client.send(new client_dynamodb_1.PutItemCommand({
|
|
89
|
+
TableName: this.tableName,
|
|
90
|
+
Item: (0, util_dynamodb_1.marshall)({
|
|
91
|
+
pk: pkFor(cognitoSub),
|
|
92
|
+
sk: "meta",
|
|
93
|
+
userId: claims.userId,
|
|
94
|
+
globalRole: claims.globalRole,
|
|
95
|
+
activeTenantId: claims.activeTenantId,
|
|
96
|
+
tenantSlug: claims.tenantSlug,
|
|
97
|
+
tenantRole: claims.tenantRole,
|
|
98
|
+
handle: claims.handle,
|
|
99
|
+
ttl: expiresAt,
|
|
100
|
+
}),
|
|
101
|
+
ConditionExpression: "attribute_not_exists(#ttl) OR #ttl < :incomingTtl",
|
|
102
|
+
ExpressionAttributeNames: { "#ttl": "ttl" },
|
|
103
|
+
ExpressionAttributeValues: (0, util_dynamodb_1.marshall)({ ":incomingTtl": expiresAt }),
|
|
104
|
+
}));
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
const name = err.name;
|
|
108
|
+
if (name === "ConditionalCheckFailedException")
|
|
109
|
+
return;
|
|
110
|
+
throw err;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Forcibly remove a cache entry — used by admin paths (member-remove,
|
|
115
|
+
* role change, OWNER transfer) to make sure the next token refresh hits
|
|
116
|
+
* RDS rather than serving a stale role.
|
|
117
|
+
*/
|
|
118
|
+
async invalidate(cognitoSub) {
|
|
119
|
+
await this.client.send(new client_dynamodb_1.DeleteItemCommand({
|
|
120
|
+
TableName: this.tableName,
|
|
121
|
+
Key: (0, util_dynamodb_1.marshall)({ pk: pkFor(cognitoSub), sk: "meta" }),
|
|
122
|
+
}));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
exports.ClaimsCache = ClaimsCache;
|
|
126
|
+
/**
|
|
127
|
+
* Convenience constructor used by the Lambda handler. Reads the table name
|
|
128
|
+
* from `DYNAMODB_TABLE` and the region from `AWS_REGION`. Tests construct
|
|
129
|
+
* a `ClaimsCache` directly with a mock client.
|
|
130
|
+
*/
|
|
131
|
+
function createClaimsCacheFromEnv() {
|
|
132
|
+
const tableName = process.env.DYNAMODB_TABLE;
|
|
133
|
+
if (!tableName) {
|
|
134
|
+
throw new Error("DYNAMODB_TABLE env var is required for ClaimsCache");
|
|
135
|
+
}
|
|
136
|
+
const client = new client_dynamodb_1.DynamoDBClient({ region: process.env.AWS_REGION });
|
|
137
|
+
return new ClaimsCache(client, tableName);
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=claims-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claims-cache.js","sourceRoot":"","sources":["../../../src/lib/auth/claims-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,7 +11,13 @@ export interface CognitoJwtClaims {
|
|
|
11
11
|
username: string;
|
|
12
12
|
email?: string;
|
|
13
13
|
"custom:userId"?: string;
|
|
14
|
+
/** Pre-T3 legacy claim — single global role. */
|
|
14
15
|
"custom:role"?: string;
|
|
16
|
+
/** T3+ global UserRole claim. */
|
|
17
|
+
"custom:globalRole"?: string;
|
|
18
|
+
"custom:activeTenantId"?: string;
|
|
19
|
+
"custom:tenantSlug"?: string;
|
|
20
|
+
"custom:tenantRole"?: string;
|
|
15
21
|
"custom:handle"?: string;
|
|
16
22
|
"custom:dataRegion"?: string;
|
|
17
23
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cognito-jwt.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/cognito-jwt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA2BH,4DAA4D;AAC5D,wBAAgB,aAAa,SAG5B;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAU/E;AAED,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAG3E"}
|
|
1
|
+
{"version":3,"file":"cognito-jwt.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/cognito-jwt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA2BH,4DAA4D;AAC5D,wBAAgB,aAAa,SAG5B;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gDAAgD;IAChD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iCAAiC;IACjC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAU/E;AAED,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAG3E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cognito-jwt.js","sourceRoot":"","sources":["../../../src/lib/auth/cognito-jwt.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AA4BH,sCAGC;
|
|
1
|
+
{"version":3,"file":"cognito-jwt.js","sourceRoot":"","sources":["../../../src/lib/auth/cognito-jwt.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AA4BH,sCAGC;AAkBD,4CAUC;AAED,gDAGC;AA9DD,mDAAoD;AAEpD,IAAI,QAAQ,GAAwD,IAAI,CAAC;AACzE,IAAI,WAAW,GAAG,CAAC,CAAC;AACpB,MAAM,mBAAmB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW;AAE5D,SAAS,WAAW;IAClB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,kEAAkE;IAClE,IAAI,CAAC,QAAQ,IAAI,CAAC,GAAG,GAAG,WAAW,GAAG,mBAAmB,CAAC,EAAE,CAAC;QAC3D,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;QACpD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;QACnD,IAAI,CAAC,UAAU,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;QAChF,CAAC;QACD,QAAQ,GAAG,mCAAkB,CAAC,MAAM,CAAC;YACnC,UAAU;YACV,QAAQ,EAAE,IAAI;YACd,QAAQ;SACT,CAAC,CAAC;QACH,WAAW,GAAG,GAAG,CAAC;IACpB,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,4DAA4D;AAC5D,SAAgB,aAAa;IAC3B,QAAQ,GAAG,IAAI,CAAC;IAChB,WAAW,GAAG,CAAC,CAAC;AAClB,CAAC;AAkBM,KAAK,UAAU,gBAAgB,CAAC,KAAa;IAClD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAClD,OAAO,OAAsC,CAAC;IAChD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,gFAAgF;QAChF,aAAa,EAAE,CAAC;QAChB,MAAM,OAAO,GAAG,MAAM,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAClD,OAAO,OAAsC,CAAC;IAChD,CAAC;AACH,CAAC;AAED,SAAgB,kBAAkB,CAAC,UAAyB;IAC1D,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IACpD,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds the Cognito Hosted UI OAuth2 authorization URL for federated sign-in.
|
|
3
|
+
*
|
|
4
|
+
* The IdP name in Cognito follows the convention `tenant-{cuid}` (using the
|
|
5
|
+
* full tenant cuid, truncated to 25 chars to fit Cognito's 32-char provider-
|
|
6
|
+
* name quota). Sign-in discovery routes by the same convention, so the value
|
|
7
|
+
* passed in is what T5 provisioned.
|
|
8
|
+
*
|
|
9
|
+
* All URL parameters are server-derived; callers supply only the Prisma-loaded
|
|
10
|
+
* cognitoIdpName — no arbitrary IdP names accepted from request input.
|
|
11
|
+
*/
|
|
12
|
+
export { cognitoIdpName } from "../tenant/idp-name";
|
|
13
|
+
export interface IdpRedirectConfig {
|
|
14
|
+
hostedUiDomain: string;
|
|
15
|
+
clientId: string;
|
|
16
|
+
redirectUri: string;
|
|
17
|
+
}
|
|
18
|
+
export interface IdpRedirectParams {
|
|
19
|
+
cognitoIdpName: string;
|
|
20
|
+
tenantSlug: string;
|
|
21
|
+
}
|
|
22
|
+
export interface IdpRedirectResult {
|
|
23
|
+
idpRedirect: string;
|
|
24
|
+
tenantSlug: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Builds the Cognito Hosted UI authorization URL.
|
|
28
|
+
*
|
|
29
|
+
* Scope is always `openid email profile` — no caller-supplied scope to prevent
|
|
30
|
+
* privilege escalation via scope injection.
|
|
31
|
+
*/
|
|
32
|
+
export declare function buildIdpRedirectUrl(config: IdpRedirectConfig, params: IdpRedirectParams): string;
|
|
33
|
+
/**
|
|
34
|
+
* Reads IdP redirect config from the environment.
|
|
35
|
+
* Env vars read here are defined in src/env.ts and must come from there —
|
|
36
|
+
* no direct process.env access outside buildEnv().
|
|
37
|
+
*/
|
|
38
|
+
export declare function getIdpRedirectConfig(env: {
|
|
39
|
+
COGNITO_HOSTED_UI_DOMAIN?: string;
|
|
40
|
+
COGNITO_APP_CLIENT_ID?: string;
|
|
41
|
+
COGNITO_REDIRECT_URI?: string;
|
|
42
|
+
}): IdpRedirectConfig;
|
|
43
|
+
//# sourceMappingURL=idp-redirect-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"idp-redirect-builder.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/idp-redirect-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,iBAAiB,EACzB,MAAM,EAAE,iBAAiB,GACxB,MAAM,CAUR;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE;IACxC,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B,GAAG,iBAAiB,CAMpB"}
|