@nebutra/identity 2.0.0 → 3.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.
@@ -1,37 +1,32 @@
1
1
 
2
- > @nebutra/identity@2.0.0 build /home/runner/work/Nebutra-Sailor/Nebutra-Sailor/packages/iam/identity
2
+ > @nebutra/identity@3.0.0 build /home/runner/work/Nebutra-Sailor/Nebutra-Sailor/packages/iam/identity
3
3
  > tsup
4
4
 
5
- CLI Building entry: src/index.ts, src/registry.ts, src/types.ts, src/adapters/authjs.ts, src/adapters/clerk.ts
5
+ CLI Building entry: src/index.ts, src/registry.ts, src/types.ts, src/adapters/nebutra.ts
6
6
  CLI Using tsconfig: tsconfig.json
7
7
  CLI tsup v8.5.1
8
8
  CLI Using tsup config: /home/runner/work/Nebutra-Sailor/Nebutra-Sailor/packages/iam/identity/tsup.config.ts
9
9
  CLI Target: es2022
10
10
  CLI Cleaning output folder
11
11
  ESM Build start
12
- ESM dist/index.js 480.00 B
13
- ESM dist/adapters/authjs.js 134.00 B
14
- ESM dist/registry.js 255.00 B
15
- ESM dist/chunk-DOCMMNRB.js 1.34 KB
16
- ESM dist/types.js 136.00 B
17
- ESM dist/chunk-MZKK4BRU.js 472.00 B
18
- ESM dist/chunk-ZERXN5CV.js 1.34 KB
19
- ESM dist/adapters/clerk.js 131.00 B
20
- ESM dist/chunk-QKUYKQO6.js 1018.00 B
21
- ESM dist/index.js.map 71.00 B
22
- ESM dist/adapters/authjs.js.map 71.00 B
23
- ESM dist/registry.js.map 71.00 B
24
- ESM dist/chunk-DOCMMNRB.js.map 3.24 KB
25
- ESM dist/types.js.map 71.00 B
26
- ESM dist/chunk-MZKK4BRU.js.map 1.22 KB
27
- ESM dist/chunk-ZERXN5CV.js.map 2.68 KB
28
- ESM dist/adapters/clerk.js.map 71.00 B
29
- ESM dist/chunk-QKUYKQO6.js.map 1.94 KB
30
- ESM ⚡️ Build success in 97ms
12
+ ESM dist/index.js 344.00 B
13
+ ESM dist/adapters/nebutra.js 137.00 B
14
+ ESM dist/registry.js 225.00 B
15
+ ESM dist/chunk-CAQ25QHX.js 415.00 B
16
+ ESM dist/types.js 136.00 B
17
+ ESM dist/chunk-VMSPQ5ZK.js 472.00 B
18
+ ESM dist/chunk-LMFYKNSW.js 851.00 B
19
+ ESM dist/index.js.map 71.00 B
20
+ ESM dist/adapters/nebutra.js.map 71.00 B
21
+ ESM dist/registry.js.map 71.00 B
22
+ ESM dist/chunk-CAQ25QHX.js.map 524.00 B
23
+ ESM dist/types.js.map 71.00 B
24
+ ESM dist/chunk-VMSPQ5ZK.js.map 1.21 KB
25
+ ESM dist/chunk-LMFYKNSW.js.map 2.51 KB
26
+ ESM ⚡️ Build success in 80ms
31
27
  DTS Build start
32
- DTS ⚡️ Build success in 28124ms
33
- DTS dist/index.d.ts 1.17 KB
34
- DTS dist/registry.d.ts 216.00 B
35
- DTS dist/adapters/authjs.d.ts 301.00 B
36
- DTS dist/adapters/clerk.d.ts 298.00 B
37
- DTS dist/types.d.ts 605.00 B
28
+ DTS ⚡️ Build success in 31675ms
29
+ DTS dist/index.d.ts 252.00 B
30
+ DTS dist/registry.d.ts 216.00 B
31
+ DTS dist/adapters/nebutra.d.ts 918.00 B
32
+ DTS dist/types.d.ts 596.00 B
@@ -1,4 +1,4 @@
1
1
 
2
- > @nebutra/identity@2.0.0 typecheck /home/runner/work/Nebutra-Sailor/Nebutra-Sailor/packages/iam/identity
2
+ > @nebutra/identity@3.0.0 typecheck /home/runner/work/Nebutra-Sailor/Nebutra-Sailor/packages/iam/identity
3
3
  > tsc --noEmit
4
4
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # @nebutra/identity
2
2
 
3
+ ## 3.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - [`6684e47`](https://github.com/Nebutra/Nebutra-Sailor/commit/6684e47930383dc572406c6f900827827375278b) Thanks [@TsekaLuk](https://github.com/TsekaLuk)! - One stack (ADR 2026-09-24 Sailor convergence, amended 2026-09-26). The
8
+ `@nebutra/*` packages now ship one provider per domain; everything else is
9
+ removed, not deprecated.
10
+ - `@nebutra/identity`: the Clerk and Auth.js adapters are gone; Better Auth is
11
+ the only identity source.
12
+ - `@nebutra/billing`: Polar and LemonSqueezy are gone. The card rail is Creem
13
+ (merchant of record) with WeChat Pay / Alipay for the mainland; Stripe stays
14
+ only to complete checkouts opened before the switch.
15
+ - `@nebutra/search`: Meilisearch, Typesense and Algolia are gone; search runs on
16
+ Postgres (pgvector + full-text).
17
+ - `@nebutra/permissions`: OpenFGA is gone; CASL is the engine.
18
+ - Also narrowed across the group: queue is QStash only (BullMQ/SQS removed),
19
+ notifications are built-in (Novu/Knock removed), webhooks are built-in (Svix
20
+ removed), uploads are S3-compatible (Vercel Blob removed), SMS is Twilio
21
+ Verify + Aliyun (Tencent removed), email is Resend (Nodemailer removed).
22
+
23
+ Migrating: drop the removed provider env vars, set the keys for the kept
24
+ provider, and run `nebutra status` to see what is live.
25
+
26
+ ### Patch Changes
27
+
28
+ - Updated dependencies []:
29
+ - @nebutra/contracts@3.0.0
30
+
3
31
  ## 2.0.0
