@augmenting-integrations/auth 6.0.0 → 8.0.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.
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ "use client";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+ var tenant_exports = {};
31
+ __export(tenant_exports, {
32
+ TENANT_GLOBAL_KEY: () => import_tenant_types2.TENANT_GLOBAL_KEY,
33
+ TenantProvider: () => TenantProvider,
34
+ useTenant: () => useTenant
35
+ });
36
+ module.exports = __toCommonJS(tenant_exports);
37
+ var React = __toESM(require("react"));
38
+ var import_tenant_types = require("../tenant-types.js");
39
+ var import_tenant_types2 = require("../tenant-types.js");
40
+ const TenantContext = React.createContext(null);
41
+ function TenantProvider({
42
+ tenant,
43
+ children
44
+ }) {
45
+ return React.createElement(TenantContext.Provider, { value: tenant }, children);
46
+ }
47
+ function useTenant() {
48
+ const ctx = React.useContext(TenantContext);
49
+ if (ctx) return ctx;
50
+ if (typeof window !== "undefined") {
51
+ const fromGlobal = window[import_tenant_types.TENANT_GLOBAL_KEY];
52
+ if (fromGlobal) return fromGlobal;
53
+ }
54
+ throw new Error(
55
+ "useTenant() called outside <TenantProvider> and before <TenantBootScript /> ran. Mount both in the root layout."
56
+ );
57
+ }
58
+ // Annotate the CommonJS export names for ESM import in node:
59
+ 0 && (module.exports = {
60
+ TENANT_GLOBAL_KEY,
61
+ TenantProvider,
62
+ useTenant
63
+ });
64
+ //# sourceMappingURL=tenant.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/client/tenant.ts"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { TENANT_GLOBAL_KEY, type TenantPublicConfig } from \"../tenant-types.js\";\n\n// =============================================================================\n// <TenantProvider> + useTenant()\n//\n// Single source of tenant truth on the client. Rendered server-side as part\n// of the root layout; reads the same TenantPublicConfig passed to\n// <TenantBootScript />. The Context value flows through SSR, so server\n// components rendered as children + every client component can call\n// useTenant() without worrying about hydration order.\n//\n// We also accept window.__TENANT__ as a fallback for non-React widgets and\n// for the rare case of a client component rendered outside the Provider\n// tree (a defensive read).\n// =============================================================================\n\nconst TenantContext = React.createContext<TenantPublicConfig | null>(null);\n\nexport function TenantProvider({\n tenant,\n children,\n}: {\n tenant: TenantPublicConfig;\n children: React.ReactNode;\n}) {\n return React.createElement(TenantContext.Provider, { value: tenant }, children);\n}\n\nexport function useTenant(): TenantPublicConfig {\n const ctx = React.useContext(TenantContext);\n if (ctx) return ctx;\n // Defensive fallback: a non-Provider client widget. Only works after\n // <TenantBootScript /> has run.\n if (typeof window !== \"undefined\") {\n const fromGlobal = window[TENANT_GLOBAL_KEY];\n if (fromGlobal) return fromGlobal;\n }\n throw new Error(\n \"useTenant() called outside <TenantProvider> and before <TenantBootScript /> ran. Mount both in the root layout.\",\n );\n}\n\nexport {\n TENANT_GLOBAL_KEY,\n type TenantPublicConfig,\n type TenantRole,\n} from \"../tenant-types.js\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,YAAuB;AACvB,0BAA2D;AA0C3D,IAAAA,uBAIO;AA9BP,MAAM,gBAAgB,MAAM,cAAyC,IAAI;AAElE,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AACF,GAGG;AACD,SAAO,MAAM,cAAc,cAAc,UAAU,EAAE,OAAO,OAAO,GAAG,QAAQ;AAChF;AAEO,SAAS,YAAgC;AAC9C,QAAM,MAAM,MAAM,WAAW,aAAa;AAC1C,MAAI,IAAK,QAAO;AAGhB,MAAI,OAAO,WAAW,aAAa;AACjC,UAAM,aAAa,OAAO,qCAAiB;AAC3C,QAAI,WAAY,QAAO;AAAA,EACzB;AACA,QAAM,IAAI;AAAA,IACR;AAAA,EACF;AACF;","names":["import_tenant_types"]}
@@ -0,0 +1,9 @@
1
+ import * as React from "react";
2
+ import { type TenantPublicConfig } from "../tenant-types.js";
3
+ export declare function TenantProvider({ tenant, children, }: {
4
+ tenant: TenantPublicConfig;
5
+ children: React.ReactNode;
6
+ }): React.FunctionComponentElement<React.ProviderProps<TenantPublicConfig | null>>;
7
+ export declare function useTenant(): TenantPublicConfig;
8
+ export { TENANT_GLOBAL_KEY, type TenantPublicConfig, type TenantRole, } from "../tenant-types.js";
9
+ //# sourceMappingURL=tenant.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant.d.ts","sourceRoot":"","sources":["../../src/client/tenant.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAqB,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAkBhF,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,QAAQ,GACT,EAAE;IACD,MAAM,EAAE,kBAAkB,CAAC;IAC3B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,kFAEA;AAED,wBAAgB,SAAS,IAAI,kBAAkB,CAY9C;AAED,OAAO,EACL,iBAAiB,EACjB,KAAK,kBAAkB,EACvB,KAAK,UAAU,GAChB,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,30 @@
1
+ "use client";
2
+ import * as React from "react";
3
+ import { TENANT_GLOBAL_KEY } from "../tenant-types.js";
4
+ const TenantContext = React.createContext(null);
5
+ function TenantProvider({
6
+ tenant,
7
+ children
8
+ }) {
9
+ return React.createElement(TenantContext.Provider, { value: tenant }, children);
10
+ }
11
+ function useTenant() {
12
+ const ctx = React.useContext(TenantContext);
13
+ if (ctx) return ctx;
14
+ if (typeof window !== "undefined") {
15
+ const fromGlobal = window[TENANT_GLOBAL_KEY];
16
+ if (fromGlobal) return fromGlobal;
17
+ }
18
+ throw new Error(
19
+ "useTenant() called outside <TenantProvider> and before <TenantBootScript /> ran. Mount both in the root layout."
20
+ );
21
+ }
22
+ import {
23
+ TENANT_GLOBAL_KEY as TENANT_GLOBAL_KEY2
24
+ } from "../tenant-types.js";
25
+ export {
26
+ TENANT_GLOBAL_KEY2 as TENANT_GLOBAL_KEY,
27
+ TenantProvider,
28
+ useTenant
29
+ };
30
+ //# sourceMappingURL=tenant.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/client/tenant.ts"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { TENANT_GLOBAL_KEY, type TenantPublicConfig } from \"../tenant-types.js\";\n\n// =============================================================================\n// <TenantProvider> + useTenant()\n//\n// Single source of tenant truth on the client. Rendered server-side as part\n// of the root layout; reads the same TenantPublicConfig passed to\n// <TenantBootScript />. The Context value flows through SSR, so server\n// components rendered as children + every client component can call\n// useTenant() without worrying about hydration order.\n//\n// We also accept window.__TENANT__ as a fallback for non-React widgets and\n// for the rare case of a client component rendered outside the Provider\n// tree (a defensive read).\n// =============================================================================\n\nconst TenantContext = React.createContext<TenantPublicConfig | null>(null);\n\nexport function TenantProvider({\n tenant,\n children,\n}: {\n tenant: TenantPublicConfig;\n children: React.ReactNode;\n}) {\n return React.createElement(TenantContext.Provider, { value: tenant }, children);\n}\n\nexport function useTenant(): TenantPublicConfig {\n const ctx = React.useContext(TenantContext);\n if (ctx) return ctx;\n // Defensive fallback: a non-Provider client widget. Only works after\n // <TenantBootScript /> has run.\n if (typeof window !== \"undefined\") {\n const fromGlobal = window[TENANT_GLOBAL_KEY];\n if (fromGlobal) return fromGlobal;\n }\n throw new Error(\n \"useTenant() called outside <TenantProvider> and before <TenantBootScript /> ran. Mount both in the root layout.\",\n );\n}\n\nexport {\n TENANT_GLOBAL_KEY,\n type TenantPublicConfig,\n type TenantRole,\n} from \"../tenant-types.js\";\n"],"mappings":";AAEA,YAAY,WAAW;AACvB,SAAS,yBAAkD;AAgB3D,MAAM,gBAAgB,MAAM,cAAyC,IAAI;AAElE,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AACF,GAGG;AACD,SAAO,MAAM,cAAc,cAAc,UAAU,EAAE,OAAO,OAAO,GAAG,QAAQ;AAChF;AAEO,SAAS,YAAgC;AAC9C,QAAM,MAAM,MAAM,WAAW,aAAa;AAC1C,MAAI,IAAK,QAAO;AAGhB,MAAI,OAAO,WAAW,aAAa;AACjC,UAAM,aAAa,OAAO,iBAAiB;AAC3C,QAAI,WAAY,QAAO;AAAA,EACzB;AACA,QAAM,IAAI;AAAA,IACR;AAAA,EACF;AACF;AAEA;AAAA,EACE,qBAAAA;AAAA,OAGK;","names":["TENANT_GLOBAL_KEY"]}
package/dist/client.cjs CHANGED
@@ -21,11 +21,14 @@ __export(client_exports, {
21
21
  AppUserProvider: () => import_AppUserProvider.AppUserProvider,
22
22
  ImpersonationBanner: () => import_ImpersonationBanner.ImpersonationBanner,
23
23
  SignOutButton: () => import_SignOutButton.SignOutButton,
24
+ TENANT_GLOBAL_KEY: () => import_tenant.TENANT_GLOBAL_KEY,
25
+ TenantProvider: () => import_tenant.TenantProvider,
24
26
  UserMenu: () => import_UserMenu.UserMenu,
25
27
  useAppUser: () => import_AppUserProvider.useAppUser,
26
28
  useDbAppUser: () => import_AppUserProvider.useDbAppUser,
27
29
  useImpersonation: () => import_use_impersonation.useImpersonation,
28
- useRole: () => import_AppUserProvider.useRole
30
+ useRole: () => import_AppUserProvider.useRole,
31
+ useTenant: () => import_tenant.useTenant
29
32
  });
