@aiquants/auth-core 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/index.d.mts +54 -1
- package/dist/index.d.ts +54 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,6 +14,8 @@ Inside this monorepo it is already wired as a pnpm workspace package:
|
|
|
14
14
|
|
|
15
15
|
- `AuthenticationPayload`, `GoogleProfileBase`, `SessionProfile`, `MyGoogleProfile` — the session/profile types re-homed from the app's `@coji/remix-auth-google` module augmentation so non-auth code can import them without pulling in remix-auth.
|
|
16
16
|
- `emailDomainAllowlist(allowedEmails, allowedDomains)` → `(email) => boolean` — trim+lowercase normalized, logical OR of exact-email and domain match, fail-closed (throws when both lists empty). `parseAllowlistCsv(raw)` parses a comma-separated env value.
|
|
17
|
+
Domain patterns accept **both** `example.com` and `@example.com` (a leading `@` is stripped), because env values are usually written bare while admin UIs tend to teach the `@`-prefixed form. Matching is exact on the host — `example.com` never grants `evil-example.com` or `sub.example.com`.
|
|
18
|
+
- `AuthUser` / `AuthGroup` / `AuthGroupMember` / `AuthAllowlistEntry` — entity types for a user/group administration surface (see `@aiquants/auth-react-router/admin`). `AuthAllowlistEntry.readOnly` marks rows sourced from an immutable provider (e.g. an env var) so the UI can render them as non-deletable.
|
|
17
19
|
- `defaultAuthMessages` / `AuthMessages` / `resolveAuthMessages(over?)` — the Japanese login-page error strings, overridable per app.
|
|
18
20
|
|
|
19
21
|
## Session profile shape (byte-compatible contract)
|
package/dist/index.d.mts
CHANGED
|
@@ -98,5 +98,58 @@ type SessionProfile = GoogleProfileBase & AuthenticationPayload;
|
|
|
98
98
|
type MyGoogleProfile = GoogleProfileBase & {
|
|
99
99
|
photo: string;
|
|
100
100
|
} & AuthenticationPayload;
|
|
101
|
+
/**
|
|
102
|
+
* Managed user entity in the authentication system.
|
|
103
|
+
* 認証システムで管理されるユーザーエンティティ。
|
|
104
|
+
*/
|
|
105
|
+
type AuthUser = {
|
|
106
|
+
id: number;
|
|
107
|
+
email: string;
|
|
108
|
+
displayName: string;
|
|
109
|
+
photo?: string;
|
|
110
|
+
isActive: boolean;
|
|
111
|
+
createdAt?: string;
|
|
112
|
+
updatedAt?: string;
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* User group entity for aggregating users into teams or departments.
|
|
116
|
+
* ユーザーをチームや部署単位で集約するユーザーグループエンティティ。
|
|
117
|
+
*/
|
|
118
|
+
type AuthGroup = {
|
|
119
|
+
id: number;
|
|
120
|
+
groupKey: string;
|
|
121
|
+
name: string;
|
|
122
|
+
description?: string;
|
|
123
|
+
isActive: boolean;
|
|
124
|
+
createdAt?: string;
|
|
125
|
+
updatedAt?: string;
|
|
126
|
+
};
|
|
127
|
+
/**
|
|
128
|
+
* Membership link between a user and a user group.
|
|
129
|
+
* ユーザーとユーザーグループの所属紐付けエンティティ。
|
|
130
|
+
*/
|
|
131
|
+
type AuthGroupMember = {
|
|
132
|
+
id: number;
|
|
133
|
+
groupId: number;
|
|
134
|
+
userId: number;
|
|
135
|
+
createdAt?: string;
|
|
136
|
+
};
|
|
137
|
+
/**
|
|
138
|
+
* Allowlist entry defining permitted emails or domains for authentication.
|
|
139
|
+
* 認証を許可するメールアドレスまたはドメインのアロワリストエントリ。
|
|
140
|
+
*/
|
|
141
|
+
type AuthAllowlistEntry = {
|
|
142
|
+
id: number;
|
|
143
|
+
pattern: string;
|
|
144
|
+
type: "email" | "domain";
|
|
145
|
+
description?: string;
|
|
146
|
+
createdAt?: string;
|
|
147
|
+
/**
|
|
148
|
+
* True when the entry comes from an immutable source (e.g. an environment variable) and
|
|
149
|
+
* therefore cannot be edited or deleted through the admin UI.
|
|
150
|
+
* 環境変数など変更不能な供給元に由来し、管理 UI から編集・削除できないエントリの目印。
|
|
151
|
+
*/
|
|
152
|
+
readOnly?: boolean;
|
|
153
|
+
};
|
|
101
154
|
|
|
102
|
-
export { type AuthMessages, type AuthenticationPayload, type GoogleProfileBase, type MyGoogleProfile, type SessionProfile, defaultAuthMessages, emailDomainAllowlist, parseAllowlistCsv, resolveAuthMessages };
|
|
155
|
+
export { type AuthAllowlistEntry, type AuthGroup, type AuthGroupMember, type AuthMessages, type AuthUser, type AuthenticationPayload, type GoogleProfileBase, type MyGoogleProfile, type SessionProfile, defaultAuthMessages, emailDomainAllowlist, parseAllowlistCsv, resolveAuthMessages };
|
package/dist/index.d.ts
CHANGED
|
@@ -98,5 +98,58 @@ type SessionProfile = GoogleProfileBase & AuthenticationPayload;
|
|
|
98
98
|
type MyGoogleProfile = GoogleProfileBase & {
|
|
99
99
|
photo: string;
|
|
100
100
|
} & AuthenticationPayload;
|
|
101
|
+
/**
|
|
102
|
+
* Managed user entity in the authentication system.
|
|
103
|
+
* 認証システムで管理されるユーザーエンティティ。
|
|
104
|
+
*/
|
|
105
|
+
type AuthUser = {
|
|
106
|
+
id: number;
|
|
107
|
+
email: string;
|
|
108
|
+
displayName: string;
|
|
109
|
+
photo?: string;
|
|
110
|
+
isActive: boolean;
|
|
111
|
+
createdAt?: string;
|
|
112
|
+
updatedAt?: string;
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* User group entity for aggregating users into teams or departments.
|
|
116
|
+
* ユーザーをチームや部署単位で集約するユーザーグループエンティティ。
|
|
117
|
+
*/
|
|
118
|
+
type AuthGroup = {
|
|
119
|
+
id: number;
|
|
120
|
+
groupKey: string;
|
|
121
|
+
name: string;
|
|
122
|
+
description?: string;
|
|
123
|
+
isActive: boolean;
|
|
124
|
+
createdAt?: string;
|
|
125
|
+
updatedAt?: string;
|
|
126
|
+
};
|
|
127
|
+
/**
|
|
128
|
+
* Membership link between a user and a user group.
|
|
129
|
+
* ユーザーとユーザーグループの所属紐付けエンティティ。
|
|
130
|
+
*/
|
|
131
|
+
type AuthGroupMember = {
|
|
132
|
+
id: number;
|
|
133
|
+
groupId: number;
|
|
134
|
+
userId: number;
|
|
135
|
+
createdAt?: string;
|
|
136
|
+
};
|
|
137
|
+
/**
|
|
138
|
+
* Allowlist entry defining permitted emails or domains for authentication.
|
|
139
|
+
* 認証を許可するメールアドレスまたはドメインのアロワリストエントリ。
|
|
140
|
+
*/
|
|
141
|
+
type AuthAllowlistEntry = {
|
|
142
|
+
id: number;
|
|
143
|
+
pattern: string;
|
|
144
|
+
type: "email" | "domain";
|
|
145
|
+
description?: string;
|
|
146
|
+
createdAt?: string;
|
|
147
|
+
/**
|
|
148
|
+
* True when the entry comes from an immutable source (e.g. an environment variable) and
|
|
149
|
+
* therefore cannot be edited or deleted through the admin UI.
|
|
150
|
+
* 環境変数など変更不能な供給元に由来し、管理 UI から編集・削除できないエントリの目印。
|
|
151
|
+
*/
|
|
152
|
+
readOnly?: boolean;
|
|
153
|
+
};
|
|
101
154
|
|
|
102
|
-
export { type AuthMessages, type AuthenticationPayload, type GoogleProfileBase, type MyGoogleProfile, type SessionProfile, defaultAuthMessages, emailDomainAllowlist, parseAllowlistCsv, resolveAuthMessages };
|
|
155
|
+
export { type AuthAllowlistEntry, type AuthGroup, type AuthGroupMember, type AuthMessages, type AuthUser, type AuthenticationPayload, type GoogleProfileBase, type MyGoogleProfile, type SessionProfile, defaultAuthMessages, emailDomainAllowlist, parseAllowlistCsv, resolveAuthMessages };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var l=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var g=Object.getOwnPropertyNames;var u=Object.prototype.hasOwnProperty;var m=(e,t)=>{for(var n in t)l(e,n,{get:t[n],enumerable:!0})},f=(e,t,n,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of g(t))!u.call(e,o)&&o!==n&&l(e,o,{get:()=>t[o],enumerable:!(s=d(t,o))||s.enumerable});return e};var c=e=>f(l({},"__esModule",{value:!0}),e);var x={};m(x,{defaultAuthMessages:()=>a,emailDomainAllowlist:()=>p,parseAllowlistCsv:()=>w,resolveAuthMessages:()=>h});module.exports=c(x);var p=(e=[],t=[])=>{let n=new Set(e.map(o=>o.trim().toLowerCase()).filter(Boolean)),s=new Set(t.map(o=>o.trim().toLowerCase()).filter(Boolean));if(n.size===0&&s.size===0)throw new Error("At least one of allowedEmails or allowedDomains must be set");return o=>{let r=(o??"").trim().toLowerCase();if(r==="")return!1;if(n.has(r))return!0;let i=r.lastIndexOf("@");return i>=0&&s.has(r.slice(i+1))}},w=e=>e?e.split(",").map(t=>t.trim()).filter(Boolean):[];var a={emailNotVerified:"\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u304C\u78BA\u8A8D\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002",googleFailed:"Google\u3067\u306E\u8A8D\u8A3C\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002",backendFailed:"\u30D0\u30C3\u30AF\u30A8\u30F3\u30C9\u3067\u306E\u8A8D\u8A3C\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002",notAllowed:"\u3053\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u3078\u306E\u30A2\u30AF\u30BB\u30B9\u306F\u8A31\u53EF\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002",backendUnreachable:"\u30D0\u30C3\u30AF\u30A8\u30F3\u30C9\u30B5\u30FC\u30D3\u30B9\u306B\u63A5\u7D9A\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u6642\u9593\u3092\u304A\u3044\u3066\u518D\u5EA6\u304A\u8A66\u3057\u304F\u3060\u3055\u3044\u3002",unexpected:"\u8A8D\u8A3C\u4E2D\u306B\u4E88\u671F\u305B\u306C\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002"},h=e=>e?{...a,...e}:a;0&&(module.exports={defaultAuthMessages,emailDomainAllowlist,parseAllowlistCsv,resolveAuthMessages});
|
|
1
|
+
"use strict";var l=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var g=Object.getOwnPropertyNames;var u=Object.prototype.hasOwnProperty;var m=(e,t)=>{for(var n in t)l(e,n,{get:t[n],enumerable:!0})},f=(e,t,n,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of g(t))!u.call(e,o)&&o!==n&&l(e,o,{get:()=>t[o],enumerable:!(s=d(t,o))||s.enumerable});return e};var c=e=>f(l({},"__esModule",{value:!0}),e);var x={};m(x,{defaultAuthMessages:()=>a,emailDomainAllowlist:()=>p,parseAllowlistCsv:()=>w,resolveAuthMessages:()=>h});module.exports=c(x);var p=(e=[],t=[])=>{let n=new Set(e.map(o=>o.trim().toLowerCase()).filter(Boolean)),s=new Set(t.map(o=>o.trim().toLowerCase().replace(/^@+/,"")).filter(Boolean));if(n.size===0&&s.size===0)throw new Error("At least one of allowedEmails or allowedDomains must be set");return o=>{let r=(o??"").trim().toLowerCase();if(r==="")return!1;if(n.has(r))return!0;let i=r.lastIndexOf("@");return i>=0&&s.has(r.slice(i+1))}},w=e=>e?e.split(",").map(t=>t.trim()).filter(Boolean):[];var a={emailNotVerified:"\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u304C\u78BA\u8A8D\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002",googleFailed:"Google\u3067\u306E\u8A8D\u8A3C\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002",backendFailed:"\u30D0\u30C3\u30AF\u30A8\u30F3\u30C9\u3067\u306E\u8A8D\u8A3C\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002",notAllowed:"\u3053\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u3078\u306E\u30A2\u30AF\u30BB\u30B9\u306F\u8A31\u53EF\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002",backendUnreachable:"\u30D0\u30C3\u30AF\u30A8\u30F3\u30C9\u30B5\u30FC\u30D3\u30B9\u306B\u63A5\u7D9A\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u6642\u9593\u3092\u304A\u3044\u3066\u518D\u5EA6\u304A\u8A66\u3057\u304F\u3060\u3055\u3044\u3002",unexpected:"\u8A8D\u8A3C\u4E2D\u306B\u4E88\u671F\u305B\u306C\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002"},h=e=>e?{...a,...e}:a;0&&(module.exports={defaultAuthMessages,emailDomainAllowlist,parseAllowlistCsv,resolveAuthMessages});
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/allowlist.ts","../src/messages.ts"],"sourcesContent":["/**\n * @aiquants/auth-core — transport-agnostic auth types, allowlist policy, and messages.\n * @aiquants/auth-core — トランスポート非依存の認証型・allowlist ポリシー・メッセージ。\n */\nexport * from \"./allowlist\"\nexport * from \"./messages\"\nexport * from \"./types\"\n","/**\n * Email / domain allowlist policy (transport-agnostic).\n * メール / ドメインの allowlist ポリシー (トランスポート非依存)。\n *\n * §8-1 (統一セマンティクス): 照合は trim + lowercase で正規化する。原本の TS 側 login gate は\n * 大文字小文字を区別していたが、Python 側 (access_policy) の正規化に合わせて一元化する。\n * これは許可を「緩める」方向の変更で、大文字混じりの許可メールが確実に通るようになる。\n */\n\n/**\n * Builds an `isEmailAllowed(email)` predicate from allowed emails and domains.\n * 許可メール / 許可ドメインから `isEmailAllowed(email)` 述語を生成する。\n *\n * @throws when both lists are empty after normalization (fail-closed configuration guard).\n * 正規化後に両リストが空なら throw (fail-closed の設定ガード)。\n */\nexport const emailDomainAllowlist = (allowedEmails: readonly string[] = [], allowedDomains: readonly string[] = []): ((email: string | null | undefined) => boolean) => {\n const emails = new Set(allowedEmails.map((e) => e.trim().toLowerCase()).filter(Boolean))\n const domains = new Set(allowedDomains.map((d) => d.trim().toLowerCase()).filter(Boolean))\n if (emails.size === 0 && domains.size === 0) {\n throw new Error(\"At least one of allowedEmails or allowedDomains must be set\")\n }\n return (email: string | null | undefined): boolean => {\n const normalized = (email ?? \"\").trim().toLowerCase()\n if (normalized === \"\") return false\n if (emails.has(normalized)) return true\n // ドメイン一致: 最後の \"@\" 以降を取り出して判定する\n const at = normalized.lastIndexOf(\"@\")\n return at >= 0 && domains.has(normalized.slice(at + 1))\n }\n}\n\n/**\n * Parses a comma-separated allowlist env value into a trimmed, non-empty string list.\n * カンマ区切りの allowlist 環境変数値を、トリム済みかつ空要素を除いた文字列配列へ変換する。\n */\nexport const parseAllowlistCsv = (raw: string | null | undefined): string[] => {\n if (!raw) return []\n return raw\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean)\n}\n","/**\n * Localizable auth error messages shown on the login page (`/auth/login?error=...`).\n * ログインページに表示する認証エラーメッセージ (上書き可能)。\n *\n * 既定は原本 (auth.server.ts の GoogleStrategy verify コールバック) の日本語文言と一致させる。\n */\n\nexport type AuthMessages = {\n /** メール未確認 (email_verified === false)。 */\n emailNotVerified: string\n /** Google 側での認証失敗 (トークン/プロフィール欠落)。 */\n googleFailed: string\n /** バックエンド検証が false を返した。 */\n backendFailed: string\n /** allowlist で許可されていないユーザー。 */\n notAllowed: string\n /** バックエンドサービスへ到達できない (getaddrinfo ENOTFOUND 等)。 */\n backendUnreachable: string\n /** その他の予期せぬエラー。 */\n unexpected: string\n}\n\n/** パッケージ既定の日本語メッセージ (原本と一致)。 */\nexport const defaultAuthMessages: AuthMessages = {\n emailNotVerified: \"メールアドレスが確認されていません。\",\n googleFailed: \"Googleでの認証に失敗しました。\",\n backendFailed: \"バックエンドでの認証に失敗しました。\",\n notAllowed: \"このアプリケーションへのアクセスは許可されていません。\",\n backendUnreachable: \"バックエンドサービスに接続できませんでした。時間をおいて再度お試しください。\",\n unexpected: \"認証中に予期せぬエラーが発生しました。\",\n}\n\n/**\n * Shallow-merges a partial override over the default messages.\n * 部分上書きを既定メッセージへ浅くマージする。\n */\nexport const resolveAuthMessages = (over?: Partial<AuthMessages>): AuthMessages => (over ? { ...defaultAuthMessages, ...over } : defaultAuthMessages)\n"],"mappings":"yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,yBAAAE,EAAA,yBAAAC,EAAA,sBAAAC,EAAA,wBAAAC,IAAA,eAAAC,EAAAN,GCgBO,IAAMO,EAAuB,CAACC,EAAmC,CAAC,EAAGC,EAAoC,CAAC,IAAuD,CACpK,IAAMC,EAAS,IAAI,IAAIF,EAAc,IAAKG,GAAMA,EAAE,KAAK,EAAE,YAAY,CAAC,EAAE,OAAO,OAAO,CAAC,
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/allowlist.ts","../src/messages.ts"],"sourcesContent":["/**\n * @aiquants/auth-core — transport-agnostic auth types, allowlist policy, and messages.\n * @aiquants/auth-core — トランスポート非依存の認証型・allowlist ポリシー・メッセージ。\n */\nexport * from \"./allowlist\"\nexport * from \"./messages\"\nexport * from \"./types\"\n","/**\n * Email / domain allowlist policy (transport-agnostic).\n * メール / ドメインの allowlist ポリシー (トランスポート非依存)。\n *\n * §8-1 (統一セマンティクス): 照合は trim + lowercase で正規化する。原本の TS 側 login gate は\n * 大文字小文字を区別していたが、Python 側 (access_policy) の正規化に合わせて一元化する。\n * これは許可を「緩める」方向の変更で、大文字混じりの許可メールが確実に通るようになる。\n */\n\n/**\n * Builds an `isEmailAllowed(email)` predicate from allowed emails and domains.\n * 許可メール / 許可ドメインから `isEmailAllowed(email)` 述語を生成する。\n *\n * @throws when both lists are empty after normalization (fail-closed configuration guard).\n * 正規化後に両リストが空なら throw (fail-closed の設定ガード)。\n */\nexport const emailDomainAllowlist = (allowedEmails: readonly string[] = [], allowedDomains: readonly string[] = []): ((email: string | null | undefined) => boolean) => {\n const emails = new Set(allowedEmails.map((e) => e.trim().toLowerCase()).filter(Boolean))\n // ドメインは \"example.com\" と \"@example.com\" の双方を受け付ける。管理 UI は後者の形式を案内し、\n // 環境変数は前者で書かれているため、正規化しないと UI から登録したドメインが一切一致しない。\n const domains = new Set(allowedDomains.map((d) => d.trim().toLowerCase().replace(/^@+/, \"\")).filter(Boolean))\n if (emails.size === 0 && domains.size === 0) {\n throw new Error(\"At least one of allowedEmails or allowedDomains must be set\")\n }\n return (email: string | null | undefined): boolean => {\n const normalized = (email ?? \"\").trim().toLowerCase()\n if (normalized === \"\") return false\n if (emails.has(normalized)) return true\n // ドメイン一致: 最後の \"@\" 以降を取り出して判定する\n const at = normalized.lastIndexOf(\"@\")\n return at >= 0 && domains.has(normalized.slice(at + 1))\n }\n}\n\n/**\n * Parses a comma-separated allowlist env value into a trimmed, non-empty string list.\n * カンマ区切りの allowlist 環境変数値を、トリム済みかつ空要素を除いた文字列配列へ変換する。\n */\nexport const parseAllowlistCsv = (raw: string | null | undefined): string[] => {\n if (!raw) return []\n return raw\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean)\n}\n","/**\n * Localizable auth error messages shown on the login page (`/auth/login?error=...`).\n * ログインページに表示する認証エラーメッセージ (上書き可能)。\n *\n * 既定は原本 (auth.server.ts の GoogleStrategy verify コールバック) の日本語文言と一致させる。\n */\n\nexport type AuthMessages = {\n /** メール未確認 (email_verified === false)。 */\n emailNotVerified: string\n /** Google 側での認証失敗 (トークン/プロフィール欠落)。 */\n googleFailed: string\n /** バックエンド検証が false を返した。 */\n backendFailed: string\n /** allowlist で許可されていないユーザー。 */\n notAllowed: string\n /** バックエンドサービスへ到達できない (getaddrinfo ENOTFOUND 等)。 */\n backendUnreachable: string\n /** その他の予期せぬエラー。 */\n unexpected: string\n}\n\n/** パッケージ既定の日本語メッセージ (原本と一致)。 */\nexport const defaultAuthMessages: AuthMessages = {\n emailNotVerified: \"メールアドレスが確認されていません。\",\n googleFailed: \"Googleでの認証に失敗しました。\",\n backendFailed: \"バックエンドでの認証に失敗しました。\",\n notAllowed: \"このアプリケーションへのアクセスは許可されていません。\",\n backendUnreachable: \"バックエンドサービスに接続できませんでした。時間をおいて再度お試しください。\",\n unexpected: \"認証中に予期せぬエラーが発生しました。\",\n}\n\n/**\n * Shallow-merges a partial override over the default messages.\n * 部分上書きを既定メッセージへ浅くマージする。\n */\nexport const resolveAuthMessages = (over?: Partial<AuthMessages>): AuthMessages => (over ? { ...defaultAuthMessages, ...over } : defaultAuthMessages)\n"],"mappings":"yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,yBAAAE,EAAA,yBAAAC,EAAA,sBAAAC,EAAA,wBAAAC,IAAA,eAAAC,EAAAN,GCgBO,IAAMO,EAAuB,CAACC,EAAmC,CAAC,EAAGC,EAAoC,CAAC,IAAuD,CACpK,IAAMC,EAAS,IAAI,IAAIF,EAAc,IAAKG,GAAMA,EAAE,KAAK,EAAE,YAAY,CAAC,EAAE,OAAO,OAAO,CAAC,EAGjFC,EAAU,IAAI,IAAIH,EAAe,IAAKI,GAAMA,EAAE,KAAK,EAAE,YAAY,EAAE,QAAQ,MAAO,EAAE,CAAC,EAAE,OAAO,OAAO,CAAC,EAC5G,GAAIH,EAAO,OAAS,GAAKE,EAAQ,OAAS,EACtC,MAAM,IAAI,MAAM,6DAA6D,EAEjF,OAAQE,GAA8C,CAClD,IAAMC,GAAcD,GAAS,IAAI,KAAK,EAAE,YAAY,EACpD,GAAIC,IAAe,GAAI,MAAO,GAC9B,GAAIL,EAAO,IAAIK,CAAU,EAAG,MAAO,GAEnC,IAAMC,EAAKD,EAAW,YAAY,GAAG,EACrC,OAAOC,GAAM,GAAKJ,EAAQ,IAAIG,EAAW,MAAMC,EAAK,CAAC,CAAC,CAC1D,CACJ,EAMaC,EAAqBC,GACzBA,EACEA,EACF,MAAM,GAAG,EACT,IAAKC,GAAMA,EAAE,KAAK,CAAC,EACnB,OAAO,OAAO,EAJF,CAAC,EChBf,IAAMC,EAAoC,CAC7C,iBAAkB,+GAClB,aAAc,iFACd,cAAe,+GACf,WAAY,qKACZ,mBAAoB,uOACpB,WAAY,oHAChB,EAMaC,EAAuBC,GAAgDA,EAAO,CAAE,GAAGF,EAAqB,GAAGE,CAAK,EAAIF","names":["index_exports","__export","defaultAuthMessages","emailDomainAllowlist","parseAllowlistCsv","resolveAuthMessages","__toCommonJS","emailDomainAllowlist","allowedEmails","allowedDomains","emails","e","domains","d","email","normalized","at","parseAllowlistCsv","raw","s","defaultAuthMessages","resolveAuthMessages","over"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var i=(e=[],n=[])=>{let s=new Set(e.map(t=>t.trim().toLowerCase()).filter(Boolean)),r=new Set(n.map(t=>t.trim().toLowerCase()).filter(Boolean));if(s.size===0&&r.size===0)throw new Error("At least one of allowedEmails or allowedDomains must be set");return t=>{let o=(t??"").trim().toLowerCase();if(o==="")return!1;if(s.has(o))return!0;let l=o.lastIndexOf("@");return l>=0&&r.has(o.slice(l+1))}},d=e=>e?e.split(",").map(n=>n.trim()).filter(Boolean):[];var a={emailNotVerified:"\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u304C\u78BA\u8A8D\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002",googleFailed:"Google\u3067\u306E\u8A8D\u8A3C\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002",backendFailed:"\u30D0\u30C3\u30AF\u30A8\u30F3\u30C9\u3067\u306E\u8A8D\u8A3C\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002",notAllowed:"\u3053\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u3078\u306E\u30A2\u30AF\u30BB\u30B9\u306F\u8A31\u53EF\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002",backendUnreachable:"\u30D0\u30C3\u30AF\u30A8\u30F3\u30C9\u30B5\u30FC\u30D3\u30B9\u306B\u63A5\u7D9A\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u6642\u9593\u3092\u304A\u3044\u3066\u518D\u5EA6\u304A\u8A66\u3057\u304F\u3060\u3055\u3044\u3002",unexpected:"\u8A8D\u8A3C\u4E2D\u306B\u4E88\u671F\u305B\u306C\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002"},u=e=>e?{...a,...e}:a;export{a as defaultAuthMessages,i as emailDomainAllowlist,d as parseAllowlistCsv,u as resolveAuthMessages};
|
|
1
|
+
var i=(e=[],n=[])=>{let s=new Set(e.map(t=>t.trim().toLowerCase()).filter(Boolean)),r=new Set(n.map(t=>t.trim().toLowerCase().replace(/^@+/,"")).filter(Boolean));if(s.size===0&&r.size===0)throw new Error("At least one of allowedEmails or allowedDomains must be set");return t=>{let o=(t??"").trim().toLowerCase();if(o==="")return!1;if(s.has(o))return!0;let l=o.lastIndexOf("@");return l>=0&&r.has(o.slice(l+1))}},d=e=>e?e.split(",").map(n=>n.trim()).filter(Boolean):[];var a={emailNotVerified:"\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u304C\u78BA\u8A8D\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002",googleFailed:"Google\u3067\u306E\u8A8D\u8A3C\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002",backendFailed:"\u30D0\u30C3\u30AF\u30A8\u30F3\u30C9\u3067\u306E\u8A8D\u8A3C\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002",notAllowed:"\u3053\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u3078\u306E\u30A2\u30AF\u30BB\u30B9\u306F\u8A31\u53EF\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002",backendUnreachable:"\u30D0\u30C3\u30AF\u30A8\u30F3\u30C9\u30B5\u30FC\u30D3\u30B9\u306B\u63A5\u7D9A\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u6642\u9593\u3092\u304A\u3044\u3066\u518D\u5EA6\u304A\u8A66\u3057\u304F\u3060\u3055\u3044\u3002",unexpected:"\u8A8D\u8A3C\u4E2D\u306B\u4E88\u671F\u305B\u306C\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002"},u=e=>e?{...a,...e}:a;export{a as defaultAuthMessages,i as emailDomainAllowlist,d as parseAllowlistCsv,u as resolveAuthMessages};
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/allowlist.ts","../src/messages.ts"],"sourcesContent":["/**\n * Email / domain allowlist policy (transport-agnostic).\n * メール / ドメインの allowlist ポリシー (トランスポート非依存)。\n *\n * §8-1 (統一セマンティクス): 照合は trim + lowercase で正規化する。原本の TS 側 login gate は\n * 大文字小文字を区別していたが、Python 側 (access_policy) の正規化に合わせて一元化する。\n * これは許可を「緩める」方向の変更で、大文字混じりの許可メールが確実に通るようになる。\n */\n\n/**\n * Builds an `isEmailAllowed(email)` predicate from allowed emails and domains.\n * 許可メール / 許可ドメインから `isEmailAllowed(email)` 述語を生成する。\n *\n * @throws when both lists are empty after normalization (fail-closed configuration guard).\n * 正規化後に両リストが空なら throw (fail-closed の設定ガード)。\n */\nexport const emailDomainAllowlist = (allowedEmails: readonly string[] = [], allowedDomains: readonly string[] = []): ((email: string | null | undefined) => boolean) => {\n const emails = new Set(allowedEmails.map((e) => e.trim().toLowerCase()).filter(Boolean))\n const domains = new Set(allowedDomains.map((d) => d.trim().toLowerCase()).filter(Boolean))\n if (emails.size === 0 && domains.size === 0) {\n throw new Error(\"At least one of allowedEmails or allowedDomains must be set\")\n }\n return (email: string | null | undefined): boolean => {\n const normalized = (email ?? \"\").trim().toLowerCase()\n if (normalized === \"\") return false\n if (emails.has(normalized)) return true\n // ドメイン一致: 最後の \"@\" 以降を取り出して判定する\n const at = normalized.lastIndexOf(\"@\")\n return at >= 0 && domains.has(normalized.slice(at + 1))\n }\n}\n\n/**\n * Parses a comma-separated allowlist env value into a trimmed, non-empty string list.\n * カンマ区切りの allowlist 環境変数値を、トリム済みかつ空要素を除いた文字列配列へ変換する。\n */\nexport const parseAllowlistCsv = (raw: string | null | undefined): string[] => {\n if (!raw) return []\n return raw\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean)\n}\n","/**\n * Localizable auth error messages shown on the login page (`/auth/login?error=...`).\n * ログインページに表示する認証エラーメッセージ (上書き可能)。\n *\n * 既定は原本 (auth.server.ts の GoogleStrategy verify コールバック) の日本語文言と一致させる。\n */\n\nexport type AuthMessages = {\n /** メール未確認 (email_verified === false)。 */\n emailNotVerified: string\n /** Google 側での認証失敗 (トークン/プロフィール欠落)。 */\n googleFailed: string\n /** バックエンド検証が false を返した。 */\n backendFailed: string\n /** allowlist で許可されていないユーザー。 */\n notAllowed: string\n /** バックエンドサービスへ到達できない (getaddrinfo ENOTFOUND 等)。 */\n backendUnreachable: string\n /** その他の予期せぬエラー。 */\n unexpected: string\n}\n\n/** パッケージ既定の日本語メッセージ (原本と一致)。 */\nexport const defaultAuthMessages: AuthMessages = {\n emailNotVerified: \"メールアドレスが確認されていません。\",\n googleFailed: \"Googleでの認証に失敗しました。\",\n backendFailed: \"バックエンドでの認証に失敗しました。\",\n notAllowed: \"このアプリケーションへのアクセスは許可されていません。\",\n backendUnreachable: \"バックエンドサービスに接続できませんでした。時間をおいて再度お試しください。\",\n unexpected: \"認証中に予期せぬエラーが発生しました。\",\n}\n\n/**\n * Shallow-merges a partial override over the default messages.\n * 部分上書きを既定メッセージへ浅くマージする。\n */\nexport const resolveAuthMessages = (over?: Partial<AuthMessages>): AuthMessages => (over ? { ...defaultAuthMessages, ...over } : defaultAuthMessages)\n"],"mappings":"AAgBO,IAAMA,EAAuB,CAACC,EAAmC,CAAC,EAAGC,EAAoC,CAAC,IAAuD,CACpK,IAAMC,EAAS,IAAI,IAAIF,EAAc,IAAKG,GAAMA,EAAE,KAAK,EAAE,YAAY,CAAC,EAAE,OAAO,OAAO,CAAC,
|
|
1
|
+
{"version":3,"sources":["../src/allowlist.ts","../src/messages.ts"],"sourcesContent":["/**\n * Email / domain allowlist policy (transport-agnostic).\n * メール / ドメインの allowlist ポリシー (トランスポート非依存)。\n *\n * §8-1 (統一セマンティクス): 照合は trim + lowercase で正規化する。原本の TS 側 login gate は\n * 大文字小文字を区別していたが、Python 側 (access_policy) の正規化に合わせて一元化する。\n * これは許可を「緩める」方向の変更で、大文字混じりの許可メールが確実に通るようになる。\n */\n\n/**\n * Builds an `isEmailAllowed(email)` predicate from allowed emails and domains.\n * 許可メール / 許可ドメインから `isEmailAllowed(email)` 述語を生成する。\n *\n * @throws when both lists are empty after normalization (fail-closed configuration guard).\n * 正規化後に両リストが空なら throw (fail-closed の設定ガード)。\n */\nexport const emailDomainAllowlist = (allowedEmails: readonly string[] = [], allowedDomains: readonly string[] = []): ((email: string | null | undefined) => boolean) => {\n const emails = new Set(allowedEmails.map((e) => e.trim().toLowerCase()).filter(Boolean))\n // ドメインは \"example.com\" と \"@example.com\" の双方を受け付ける。管理 UI は後者の形式を案内し、\n // 環境変数は前者で書かれているため、正規化しないと UI から登録したドメインが一切一致しない。\n const domains = new Set(allowedDomains.map((d) => d.trim().toLowerCase().replace(/^@+/, \"\")).filter(Boolean))\n if (emails.size === 0 && domains.size === 0) {\n throw new Error(\"At least one of allowedEmails or allowedDomains must be set\")\n }\n return (email: string | null | undefined): boolean => {\n const normalized = (email ?? \"\").trim().toLowerCase()\n if (normalized === \"\") return false\n if (emails.has(normalized)) return true\n // ドメイン一致: 最後の \"@\" 以降を取り出して判定する\n const at = normalized.lastIndexOf(\"@\")\n return at >= 0 && domains.has(normalized.slice(at + 1))\n }\n}\n\n/**\n * Parses a comma-separated allowlist env value into a trimmed, non-empty string list.\n * カンマ区切りの allowlist 環境変数値を、トリム済みかつ空要素を除いた文字列配列へ変換する。\n */\nexport const parseAllowlistCsv = (raw: string | null | undefined): string[] => {\n if (!raw) return []\n return raw\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean)\n}\n","/**\n * Localizable auth error messages shown on the login page (`/auth/login?error=...`).\n * ログインページに表示する認証エラーメッセージ (上書き可能)。\n *\n * 既定は原本 (auth.server.ts の GoogleStrategy verify コールバック) の日本語文言と一致させる。\n */\n\nexport type AuthMessages = {\n /** メール未確認 (email_verified === false)。 */\n emailNotVerified: string\n /** Google 側での認証失敗 (トークン/プロフィール欠落)。 */\n googleFailed: string\n /** バックエンド検証が false を返した。 */\n backendFailed: string\n /** allowlist で許可されていないユーザー。 */\n notAllowed: string\n /** バックエンドサービスへ到達できない (getaddrinfo ENOTFOUND 等)。 */\n backendUnreachable: string\n /** その他の予期せぬエラー。 */\n unexpected: string\n}\n\n/** パッケージ既定の日本語メッセージ (原本と一致)。 */\nexport const defaultAuthMessages: AuthMessages = {\n emailNotVerified: \"メールアドレスが確認されていません。\",\n googleFailed: \"Googleでの認証に失敗しました。\",\n backendFailed: \"バックエンドでの認証に失敗しました。\",\n notAllowed: \"このアプリケーションへのアクセスは許可されていません。\",\n backendUnreachable: \"バックエンドサービスに接続できませんでした。時間をおいて再度お試しください。\",\n unexpected: \"認証中に予期せぬエラーが発生しました。\",\n}\n\n/**\n * Shallow-merges a partial override over the default messages.\n * 部分上書きを既定メッセージへ浅くマージする。\n */\nexport const resolveAuthMessages = (over?: Partial<AuthMessages>): AuthMessages => (over ? { ...defaultAuthMessages, ...over } : defaultAuthMessages)\n"],"mappings":"AAgBO,IAAMA,EAAuB,CAACC,EAAmC,CAAC,EAAGC,EAAoC,CAAC,IAAuD,CACpK,IAAMC,EAAS,IAAI,IAAIF,EAAc,IAAKG,GAAMA,EAAE,KAAK,EAAE,YAAY,CAAC,EAAE,OAAO,OAAO,CAAC,EAGjFC,EAAU,IAAI,IAAIH,EAAe,IAAKI,GAAMA,EAAE,KAAK,EAAE,YAAY,EAAE,QAAQ,MAAO,EAAE,CAAC,EAAE,OAAO,OAAO,CAAC,EAC5G,GAAIH,EAAO,OAAS,GAAKE,EAAQ,OAAS,EACtC,MAAM,IAAI,MAAM,6DAA6D,EAEjF,OAAQE,GAA8C,CAClD,IAAMC,GAAcD,GAAS,IAAI,KAAK,EAAE,YAAY,EACpD,GAAIC,IAAe,GAAI,MAAO,GAC9B,GAAIL,EAAO,IAAIK,CAAU,EAAG,MAAO,GAEnC,IAAMC,EAAKD,EAAW,YAAY,GAAG,EACrC,OAAOC,GAAM,GAAKJ,EAAQ,IAAIG,EAAW,MAAMC,EAAK,CAAC,CAAC,CAC1D,CACJ,EAMaC,EAAqBC,GACzBA,EACEA,EACF,MAAM,GAAG,EACT,IAAKC,GAAMA,EAAE,KAAK,CAAC,EACnB,OAAO,OAAO,EAJF,CAAC,EChBf,IAAMC,EAAoC,CAC7C,iBAAkB,+GAClB,aAAc,iFACd,cAAe,+GACf,WAAY,qKACZ,mBAAoB,uOACpB,WAAY,oHAChB,EAMaC,EAAuBC,GAAgDA,EAAO,CAAE,GAAGF,EAAqB,GAAGE,CAAK,EAAIF","names":["emailDomainAllowlist","allowedEmails","allowedDomains","emails","e","domains","d","email","normalized","at","parseAllowlistCsv","raw","s","defaultAuthMessages","resolveAuthMessages","over"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aiquants/auth-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Transport-agnostic auth core: shared session/profile types, email/domain allowlist policy, and localizable auth error messages. No framework or provider SDK dependency.",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"main": "dist/index.js",
|