4
32
 
5
33
  ### Patch Changes
package/README.md CHANGED
@@ -4,9 +4,18 @@ Provider-agnostic identity adapter layer — maps auth-provider-specific session
4
4
 
5
5
  ## Design Intent
6
6
 
7
- Nebutra supports multiple auth providers (Clerk, Auth.js, custom). Rather than leaking provider-specific types into application code, this package defines an `IdentityAdapter` interface and an `IdentityAdapterRegistry` that maps any provider's session data to the `CanonicalIdentity` schema from `@nebutra/contracts`. Application code always receives `CanonicalIdentity`; swapping auth providers requires only registering a new adapter.
8
-
9
- The Clerk adapter is the default production adapter. The Auth.js adapter provides a drop-in alternative. Both are tested against the same `CanonicalIdentity` schema.
7
+ This package defines an `IdentityAdapter` interface and an `IdentityAdapterRegistry` that maps a provider's session data to the `CanonicalIdentity` schema from `@nebutra/contracts`, so application code always receives `CanonicalIdentity` regardless of the upstream provider.
8
+
9
+ `@nebutra/auth` (Better Auth) is the kept, single production auth backend per
10
+ ADR 2026-09-24 (Sailor Convergence); the built-in `clerk` and `authjs`
11
+ adapters here are not that backend and are not currently wired to any caller
12
+ in this monorepo — they exist for a consumer that talks to Clerk or Auth.js
13
+ directly and needs to normalize its claims into the same canonical shape (for
14
+ example, a future integration point for `apps/sleptons`'s own direct Clerk
15
+ usage, which Nebutra keeps intentionally as its own product, stripped from
16
+ the template). Swapping which adapter a given consumer uses requires only
17
+ registering a new `IdentityAdapter`; none of this is a scaffold-time or
18
+ `create-sailor` choice.
10
19
 
11
20
  ## Usage
12
21
 
@@ -0,0 +1,30 @@
1
+ import { CanonicalIdentity } from '@nebutra/contracts';
2
+ import { IdentityAdapter } from '../types.js';
3
+
4
+ /**
5
+ * Nebutra Identity Adapter
6
+ *
7
+ * Maps oidc-provider / Nebutra-issued OIDC tokens to CanonicalIdentity.
8
+ * Used when Nebutra acts as both the IdP AND the resource server —
9
+ * i.e., when a Nebutra service receives an access token issued by
10
+ * the Nebutra IdP and needs to resolve the user identity.
11
+ */
12
+
13
+ interface NebutraOIDCClaims {
14
+ sub: string;
15
+ email?: string;
16
+ name?: string;
17
+ picture?: string;
18
+ "nebutra:organization_id"?: string;
19
+ "nebutra:role"?: string;
20
+ "nebutra:plan"?: string;
21
+ [key: string]: unknown;
22
+ }
23
+ declare class NebutraIdentityAdapter implements IdentityAdapter<NebutraOIDCClaims> {
24
+ readonly provider: "nebutra";
25
+ mapToCanonical(input: NebutraOIDCClaims): CanonicalIdentity | null;
26
+ private mapRole;
27
+ private mapPlan;
28
+ }
29
+
30
+ export { NebutraIdentityAdapter };
@@ -0,0 +1,7 @@
1
+ import {
2
+ NebutraIdentityAdapter
3
+ } from "../chunk-LMFYKNSW.js";
4
+ export {
5
+ NebutraIdentityAdapter
6
+ };
7
+ //# sourceMappingURL=nebutra.js.map
@@ -0,0 +1,18 @@
1
+ import {
2
+ IdentityAdapterRegistry
3
+ } from "./chunk-VMSPQ5ZK.js";
4
+ import {
5
+ NebutraIdentityAdapter
6
+ } from "./chunk-LMFYKNSW.js";
7
+
8
+ // src/registry.ts
9
+ function createDefaultIdentityAdapterRegistry() {
10
+ const registry = new IdentityAdapterRegistry();
11
+ registry.register(new NebutraIdentityAdapter());
12
+ return registry;
13
+ }
14
+
15
+ export {
16
+ createDefaultIdentityAdapterRegistry
17
+ };
18
+ //# sourceMappingURL=chunk-CAQ25QHX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/registry.ts"],"sourcesContent":["import { NebutraIdentityAdapter } from \"./adapters/nebutra\";\nimport { IdentityAdapterRegistry } from \"./types\";\n\nexport function createDefaultIdentityAdapterRegistry(): IdentityAdapterRegistry {\n const registry = new IdentityAdapterRegistry();\n registry.register(new NebutraIdentityAdapter());\n return registry;\n}\n"],"mappings":";;;;;;;;AAGO,SAAS,uCAAgE;AAC9E,QAAM,WAAW,IAAI,wBAAwB;AAC7C,WAAS,SAAS,IAAI,uBAAuB,CAAC;AAC9C,SAAO;AACT;","names":[]}
@@ -1,13 +1,3 @@
1
- import {
2
- IdentityAdapterRegistry
3
- } from "./chunk-MZKK4BRU.js";
4
- import {
5
- AuthJsIdentityAdapter
6
- } from "./chunk-ZERXN5CV.js";
7
- import {
8
- ClerkIdentityAdapter
9
- } from "./chunk-QKUYKQO6.js";
10
-
11
1
  // src/adapters/nebutra.ts
12
2
  var NebutraIdentityAdapter = class {
13
3
  provider = "nebutra";
@@ -39,17 +29,7 @@ var NebutraIdentityAdapter = class {
39
29
  }
40
30
  };