30
33
  module.exports = __toCommonJS(client_exports);
31
34
  var import_AppUserProvider = require("./client/AppUserProvider.js");
@@ -33,15 +36,19 @@ var import_UserMenu = require("./client/UserMenu.js");
33
36
  var import_SignOutButton = require("./client/SignOutButton.js");
34
37
  var import_ImpersonationBanner = require("./client/ImpersonationBanner.js");
35
38
  var import_use_impersonation = require("./client/use-impersonation.js");
39
+ var import_tenant = require("./client/tenant.js");
36
40
  // Annotate the CommonJS export names for ESM import in node:
37
41
  0 && (module.exports = {
38
42
  AppUserProvider,
39
43
  ImpersonationBanner,
40
44
  SignOutButton,
45
+ TENANT_GLOBAL_KEY,
46
+ TenantProvider,
41
47
  UserMenu,
42
48
  useAppUser,
43
49
  useDbAppUser,
44
50
  useImpersonation,
45
- useRole
51
+ useRole,
52
+ useTenant
46
53
  });
47
54
  //# sourceMappingURL=client.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client.ts"],"sourcesContent":["export {\n AppUserProvider,\n useAppUser,\n useDbAppUser,\n useRole,\n type AppUserState,\n type DbAppUser,\n type SessionAppUser,\n} from \"./client/AppUserProvider.js\";\nexport { UserMenu } from \"./client/UserMenu.js\";\nexport { SignOutButton } from \"./client/SignOutButton.js\";\nexport { ImpersonationBanner } from \"./client/ImpersonationBanner.js\";\nexport {\n useImpersonation,\n type EffectiveUser,\n type ImpersonatedBy,\n type MeResponse,\n} from \"./client/use-impersonation.js\";\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,6BAQO;AACP,sBAAyB;AACzB,2BAA8B;AAC9B,iCAAoC;AACpC,+BAKO;","names":[]}
1
+ {"version":3,"sources":["../src/client.ts"],"sourcesContent":["export {\n AppUserProvider,\n useAppUser,\n useDbAppUser,\n useRole,\n type AppUserState,\n type DbAppUser,\n type SessionAppUser,\n} from \"./client/AppUserProvider.js\";\nexport { UserMenu } from \"./client/UserMenu.js\";\nexport { SignOutButton } from \"./client/SignOutButton.js\";\nexport { ImpersonationBanner } from \"./client/ImpersonationBanner.js\";\nexport {\n useImpersonation,\n type EffectiveUser,\n type ImpersonatedBy,\n type MeResponse,\n} from \"./client/use-impersonation.js\";\nexport {\n TenantProvider,\n useTenant,\n TENANT_GLOBAL_KEY,\n type TenantPublicConfig,\n type TenantRole,\n} from \"./client/tenant.js\";\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,6BAQO;AACP,sBAAyB;AACzB,2BAA8B;AAC9B,iCAAoC;AACpC,+BAKO;AACP,oBAMO;","names":[]}
package/dist/client.d.ts CHANGED
@@ -3,4 +3,5 @@ export { UserMenu } from "./client/UserMenu.js";
3
3
  export { SignOutButton } from "./client/SignOutButton.js";
4
4
  export { ImpersonationBanner } from "./client/ImpersonationBanner.js";
5
5
  export { useImpersonation, type EffectiveUser, type ImpersonatedBy, type MeResponse, } from "./client/use-impersonation.js";
6
+ export { TenantProvider, useTenant, TENANT_GLOBAL_KEY, type TenantPublicConfig, type TenantRole, } from "./client/tenant.js";
6
7
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,UAAU,EACV,YAAY,EACZ,OAAO,EACP,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,cAAc,GACpB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EACL,gBAAgB,EAChB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,UAAU,GAChB,MAAM,+BAA+B,CAAC"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,UAAU,EACV,YAAY,EACZ,OAAO,EACP,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,cAAc,GACpB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EACL,gBAAgB,EAChB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,UAAU,GAChB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,cAAc,EACd,SAAS,EACT,iBAAiB,EACjB,KAAK,kBAAkB,EACvB,KAAK,UAAU,GAChB,MAAM,oBAAoB,CAAC"}
package/dist/client.js CHANGED
@@ -10,14 +10,22 @@ import { ImpersonationBanner } from "./client/ImpersonationBanner.js";
10
10
  import {
11
11
  useImpersonation
12
12
  } from "./client/use-impersonation.js";