41
31
 
42
- // src/registry.ts
43
- function createDefaultIdentityAdapterRegistry() {
44
- const registry = new IdentityAdapterRegistry();
45
- registry.register(new ClerkIdentityAdapter());
46
- registry.register(new AuthJsIdentityAdapter());
47
- registry.register(new NebutraIdentityAdapter());
48
- return registry;
49
- }
50
-
51
32
  export {
52
- NebutraIdentityAdapter,
53
- createDefaultIdentityAdapterRegistry
33
+ NebutraIdentityAdapter
54
34
  };
55
- //# sourceMappingURL=chunk-DOCMMNRB.js.map
35
+ //# sourceMappingURL=chunk-LMFYKNSW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters/nebutra.ts"],"sourcesContent":["/**\n * Nebutra Identity Adapter\n *\n * Maps oidc-provider / Nebutra-issued OIDC tokens to CanonicalIdentity.\n * Used when Nebutra acts as both the IdP AND the resource server —\n * i.e., when a Nebutra service receives an access token issued by\n * the Nebutra IdP and needs to resolve the user identity.\n */\n\nimport type { CanonicalIdentity } from \"@nebutra/contracts\";\nimport type { IdentityAdapter } from \"../types\";\n\ninterface NebutraOIDCClaims {\n sub: string;\n email?: string;\n name?: string;\n picture?: string;\n \"nebutra:organization_id\"?: string;\n \"nebutra:role\"?: string;\n \"nebutra:plan\"?: string;\n [key: string]: unknown;\n}\n\nexport class NebutraIdentityAdapter implements IdentityAdapter<NebutraOIDCClaims> {\n readonly provider = \"nebutra\" as const;\n\n mapToCanonical(input: NebutraOIDCClaims): CanonicalIdentity | null {\n if (!input.sub) return null;\n\n return {\n provider: \"nebutra\",\n userId: input.sub,\n organizationId: input[\"nebutra:organization_id\"],\n role: this.mapRole(input[\"nebutra:role\"]),\n plan: this.mapPlan(input[\"nebutra:plan\"]),\n email: input.email,\n claimsVersion: \"v1\",\n };\n }\n\n private mapRole(role?: string): \"OWNER\" | \"ADMIN\" | \"MEMBER\" | \"VIEWER\" | undefined {\n const validRoles = [\"OWNER\", \"ADMIN\", \"MEMBER\", \"VIEWER\"] as const;\n if (role && validRoles.includes(role as (typeof validRoles)[number])) {\n return role as (typeof validRoles)[number];\n }\n return undefined;\n }\n\n private mapPlan(plan?: string): \"FREE\" | \"PRO\" | \"ENTERPRISE\" | undefined {\n const validPlans = [\"FREE\", \"PRO\", \"ENTERPRISE\"] as const;\n if (plan && validPlans.includes(plan as (typeof validPlans)[number])) {\n return plan as (typeof validPlans)[number];\n }\n return undefined;\n }\n}\n"],"mappings":";AAuBO,IAAM,yBAAN,MAA2E;AAAA,EACvE,WAAW;AAAA,EAEpB,eAAe,OAAoD;AACjE,QAAI,CAAC,MAAM,IAAK,QAAO;AAEvB,WAAO;AAAA,MACL,UAAU;AAAA,MACV,QAAQ,MAAM;AAAA,MACd,gBAAgB,MAAM,yBAAyB;AAAA,MAC/C,MAAM,KAAK,QAAQ,MAAM,cAAc,CAAC;AAAA,MACxC,MAAM,KAAK,QAAQ,MAAM,cAAc,CAAC;AAAA,MACxC,OAAO,MAAM;AAAA,MACb,eAAe;AAAA,IACjB;AAAA,EACF;AAAA,EAEQ,QAAQ,MAAoE;AAClF,UAAM,aAAa,CAAC,SAAS,SAAS,UAAU,QAAQ;AACxD,QAAI,QAAQ,WAAW,SAAS,IAAmC,GAAG;AACpE,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,QAAQ,MAA0D;AACxE,UAAM,aAAa,CAAC,QAAQ,OAAO,YAAY;AAC/C,QAAI,QAAQ,WAAW,SAAS,IAAmC,GAAG;AACpE,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AACF;","names":[]}
@@ -19,4 +19,4 @@ var IdentityAdapterRegistry = class {
19
19
  export {
20
20
  IdentityAdapterRegistry
21
21
  };
22
- //# sourceMappingURL=chunk-MZKK4BRU.js.map
22
+ //# sourceMappingURL=chunk-VMSPQ5ZK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type { CanonicalIdentity } from \"@nebutra/contracts\";\n\nexport type IdentityProvider = \"nebutra\" | \"custom\";\n\nexport interface IdentityAdapter<TInput = unknown> {\n provider: IdentityProvider | string;\n mapToCanonical(input: TInput): CanonicalIdentity | null;\n}\n\nexport class IdentityAdapterRegistry {\n private readonly adapters = new Map<string, IdentityAdapter>();\n\n register(adapter: IdentityAdapter): void {\n this.adapters.set(adapter.provider, adapter);\n }\n\n get(provider: string): IdentityAdapter | undefined {\n return this.adapters.get(provider);\n }\n\n map<TInput = unknown>(provider: string, input: TInput): CanonicalIdentity | null {\n const adapter = this.get(provider);\n if (!adapter) {\n return null;\n }\n return adapter.mapToCanonical(input);\n }\n}\n"],"mappings":";AASO,IAAM,0BAAN,MAA8B;AAAA,EAClB,WAAW,oBAAI,IAA6B;AAAA,EAE7D,SAAS,SAAgC;AACvC,SAAK,SAAS,IAAI,QAAQ,UAAU,OAAO;AAAA,EAC7C;AAAA,EAEA,IAAI,UAA+C;AACjD,WAAO,KAAK,SAAS,IAAI,QAAQ;AAAA,EACnC;AAAA,EAEA,IAAsB,UAAkB,OAAyC;AAC/E,UAAM,UAAU,KAAK,IAAI,QAAQ;AACjC,QAAI,CAAC,SAAS;AACZ,aAAO;AAAA,IACT;AACA,WAAO,QAAQ,eAAe,KAAK;AAAA,EACrC;AACF;","names":[]}
package/dist/index.d.ts CHANGED
@@ -1,34 +1,4 @@
1
- export { AuthJsIdentityAdapter } from './adapters/authjs.js';
2
- export { ClerkIdentityAdapter } from './adapters/clerk.js';
3
- import { CanonicalIdentity } from '@nebutra/contracts';
4
- import { IdentityAdapter } from './types.js';
5
- export { IdentityAdapterRegistry, IdentityProvider } from './types.js';
1
+ export { NebutraIdentityAdapter } from './adapters/nebutra.js';
6
2
  export { createDefaultIdentityAdapterRegistry } from './registry.js';
7
-
8
- /**
9
- * Nebutra Identity Adapter
10
- *
11
- * Maps oidc-provider / Nebutra-issued OIDC tokens to CanonicalIdentity.
12
- * Used when Nebutra acts as both the IdP AND the resource server —
13
- * i.e., when a Nebutra service receives an access token issued by
14
- * the Nebutra IdP and needs to resolve the user identity.
15
- */
16
-
17
- interface NebutraOIDCClaims {
18
- sub: string;
19
- email?: string;
20
- name?: string;
21
- picture?: string;
22
- "nebutra:organization_id"?: string;
23
- "nebutra:role"?: string;
24
- "nebutra:plan"?: string;
25
- [key: string]: unknown;
26
- }
27
- declare class NebutraIdentityAdapter implements IdentityAdapter<NebutraOIDCClaims> {
28
- readonly provider: "nebutra";
29
- mapToCanonical(input: NebutraOIDCClaims): CanonicalIdentity | null;
30
- private mapRole;
31
- private mapPlan;
32
- }
33
-
34
- export { IdentityAdapter, NebutraIdentityAdapter };
3
+ export { IdentityAdapter, IdentityAdapterRegistry, IdentityProvider } from './types.js';
4
+ import '@nebutra/contracts';
package/dist/index.js CHANGED
@@ -1,19 +1,13 @@
1
1
  import {
2
- NebutraIdentityAdapter,
3
2
  createDefaultIdentityAdapterRegistry
4
- } from "./chunk-DOCMMNRB.js";
3
+ } from "./chunk-CAQ25QHX.js";
5
4
  import {
6
5
  IdentityAdapterRegistry
7
- } from "./chunk-MZKK4BRU.js";
8
- import {
9
- AuthJsIdentityAdapter
10
- } from "./chunk-ZERXN5CV.js";
6
+ } from "./chunk-VMSPQ5ZK.js";
11
7
  import {
12
- ClerkIdentityAdapter
13
- } from "./chunk-QKUYKQO6.js";
8
+ NebutraIdentityAdapter
9
+ } from "./chunk-LMFYKNSW.js";
14
10
  export {
15
- AuthJsIdentityAdapter,
16
- ClerkIdentityAdapter,
17
11
  IdentityAdapterRegistry,
18
12
  NebutraIdentityAdapter,
19
13
  createDefaultIdentityAdapterRegistry
package/dist/registry.js CHANGED
@@ -1,9 +1,8 @@
1
1
  import {
2
2
  createDefaultIdentityAdapterRegistry
3
- } from "./chunk-DOCMMNRB.js";
4
- import "./chunk-MZKK4BRU.js";
5
- import "./chunk-ZERXN5CV.js";
6
- import "./chunk-QKUYKQO6.js";
3
+ } from "./chunk-CAQ25QHX.js";
4
+ import "./chunk-VMSPQ5ZK.js";
5
+ import "./chunk-LMFYKNSW.js";
7
6
  export {
8
7
  createDefaultIdentityAdapterRegistry
9
8
  };