13
+ import {
14
+ TenantProvider,
15
+ useTenant,
16
+ TENANT_GLOBAL_KEY
17
+ } from "./client/tenant.js";
13
18
  export {
14
19
  AppUserProvider,
15
20
  ImpersonationBanner,
16
21
  SignOutButton,
22
+ TENANT_GLOBAL_KEY,
23
+ TenantProvider,
17
24
  UserMenu,
18
25
  useAppUser,
19
26
  useDbAppUser,
20
27
  useImpersonation,
21
- useRole
28
+ useRole,
29
+ useTenant
22
30
  };
23
31
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client.ts"],"sourcesContent":["export {\n AppUserProvider,\n useAppUser,\n useDbAppUser,\n useRole,\n type AppUserState,\n type DbAppUser,\n type SessionAppUser,\n} from \"./client/AppUserProvider.js\";\nexport { UserMenu } from \"./client/UserMenu.js\";\nexport { SignOutButton } from \"./client/SignOutButton.js\";\nexport { ImpersonationBanner } from \"./client/ImpersonationBanner.js\";\nexport {\n useImpersonation,\n type EffectiveUser,\n type ImpersonatedBy,\n type MeResponse,\n} from \"./client/use-impersonation.js\";\n"],"mappings":"AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AACP,SAAS,gBAAgB;AACzB,SAAS,qBAAqB;AAC9B,SAAS,2BAA2B;AACpC;AAAA,EACE;AAAA,OAIK;","names":[]}
1
+ {"version":3,"sources":["../src/client.ts"],"sourcesContent":["export {\n AppUserProvider,\n useAppUser,\n useDbAppUser,\n useRole,\n type AppUserState,\n type DbAppUser,\n type SessionAppUser,\n} from \"./client/AppUserProvider.js\";\nexport { UserMenu } from \"./client/UserMenu.js\";\nexport { SignOutButton } from \"./client/SignOutButton.js\";\nexport { ImpersonationBanner } from \"./client/ImpersonationBanner.js\";\nexport {\n useImpersonation,\n type EffectiveUser,\n type ImpersonatedBy,\n type MeResponse,\n} from \"./client/use-impersonation.js\";\nexport {\n TenantProvider,\n useTenant,\n TENANT_GLOBAL_KEY,\n type TenantPublicConfig,\n type TenantRole,\n} from \"./client/tenant.js\";\n"],"mappings":"AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AACP,SAAS,gBAAgB;AACzB,SAAS,qBAAqB;AAC9B,SAAS,2BAA2B;AACpC;AAAA,EACE;AAAA,OAIK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAGK;","names":[]}
@@ -1,4 +1,5 @@
1
1
  import { type DefaultSession, type Session } from "next-auth";