package/dist/types.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { CanonicalIdentity } from '@nebutra/contracts';
2
2
 
3
- type IdentityProvider = "clerk" | "authjs" | "custom";
3
+ type IdentityProvider = "nebutra" | "custom";
4
4
  interface IdentityAdapter<TInput = unknown> {
5
5
  provider: IdentityProvider | string;
6
6
  mapToCanonical(input: TInput): CanonicalIdentity | null;
package/dist/types.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  IdentityAdapterRegistry
3
- } from "./chunk-MZKK4BRU.js";
3
+ } from "./chunk-VMSPQ5ZK.js";
4
4
  export {
5
5
  IdentityAdapterRegistry
6
6
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@nebutra/identity",
3
- "version": "2.0.0",
4
- "description": "Provider-agnostic identity adapter layer (Clerk-first, Auth.js-ready)",
3
+ "version": "3.0.0",
4
+ "description": "Provider-agnostic identity adapter layer (Nebutra-issued OIDC claims by default)",
5
5
  "private": false,
6
6
  "nebutra": {
7
7
  "status": "foundation",
@@ -16,19 +16,11 @@
16
16
  ".": {
17
17
  "import": "./dist/index.js",
18
18
  "types": "./dist/index.d.ts"
19
- },
20
- "./adapters/clerk": {
21
- "import": "./dist/adapters/clerk.js",
22
- "types": "./dist/adapters/clerk.d.ts"
23
- },
24
- "./adapters/authjs": {
25
- "import": "./dist/adapters/authjs.js",
26
- "types": "./dist/adapters/authjs.d.ts"
27
19
  }
28
20
  },
29
21
  "dependencies": {
30
22
  "zod": "^4.3.6",
31
- "@nebutra/contracts": "2.0.0"
23
+ "@nebutra/contracts": "3.0.0"
32
24
  },
33
25
  "devDependencies": {
34
26
  "@types/node": "^22.19.15",
package/src/index.ts CHANGED
@@ -1,5 +1,3 @@
1
- export { AuthJsIdentityAdapter } from "./adapters/authjs";
2
- export { ClerkIdentityAdapter } from "./adapters/clerk";
3
1
  export { NebutraIdentityAdapter } from "./adapters/nebutra";
4
2
  export { createDefaultIdentityAdapterRegistry } from "./registry";
5
3
  export type { IdentityAdapter, IdentityProvider } from "./types";
package/src/registry.ts CHANGED
@@ -1,12 +1,8 @@
1
- import { AuthJsIdentityAdapter } from "./adapters/authjs";
2
- import { ClerkIdentityAdapter } from "./adapters/clerk";
3
1
  import { NebutraIdentityAdapter } from "./adapters/nebutra";
4
2
  import { IdentityAdapterRegistry } from "./types";
5
3
 
6
4
  export function createDefaultIdentityAdapterRegistry(): IdentityAdapterRegistry {
7
5
  const registry = new IdentityAdapterRegistry();
8
- registry.register(new ClerkIdentityAdapter());
9
- registry.register(new AuthJsIdentityAdapter());
10
6
  registry.register(new NebutraIdentityAdapter());
11
7
  return registry;
12
8
  }
package/src/types.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { CanonicalIdentity } from "@nebutra/contracts";
2
2
 
3
- export type IdentityProvider = "clerk" | "authjs" | "custom";
3
+ export type IdentityProvider = "nebutra" | "custom";
4
4
 
5
5
  export interface IdentityAdapter<TInput = unknown> {
6
6
  provider: IdentityProvider | string;
package/tsup.config.ts CHANGED
@@ -1,13 +1,7 @@
1
1
  import { defineConfig } from "tsup";
2
2
 
3
3
  export default defineConfig({
4
- entry: [
5
- "src/index.ts",
6
- "src/types.ts",
7
- "src/registry.ts",
8
- "src/adapters/clerk.ts",
9
- "src/adapters/authjs.ts",
10
- ],
4
+ entry: ["src/index.ts", "src/types.ts", "src/registry.ts", "src/adapters/nebutra.ts"],
11
5
  format: ["esm"],
12
6
  dts: true,
13
7
  sourcemap: true,
@@ -1,9 +0,0 @@
1
- import { CanonicalIdentity } from '@nebutra/contracts';
2
- import { IdentityAdapter } from '../types.js';
3
-
4
- declare class AuthJsIdentityAdapter implements IdentityAdapter<unknown> {
5
- provider: "authjs";
6
- mapToCanonical(input: unknown): CanonicalIdentity | null;
7
- }
8
-
9
- export { AuthJsIdentityAdapter };
@@ -1,7 +0,0 @@
1
- import {
2
- AuthJsIdentityAdapter
3
- } from "../chunk-ZERXN5CV.js";
4
- export {
5
- AuthJsIdentityAdapter
6
- };
7
- //# sourceMappingURL=authjs.js.map
@@ -1,9 +0,0 @@
1
- import { CanonicalIdentity } from '@nebutra/contracts';
2
- import { IdentityAdapter } from '../types.js';
3
-
4
- declare class ClerkIdentityAdapter implements IdentityAdapter<unknown> {
5
- provider: "clerk";
6
- mapToCanonical(input: unknown): CanonicalIdentity | null;
7
- }
8
-
9
- export { ClerkIdentityAdapter };
@@ -1,7 +0,0 @@
1
- import {
2
- ClerkIdentityAdapter
3
- } from "../chunk-QKUYKQO6.js";
4
- export {
5
- ClerkIdentityAdapter
6
- };
7
- //# sourceMappingURL=clerk.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/adapters/nebutra.ts","../src/registry.ts"],"sourcesContent":["/**\n * Nebutra Identity Adapter\n *\n * Maps oidc-provider / Nebutra-issued OIDC tokens to CanonicalIdentity.\n * Used when Nebutra acts as both the IdP AND the resource server —\n * i.e., when a Nebutra service receives an access token issued by\n * the Nebutra IdP and needs to resolve the user identity.\n */\n\nimport type { CanonicalIdentity } from \"@nebutra/contracts\";\nimport type { IdentityAdapter } from \"../types\";\n\ninterface NebutraOIDCClaims {\n sub: string;\n email?: string;\n name?: string;\n picture?: string;\n \"nebutra:organization_id\"?: string;\n \"nebutra:role\"?: string;\n \"nebutra:plan\"?: string;\n [key: string]: unknown;\n}\n\nexport class NebutraIdentityAdapter implements IdentityAdapter<NebutraOIDCClaims> {\n readonly provider = \"nebutra\" as const;\n\n mapToCanonical(input: NebutraOIDCClaims): CanonicalIdentity | null {\n if (!input.sub) return null;\n\n return {\n provider: \"nebutra\",\n userId: input.sub,\n organizationId: input[\"nebutra:organization_id\"],\n role: this.mapRole(input[\"nebutra:role\"]),\n plan: this.mapPlan(input[\"nebutra:plan\"]),\n email: input.email,\n claimsVersion: \"v1\",\n };\n }\n\n private mapRole(role?: string): \"OWNER\" | \"ADMIN\" | \"MEMBER\" | \"VIEWER\" | undefined {\n const validRoles = [\"OWNER\", \"ADMIN\", \"MEMBER\", \"VIEWER\"] as const;\n if (role && validRoles.includes(role as (typeof validRoles)[number])) {\n return role as (typeof validRoles)[number];\n }\n return undefined;\n }\n\n private mapPlan(plan?: string): \"FREE\" | \"PRO\" | \"ENTERPRISE\" | undefined {\n const validPlans = [\"FREE\", \"PRO\", \"ENTERPRISE\"] as const;\n if (plan && validPlans.includes(plan as (typeof validPlans)[number])) {\n return plan as (typeof validPlans)[number];\n }\n return undefined;\n }\n}\n","import { AuthJsIdentityAdapter } from \"./adapters/authjs\";\nimport { ClerkIdentityAdapter } from \"./adapters/clerk\";\nimport { NebutraIdentityAdapter } from \"./adapters/nebutra\";\nimport { IdentityAdapterRegistry } from \"./types\";\n\nexport function createDefaultIdentityAdapterRegistry(): IdentityAdapterRegistry {\n const registry = new IdentityAdapterRegistry();\n registry.register(new ClerkIdentityAdapter());\n registry.register(new AuthJsIdentityAdapter());\n registry.register(new NebutraIdentityAdapter());\n return registry;\n}\n"],"mappings":";;;;;;;;;;;AAuBO,IAAM,yBAAN,MAA2E;AAAA,EACvE,WAAW;AAAA,EAEpB,eAAe,OAAoD;AACjE,QAAI,CAAC,MAAM,IAAK,QAAO;AAEvB,WAAO;AAAA,MACL,UAAU;AAAA,MACV,QAAQ,MAAM;AAAA,MACd,gBAAgB,MAAM,yBAAyB;AAAA,MAC/C,MAAM,KAAK,QAAQ,MAAM,cAAc,CAAC;AAAA,MACxC,MAAM,KAAK,QAAQ,MAAM,cAAc,CAAC;AAAA,MACxC,OAAO,MAAM;AAAA,MACb,eAAe;AAAA,IACjB;AAAA,EACF;AAAA,EAEQ,QAAQ,MAAoE;AAClF,UAAM,aAAa,CAAC,SAAS,SAAS,UAAU,QAAQ;AACxD,QAAI,QAAQ,WAAW,SAAS,IAAmC,GAAG;AACpE,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,QAAQ,MAA0D;AACxE,UAAM,aAAa,CAAC,QAAQ,OAAO,YAAY;AAC/C,QAAI,QAAQ,WAAW,SAAS,IAAmC,GAAG;AACpE,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AACF;;;AClDO,SAAS,uCAAgE;AAC9E,QAAM,WAAW,IAAI,wBAAwB;AAC7C,WAAS,SAAS,IAAI,qBAAqB,CAAC;AAC5C,WAAS,SAAS,IAAI,sBAAsB,CAAC;AAC7C,WAAS,SAAS,IAAI,uBAAuB,CAAC;AAC9C,SAAO;AACT;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type { CanonicalIdentity } from \"@nebutra/contracts\";\n\nexport type IdentityProvider = \"clerk\" | \"authjs\" | \"custom\";\n\nexport interface IdentityAdapter<TInput = unknown> {\n provider: IdentityProvider | string;\n mapToCanonical(input: TInput): CanonicalIdentity | null;\n}\n\nexport class IdentityAdapterRegistry {\n private readonly adapters = new Map<string, IdentityAdapter>();\n\n register(adapter: IdentityAdapter): void {\n this.adapters.set(adapter.provider, adapter);\n }\n\n get(provider: string): IdentityAdapter | undefined {\n return this.adapters.get(provider);\n }\n\n map<TInput = unknown>(provider: string, input: TInput): CanonicalIdentity | null {\n const adapter = this.get(provider);\n if (!adapter) {\n return null;\n }\n return adapter.mapToCanonical(input);\n }\n}\n"],"mappings":";AASO,IAAM,0BAAN,MAA8B;AAAA,EAClB,WAAW,oBAAI,IAA6B;AAAA,EAE7D,SAAS,SAAgC;AACvC,SAAK,SAAS,IAAI,QAAQ,UAAU,OAAO;AAAA,EAC7C;AAAA,EAEA,IAAI,UAA+C;AACjD,WAAO,KAAK,SAAS,IAAI,QAAQ;AAAA,EACnC;AAAA,EAEA,IAAsB,UAAkB,OAAyC;AAC/E,UAAM,UAAU,KAAK,IAAI,QAAQ;AACjC,QAAI,CAAC,SAAS;AACZ,aAAO;AAAA,IACT;AACA,WAAO,QAAQ,eAAe,KAAK;AAAA,EACrC;AACF;","names":[]}
@@ -1,35 +0,0 @@
1
- // src/adapters/clerk.ts
2
- import { CanonicalIdentitySchema } from "@nebutra/contracts";
3
- import { z } from "zod";
4
- var ClerkPayloadSchema = z.object({
5
- sub: z.string().min(1),
6
- org_id: z.string().min(1).optional(),
7
- org_role: z.enum(["OWNER", "ADMIN", "MEMBER", "VIEWER"]).optional(),
8
- sid: z.string().min(1).optional(),
9
- email: z.string().email().optional()
10
- });
11
- var ClerkIdentityAdapter = class {
12
- provider = "clerk";
13
- mapToCanonical(input) {
14
- const parsed = ClerkPayloadSchema.safeParse(input);
15
- if (!parsed.success) {
16
- return null;
17
- }
18
- const candidate = {
19
- provider: "clerk",
20
- userId: parsed.data.sub,
21
- organizationId: parsed.data.org_id,
22
- role: parsed.data.org_role,
23
- email: parsed.data.email,
24
- sessionId: parsed.data.sid,
25
- claimsVersion: "v1"
26
- };
27
- const canonical = CanonicalIdentitySchema.safeParse(candidate);
28
- return canonical.success ? canonical.data : null;
29
- }
30
- };
31
-
32
- export {
33
- ClerkIdentityAdapter
34
- };
35
- //# sourceMappingURL=chunk-QKUYKQO6.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/adapters/clerk.ts"],"sourcesContent":["import { type CanonicalIdentity, CanonicalIdentitySchema } from \"@nebutra/contracts\";\nimport { z } from \"zod\";\n\nimport type { IdentityAdapter } from \"../types\";\n\nconst ClerkPayloadSchema = z.object({\n sub: z.string().min(1),\n org_id: z.string().min(1).optional(),\n org_role: z.enum([\"OWNER\", \"ADMIN\", \"MEMBER\", \"VIEWER\"]).optional(),\n sid: z.string().min(1).optional(),\n email: z.string().email().optional(),\n});\n\nexport class ClerkIdentityAdapter implements IdentityAdapter<unknown> {\n provider = \"clerk\" as const;\n\n mapToCanonical(input: unknown): CanonicalIdentity | null {\n const parsed = ClerkPayloadSchema.safeParse(input);\n if (!parsed.success) {\n return null;\n }\n\n const candidate = {\n provider: \"clerk\" as const,\n userId: parsed.data.sub,\n organizationId: parsed.data.org_id,\n role: parsed.data.org_role,\n email: parsed.data.email,\n sessionId: parsed.data.sid,\n claimsVersion: \"v1\" as const,\n };\n\n const canonical = CanonicalIdentitySchema.safeParse(candidate);\n return canonical.success ? canonical.data : null;\n }\n}\n"],"mappings":";AAAA,SAAiC,+BAA+B;AAChE,SAAS,SAAS;AAIlB,IAAM,qBAAqB,EAAE,OAAO;AAAA,EAClC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACrB,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACnC,UAAU,EAAE,KAAK,CAAC,SAAS,SAAS,UAAU,QAAQ,CAAC,EAAE,SAAS;AAAA,EAClE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EAChC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS;AACrC,CAAC;AAEM,IAAM,uBAAN,MAA+D;AAAA,EACpE,WAAW;AAAA,EAEX,eAAe,OAA0C;AACvD,UAAM,SAAS,mBAAmB,UAAU,KAAK;AACjD,QAAI,CAAC,OAAO,SAAS;AACnB,aAAO;AAAA,IACT;AAEA,UAAM,YAAY;AAAA,MAChB,UAAU;AAAA,MACV,QAAQ,OAAO,KAAK;AAAA,MACpB,gBAAgB,OAAO,KAAK;AAAA,MAC5B,MAAM,OAAO,KAAK;AAAA,MAClB,OAAO,OAAO,KAAK;AAAA,MACnB,WAAW,OAAO,KAAK;AAAA,MACvB,eAAe;AAAA,IACjB;AAEA,UAAM,YAAY,wBAAwB,UAAU,SAAS;AAC7D,WAAO,UAAU,UAAU,UAAU,OAAO;AAAA,EAC9C;AACF;","names":[]}
@@ -1,46 +0,0 @@
1
- // src/adapters/authjs.ts
2
- import { CanonicalIdentitySchema } from "@nebutra/contracts";
3
- import { z } from "zod";
4
- var AuthJsSessionSchema = z.object({
5
- user: z.object({
6
- id: z.string().min(1).optional(),
7
- email: z.string().email().optional()
8
- }).optional(),
9
- token: z.object({
10
- sub: z.string().min(1).optional(),
11
- orgId: z.string().min(1).optional(),
12
- orgRole: z.enum(["OWNER", "ADMIN", "MEMBER", "VIEWER"]).optional(),
13
- sid: z.string().min(1).optional(),
14
- plan: z.enum(["FREE", "PRO", "ENTERPRISE"]).optional()
15
- }).optional()
16
- });
17
- var AuthJsIdentityAdapter = class {
18
- provider = "authjs";
19
- mapToCanonical(input) {
20
- const parsed = AuthJsSessionSchema.safeParse(input);
21
- if (!parsed.success) {
22
- return null;
23
- }
24
- const userId = parsed.data.user?.id ?? parsed.data.token?.sub;
25
- if (!userId) {
26
- return null;
27
- }
28
- const candidate = {
29
- provider: "authjs",
30
- userId,
31
- organizationId: parsed.data.token?.orgId,
32
- role: parsed.data.token?.orgRole,
33
- plan: parsed.data.token?.plan,
34
- email: parsed.data.user?.email,
35
- sessionId: parsed.data.token?.sid,
36
- claimsVersion: "v1"
37
- };
38
- const canonical = CanonicalIdentitySchema.safeParse(candidate);
39
- return canonical.success ? canonical.data : null;
40
- }
41
- };
42
-
43
- export {
44
- AuthJsIdentityAdapter
45
- };
46
- //# sourceMappingURL=chunk-ZERXN5CV.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/adapters/authjs.ts"],"sourcesContent":["import { type CanonicalIdentity, CanonicalIdentitySchema } from \"@nebutra/contracts\";\nimport { z } from \"zod\";\n\nimport type { IdentityAdapter } from \"../types\";\n\nconst AuthJsSessionSchema = z.object({\n user: z\n .object({\n id: z.string().min(1).optional(),\n email: z.string().email().optional(),\n })\n .optional(),\n token: z\n .object({\n sub: z.string().min(1).optional(),\n orgId: z.string().min(1).optional(),\n orgRole: z.enum([\"OWNER\", \"ADMIN\", \"MEMBER\", \"VIEWER\"]).optional(),\n sid: z.string().min(1).optional(),\n plan: z.enum([\"FREE\", \"PRO\", \"ENTERPRISE\"]).optional(),\n })\n .optional(),\n});\n\nexport class AuthJsIdentityAdapter implements IdentityAdapter<unknown> {\n provider = \"authjs\" as const;\n\n mapToCanonical(input: unknown): CanonicalIdentity | null {\n const parsed = AuthJsSessionSchema.safeParse(input);\n if (!parsed.success) {\n return null;\n }\n\n const userId = parsed.data.user?.id ?? parsed.data.token?.sub;\n if (!userId) {\n return null;\n }\n\n const candidate = {\n provider: \"authjs\" as const,\n userId,\n organizationId: parsed.data.token?.orgId,\n role: parsed.data.token?.orgRole,\n plan: parsed.data.token?.plan,\n email: parsed.data.user?.email,\n sessionId: parsed.data.token?.sid,\n claimsVersion: \"v1\" as const,\n };\n\n const canonical = CanonicalIdentitySchema.safeParse(candidate);\n return canonical.success ? canonical.data : null;\n }\n}\n"],"mappings":";AAAA,SAAiC,+BAA+B;AAChE,SAAS,SAAS;AAIlB,IAAM,sBAAsB,EAAE,OAAO;AAAA,EACnC,MAAM,EACH,OAAO;AAAA,IACN,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,IAC/B,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS;AAAA,EACrC,CAAC,EACA,SAAS;AAAA,EACZ,OAAO,EACJ,OAAO;AAAA,IACN,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,IAChC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,IAClC,SAAS,EAAE,KAAK,CAAC,SAAS,SAAS,UAAU,QAAQ,CAAC,EAAE,SAAS;AAAA,IACjE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,IAChC,MAAM,EAAE,KAAK,CAAC,QAAQ,OAAO,YAAY,CAAC,EAAE,SAAS;AAAA,EACvD,CAAC,EACA,SAAS;AACd,CAAC;AAEM,IAAM,wBAAN,MAAgE;AAAA,EACrE,WAAW;AAAA,EAEX,eAAe,OAA0C;AACvD,UAAM,SAAS,oBAAoB,UAAU,KAAK;AAClD,QAAI,CAAC,OAAO,SAAS;AACnB,aAAO;AAAA,IACT;AAEA,UAAM,SAAS,OAAO,KAAK,MAAM,MAAM,OAAO,KAAK,OAAO;AAC1D,QAAI,CAAC,QAAQ;AACX,aAAO;AAAA,IACT;AAEA,UAAM,YAAY;AAAA,MAChB,UAAU;AAAA,MACV;AAAA,MACA,gBAAgB,OAAO,KAAK,OAAO;AAAA,MACnC,MAAM,OAAO,KAAK,OAAO;AAAA,MACzB,MAAM,OAAO,KAAK,OAAO;AAAA,MACzB,OAAO,OAAO,KAAK,MAAM;AAAA,MACzB,WAAW,OAAO,KAAK,OAAO;AAAA,MAC9B,eAAe;AAAA,IACjB;AAEA,UAAM,YAAY,wBAAwB,UAAU,SAAS;AAC7D,WAAO,UAAU,UAAU,UAAU,OAAO;AAAA,EAC9C;AACF;","names":[]}
@@ -1,52 +0,0 @@
1
- import { type CanonicalIdentity, CanonicalIdentitySchema } from "@nebutra/contracts";
2
- import { z } from "zod";
3
-
4
- import type { IdentityAdapter } from "../types";
5
-
6
- const AuthJsSessionSchema = z.object({
7
- user: z
8
- .object({
9
- id: z.string().min(1).optional(),
10
- email: z.string().email().optional(),
11
- })
12
- .optional(),
13
- token: z
14
- .object({
15
- sub: z.string().min(1).optional(),
16
- orgId: z.string().min(1).optional(),
17
- orgRole: z.enum(["OWNER", "ADMIN", "MEMBER", "VIEWER"]).optional(),
18
- sid: z.string().min(1).optional(),
19
- plan: z.enum(["FREE", "PRO", "ENTERPRISE"]).optional(),
20
- })
21
- .optional(),
22
- });
23
-
24
- export class AuthJsIdentityAdapter implements IdentityAdapter<unknown> {
25
- provider = "authjs" as const;
26
-
27
- mapToCanonical(input: unknown): CanonicalIdentity | null {
28
- const parsed = AuthJsSessionSchema.safeParse(input);
29
- if (!parsed.success) {
30
- return null;
31
- }
32
-
33
- const userId = parsed.data.user?.id ?? parsed.data.token?.sub;
34
- if (!userId) {
35
- return null;
36
- }
37
-
38
- const candidate = {
39
- provider: "authjs" as const,
40
- userId,
41
- organizationId: parsed.data.token?.orgId,
42
- role: parsed.data.token?.orgRole,
43
- plan: parsed.data.token?.plan,
44
- email: parsed.data.user?.email,
45
- sessionId: parsed.data.token?.sid,
46
- claimsVersion: "v1" as const,
47
- };
48
-
49
- const canonical = CanonicalIdentitySchema.safeParse(candidate);
50
- return canonical.success ? canonical.data : null;
51
- }
52
- }
@@ -1,36 +0,0 @@
1
- import { type CanonicalIdentity, CanonicalIdentitySchema } from "@nebutra/contracts";
2
- import { z } from "zod";
3
-
4
- import type { IdentityAdapter } from "../types";
5
-
6
- const ClerkPayloadSchema = z.object({
7
- sub: z.string().min(1),
8
- org_id: z.string().min(1).optional(),
9
- org_role: z.enum(["OWNER", "ADMIN", "MEMBER", "VIEWER"]).optional(),
10
- sid: z.string().min(1).optional(),
11
- email: z.string().email().optional(),
12
- });
13
-
14
- export class ClerkIdentityAdapter implements IdentityAdapter<unknown> {
15
- provider = "clerk" as const;
16
-
17
- mapToCanonical(input: unknown): CanonicalIdentity | null {
18
- const parsed = ClerkPayloadSchema.safeParse(input);
19
- if (!parsed.success) {
20
- return null;
21
- }
22
-
23
- const candidate = {
24
- provider: "clerk" as const,
25
- userId: parsed.data.sub,
26
- organizationId: parsed.data.org_id,
27
- role: parsed.data.org_role,
28
- email: parsed.data.email,
29
- sessionId: parsed.data.sid,
30
- claimsVersion: "v1" as const,
31
- };
32
-
33
- const canonical = CanonicalIdentitySchema.safeParse(candidate);
34
- return canonical.success ? canonical.data : null;
35
- }
36
- }
File without changes