2
+ import type { TenantServerConfig } from "../tenant-types.js";
2
3
  declare module "next-auth" {
3
4
  interface Session {
4
5
  user: {
@@ -10,47 +11,33 @@ declare module "next-auth" {
10
11
  }
11
12
  }
12
13
  export type CreateAuthOptions = {
13
- /** Path prefixes that require an authenticated session. */
14
- authedRoutePrefixes: string[];
15
14
  /**
16
- * Page to redirect to when an unauthed user hits a gated route.
17
- * If omitted, derived automatically from appDomain + allowedParentDomain:
18
- * apex app gets `/login`; subdomain apps get `https://<apex>/login`.
15
+ * Full tenant configuration. Provides apex/cookieDomain/parentDomain/
16
+ * appDomain/role + cognito client id + issuer + allowed admin emails.
17
+ * Load via `loadTenantConfig()` from `@augmenting-integrations/tenant/server`.
19
18
  */
20
- signInPage?: string;
19
+ tenant: TenantServerConfig;
20
+ /** Path prefixes that require an authenticated session. */
21
+ authedRoutePrefixes: string[];
21
22
  /**
22
- * Cookie Domain attribute. In subdomain ecosystems, set to the parent
23
- * (e.g. `.agency.aillc.link`). Default: process.env.AUTH_COOKIE_DOMAIN.
24
- * In dev (NODE_ENV !== "production") this is ignored — cookies stay
25
- * host-only so per-port localhost apps don't collide.
23
+ * JWT signing secret. Caller fetches from Secrets Manager via
24
+ * `getSecret(tenant.authSecretArn)` and passes the resolved value here.
25
+ * The library doesn't bundle AWS SDK reads itself.
26
26
  */
27
- cookieDomain?: string;
27
+ authSecret: string;
28
28
  /**
29
- * The parent domain that all subdomain apps share (e.g.
30
- * `.agency.aillc.link`). The redirect callback uses this to allow
31
- * post-login redirects back to any subdomain of the parent (apex or
32
- * `<sub>.agency.aillc.link`). Default: process.env.AUTH_ALLOWED_PARENT_DOMAIN.
29
+ * Cognito OAuth client secret. Apex apps only -- spokes never run the
30
+ * OAuth dance. Caller fetches from Secrets Manager via
31
+ * `getSecret(tenant.authCognitoSecretArn)`.
33
32
  */
34
- allowedParentDomain?: string;
33
+ cognitoClientSecret?: string;
35
34
  /**
36
- * This app's full FQDN (e.g. `agency.aillc.link` for the apex app, or
37
- * `leads.agency.aillc.link` for a subdomain app). Used to derive the
38
- * default signInPage. Default: process.env.APP_DOMAIN.
35
+ * Override the auto-derived sign-in page (rarely needed). Default:
36
+ * apex apps get `/login`; spoke apps get `https://<apex>/login`.
39
37
  */
40
- appDomain?: string;
38
+ signInPage?: string;
41
39
  /** Override prod/dev detection. Default reads NODE_ENV. */
42
40
  isProd?: boolean;
43
- /**
44
- * The JWT signing secret. Default: process.env.AUTH_SECRET.
45
- * In prod, pass this from a runtime fetch (Secrets Manager) to keep the
46
- * secret out of Lambda env vars and to support rotation without redeploy.
47
- */
48
- secret?: string;
49
- cognito?: {
50
- clientId?: string;
51
- clientSecret?: string;
52
- issuer?: string;
53
- };
54
41
  };
55
42
  export declare class AuthError extends Error {
56
43
  code: "unauthenticated" | "forbidden";
@@ -1 +1 @@
1
- {"version":3,"file":"createAuth.d.ts","sourceRoot":"","sources":["../../src/server/createAuth.ts"],"names":[],"mappings":"AAkBA,OAAiB,EACf,KAAK,cAAc,EAEnB,KAAK,OAAO,EACb,MAAM,WAAW,CAAC;AAQnB,OAAO,QAAQ,WAAW,CAAC;IACzB,UAAU,OAAO;QACf,IAAI,EAAE;YACJ,MAAM,EAAE,MAAM,EAAE,CAAC;SAClB,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;KAC5B;IACD,UAAU,IAAI;QACZ,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;KACnB;CACF;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,2DAA2D;IAC3D,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE;QACR,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;CACH,CAAC;AAIF,qBAAa,SAAU,SAAQ,KAAK;IACf,IAAI,EAAE,iBAAiB,GAAG,WAAW;gBAArC,IAAI,EAAE,iBAAiB,GAAG,WAAW;CAIzD;AAID,2EAA2E;AAC3E,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,EAAE,CAE3E;AAED,+CAA+C;AAC/C,wBAAgB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAInF;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,EACnC,GAAG,KAAK,EAAE,MAAM,EAAE,GACjB,IAAI,CAKN;AAkFD,wBAAgB,UAAU,CAAC,IAAI,EAAE,iBAAiB,sCA+IjD;AAED,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"createAuth.d.ts","sourceRoot":"","sources":["../../src/server/createAuth.ts"],"names":[],"mappings":"AAkBA,OAAiB,EACf,KAAK,cAAc,EAEnB,KAAK,OAAO,EACb,MAAM,WAAW,CAAC;AAGnB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAM7D,OAAO,QAAQ,WAAW,CAAC;IACzB,UAAU,OAAO;QACf,IAAI,EAAE;YACJ,MAAM,EAAE,MAAM,EAAE,CAAC;SAClB,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;KAC5B;IACD,UAAU,IAAI;QACZ,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;KACnB;CACF;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;;OAIG;IACH,MAAM,EAAE,kBAAkB,CAAC;IAC3B,2DAA2D;IAC3D,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B;;;;OAIG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAIF,qBAAa,SAAU,SAAQ,KAAK;IACf,IAAI,EAAE,iBAAiB,GAAG,WAAW;gBAArC,IAAI,EAAE,iBAAiB,GAAG,WAAW;CAIzD;AAID,2EAA2E;AAC3E,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,EAAE,CAE3E;AAED,+CAA+C;AAC/C,wBAAgB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAInF;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,EACnC,GAAG,KAAK,EAAE,MAAM,EAAE,GACjB,IAAI,CAKN;AA+BD,wBAAgB,UAAU,CAAC,IAAI,EAAE,iBAAiB,sCAmIjD;AAED,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,26 @@
1
+ import "server-only";
2
+ import * as React from "react";
3
+ import { type TenantPublicConfig, type TenantRole, type TenantServerConfig } from "../tenant-types.js";
4
+ export type LoadOptions = {
5
+ role: TenantRole;
6
+ /**
7
+ * Override env reads with explicit values (useful for tests).
8
+ */
9
+ overrides?: Partial<TenantServerConfig>;
10
+ };
11
+ /**
12
+ * Read tenant configuration from process.env with optional overrides.
13
+ * Throws a single Error listing every missing required field.
14
+ */
15
+ export declare function loadTenantConfig(opts: LoadOptions): TenantServerConfig;
16
+ /**
17
+ * Reduce a TenantServerConfig to the public-safe subset. Strips every
18
+ * secret-arn so the result is safe to ship to the browser via
19
+ * <TenantBootScript />.
20
+ */
21
+ export declare function publicSubset(config: TenantServerConfig): TenantPublicConfig;
22
+ export declare function TenantBootScript({ config }: {
23
+ config: TenantPublicConfig;
24
+ }): React.DetailedReactHTMLElement<Record<string, unknown>, HTMLElement>;
25
+ export { TENANT_GLOBAL_KEY, type TenantPublicConfig, type TenantServerConfig, type TenantRole, } from "../tenant-types.js";
26
+ //# sourceMappingURL=tenant.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant.d.ts","sourceRoot":"","sources":["../../src/server/tenant.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAC;AACrB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,UAAU,EACf,KAAK,kBAAkB,EACxB,MAAM,oBAAoB,CAAC;AAoB5B,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,UAAU,CAAC;IACjB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;CACzC,CAAC;AAEF;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,WAAW,GAAG,kBAAkB,CAwDtE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,kBAAkB,GAAG,kBAAkB,CAU3E;AAeD,wBAAgB,gBAAgB,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,kBAAkB,CAAA;CAAE,wEAM1E;AAED,OAAO,EACL,iBAAiB,EACjB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,UAAU,GAChB,MAAM,oBAAoB,CAAC"}
package/dist/server.cjs CHANGED
@@ -33,11 +33,15 @@ __export(server_exports, {
33
33
  AuthError: () => AuthError,
34
34
  IMPERSONATE_COOKIE_NAME: () => IMPERSONATE_COOKIE_NAME,
35
35
  IMPERSONATE_TTL_SECONDS: () => IMPERSONATE_TTL_SECONDS,
36
+ TENANT_GLOBAL_KEY: () => TENANT_GLOBAL_KEY,
37
+ TenantBootScript: () => TenantBootScript,
36
38
  createAuth: () => createAuth,
37
39
  createGetOrCreateAppUser: () => createGetOrCreateAppUser,
38
40
  getUserGroups: () => getUserGroups,
39
41
  hasGroup: () => hasGroup,
42
+ loadTenantConfig: () => loadTenantConfig,
40
43
  mintImpersonationToken: () => mintImpersonationToken,
44
+ publicSubset: () => publicSubset,
41
45
  requireGroup: () => requireGroup,
42
46
  verifyImpersonationToken: () => verifyImpersonationToken
43
47
  });
@@ -69,37 +73,11 @@ function requireGroup(session, ...names) {
69
73
  const ok = names.some((n) => hasGroup(session, n));
70
74
  if (!ok) throw new AuthError("forbidden");
71
75
  }
72
- function validateProdEnv(args) {
73
- if (!args.isProd) return;
74
- if (process.env.NEXT_PHASE === "phase-production-build") return;
75
- if (!process.env.AWS_LAMBDA_FUNCTION_NAME) return;
76
- const missing = [];
77
- if (!args.secret) missing.push("AUTH_SECRET");
78
- if (!args.cognitoClientId) missing.push("AUTH_COGNITO_ID");
79
- if (!args.cognitoClientSecret) missing.push("AUTH_COGNITO_SECRET");
80
- if (!args.cognitoIssuer) missing.push("AUTH_COGNITO_ISSUER");
81
- const hasAny = !!(args.cookieDomain || args.allowedParentDomain || args.appDomain);
82
- if (hasAny) {
83
- if (!args.cookieDomain) missing.push("AUTH_COOKIE_DOMAIN");
84
- if (!args.allowedParentDomain) missing.push("AUTH_ALLOWED_PARENT_DOMAIN");
85
- if (!args.appDomain) missing.push("APP_DOMAIN");
86
- }
87
- if (missing.length > 0) {
88
- throw new Error(
89
- `[@augmenting-integrations/auth] Missing required prod env vars: ${missing.join(
90
- ", "
91
- )}. Provide via createAuth() opts or process.env.`
92
- );
93
- }
94
- }
95
- function buildRedirectCallback(allowedParentDomain) {
76
+ function buildRedirectCallback(parentDomain) {
96
77
  return ({ url, baseUrl }) => {
97
78
  try {
98
79
  const target = new URL(url, baseUrl);
99
- if (!allowedParentDomain) {
100
- return target.origin === new URL(baseUrl).origin ? target.toString() : baseUrl;
101
- }
102
- const apex = allowedParentDomain.replace(/^\./, "").toLowerCase();
80
+ const apex = parentDomain.replace(/^\./, "").toLowerCase();
103
81
  const host = target.hostname.toLowerCase();
104
82
  const ok = host === apex || host.endsWith(`.${apex}`);
105
83
  return ok ? target.toString() : baseUrl;
@@ -110,38 +88,31 @@ function buildRedirectCallback(allowedParentDomain) {
110
88
  }
111
89
  function deriveSignInPage(args) {
112
90
  if (args.signInPage) return args.signInPage;
113
- if (args.appDomain && args.allowedParentDomain) {
114
- const apex = args.allowedParentDomain.replace(/^\./, "");
115
- return args.appDomain === apex ? "/login" : `https://${apex}/login`;
116
- }
117
- return "/login";
91
+ return args.appDomain === args.apex ? "/login" : `https://${args.apex}/login`;
118
92
  }
119
93
  function createAuth(opts) {
94
+ const { tenant, authSecret, cognitoClientSecret } = opts;
120
95
  const isProd = opts.isProd ?? process.env.NODE_ENV === "production";
121
- const cookieDomain = isProd ? opts.cookieDomain ?? process.env.AUTH_COOKIE_DOMAIN : void 0;
122
- const allowedParentDomain = opts.allowedParentDomain ?? process.env.AUTH_ALLOWED_PARENT_DOMAIN;
123
- const appDomain = opts.appDomain ?? process.env.APP_DOMAIN;
124
- const SECRET = opts.secret ?? process.env.AUTH_SECRET ?? (isProd ? void 0 : "dev-only-fallback-not-for-prod");
125
- const cognitoClientId = opts.cognito?.clientId ?? process.env.AUTH_COGNITO_ID;
126
- const cognitoClientSecret = opts.cognito?.clientSecret ?? process.env.AUTH_COGNITO_SECRET;
127
- const cognitoIssuer = opts.cognito?.issuer ?? process.env.AUTH_COGNITO_ISSUER;
128
- validateProdEnv({
129
- isProd,
130
- cookieDomain,
131
- allowedParentDomain,
132
- appDomain,
133
- secret: SECRET,
134
- cognitoClientId,
135
- cognitoClientSecret,
136
- cognitoIssuer
137
- });
96
+ const cookieDomain = isProd ? tenant.cookieDomain : void 0;
97
+ if (tenant.role === "apex") {
98
+ if (!tenant.cognitoClientId || !tenant.cognitoIssuer) {
99
+ throw new Error(
100
+ "createAuth: tenant.role='apex' requires cognitoClientId + cognitoIssuer. Check loadTenantConfig() inputs."
101
+ );
102
+ }
103
+ if (isProd && !cognitoClientSecret) {
104
+ throw new Error(
105
+ "createAuth: tenant.role='apex' in production requires cognitoClientSecret. Fetch via getSecret(tenant.authCognitoSecretArn) and pass it in."
106
+ );
107
+ }
108
+ }
138
109
  const signInPage = deriveSignInPage({
139
110
  signInPage: opts.signInPage,
140
- appDomain,
141
- allowedParentDomain
111
+ appDomain: tenant.appDomain,
112
+ apex: tenant.apex
142
113
  });
143
114
  const config = {
144
- secret: SECRET,
115
+ secret: authSecret,
145
116
  cookies: cookieDomain ? {
146
117
  sessionToken: {
147
118
  name: "authjs.session-token",
@@ -156,9 +127,9 @@ function createAuth(opts) {
156
127
  } : void 0,
157
128
  providers: isProd ? [
158
129
  (0, import_cognito.default)({
159
- clientId: cognitoClientId,
130
+ clientId: tenant.cognitoClientId,
160
131
  clientSecret: cognitoClientSecret,
161
- issuer: cognitoIssuer
132
+ issuer: tenant.cognitoIssuer
162
133
  })
163
134
  ] : [
164
135
  (0, import_credentials.default)({
@@ -226,7 +197,7 @@ function createAuth(opts) {
226
197
  }
227
198
  return true;
228
199
  },
229
- redirect: buildRedirectCallback(allowedParentDomain)
200
+ redirect: buildRedirectCallback(tenant.parentDomain)
230
201
  },
231
202
  pages: { signIn: signInPage },
232
203
  trustHost: true
@@ -369,16 +340,99 @@ function createGetOrCreateAppUser(opts) {
369
340
  });
370
341
  };
371
342
  }
343
+
344
+ // src/server/tenant.ts
345
+ var import_server_only3 = require("server-only");
346
+ var React = __toESM(require("react"));
347
+
348
+ // src/tenant-types.ts
349
+ var TENANT_GLOBAL_KEY = "__TENANT__";
350
+
351
+ // src/server/tenant.ts
352
+ function loadTenantConfig(opts) {
353
+ const env = process.env;
354
+ const o = opts.overrides ?? {};
355
+ const draft = {
356
+ role: opts.role,
357
+ apex: o.apex ?? env.APEX_DOMAIN,
358
+ cookieDomain: o.cookieDomain ?? env.AUTH_COOKIE_DOMAIN,
359
+ parentDomain: o.parentDomain ?? env.AUTH_ALLOWED_PARENT_DOMAIN,
360
+ region: o.region ?? env.AWS_REGION ?? "us-east-1",
361
+ appSlug: o.appSlug ?? env.APP_SLUG,
362
+ appDomain: o.appDomain ?? env.APP_DOMAIN,
363
+ authSecretArn: o.authSecretArn ?? env.AUTH_SECRET_ARN,
364
+ registryTable: o.registryTable ?? env.REGISTRY_TABLE,
365
+ authCognitoSecretArn: o.authCognitoSecretArn ?? env.AUTH_COGNITO_SECRET_ARN,
366
+ cognitoIssuer: o.cognitoIssuer ?? env.AUTH_COGNITO_ISSUER,
367
+ cognitoClientId: o.cognitoClientId ?? env.AUTH_COGNITO_CLIENT_ID,
368
+ adminEmails: o.adminEmails ?? env.ADMIN_EMAILS,
369
+ dbSecretArn: o.dbSecretArn ?? env.DB_SECRET_ARN,
370
+ dbHost: o.dbHost ?? env.DB_HOST,
371
+ dbName: o.dbName ?? env.DB_NAME,
372
+ stripeSecretArn: o.stripeSecretArn ?? env.STRIPE_SECRET_ARN,
373
+ stripeWebhookSecretArn: o.stripeWebhookSecretArn ?? env.STRIPE_WEBHOOK_SECRET_ARN
374
+ };
375
+ if (opts.role === "apex" && !draft.appDomain) {
376
+ draft.appDomain = draft.apex;
377
+ }
378
+ const required = [
379
+ { key: "apex", env: "APEX_DOMAIN" },
380
+ { key: "cookieDomain", env: "AUTH_COOKIE_DOMAIN" },
381
+ { key: "parentDomain", env: "AUTH_ALLOWED_PARENT_DOMAIN" },
382
+ { key: "authSecretArn", env: "AUTH_SECRET_ARN" },
383
+ { key: "registryTable", env: "REGISTRY_TABLE" },
384
+ { key: "appDomain", env: "APP_DOMAIN" }
385
+ ];
386
+ if (opts.role === "apex") {
387
+ required.push(
388
+ { key: "authCognitoSecretArn", env: "AUTH_COGNITO_SECRET_ARN" },
389
+ { key: "cognitoIssuer", env: "AUTH_COGNITO_ISSUER" },
390
+ { key: "cognitoClientId", env: "AUTH_COGNITO_CLIENT_ID" }
391
+ );
392
+ } else {
393
+ required.push({ key: "appSlug", env: "APP_SLUG" });
394
+ }
395
+ const missing = required.filter((r) => !draft[r.key]).map((r) => r.env);
396
+ if (missing.length > 0) {
397
+ throw new Error(
398
+ `loadTenantConfig(${opts.role}): missing required env vars: ${missing.join(", ")}`
399
+ );
400
+ }
401
+ return draft;
402
+ }
403
+ function publicSubset(config) {
404
+ return {
405
+ apex: config.apex,
406
+ cookieDomain: config.cookieDomain,
407
+ parentDomain: config.parentDomain,
408
+ region: config.region,
409
+ appSlug: config.appSlug,
410
+ appDomain: config.appDomain,
411
+ role: config.role
412
+ };
413
+ }
414
+ var INNER_HTML_PROP = "dangerouslySetInnerHTML";
415
+ function TenantBootScript({ config }) {
416
+ const payload = JSON.stringify(config).replace(/</g, "\\u003c");
417
+ const body = `window.${TENANT_GLOBAL_KEY}=${payload};`;
418
+ const props = {};
419
+ props[INNER_HTML_PROP] = { __html: body };
420
+ return React.createElement("script", props);
421
+ }
372
422
  // Annotate the CommonJS export names for ESM import in node:
373
423
  0 && (module.exports = {
374
424
  AuthError,
375
425
  IMPERSONATE_COOKIE_NAME,
376
426
  IMPERSONATE_TTL_SECONDS,
427
+ TENANT_GLOBAL_KEY,
428
+ TenantBootScript,
377
429
  createAuth,
378
430
  createGetOrCreateAppUser,
379
431
  getUserGroups,
380
432
  hasGroup,
433
+ loadTenantConfig,
381
434
  mintImpersonationToken,
435
+ publicSubset,
382
436
  requireGroup,
383
437
  verifyImpersonationToken
384
438
  });