@facilis.dev/auth 0.0.0-stage → 0.1.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.
Files changed (73) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +18 -2
  3. package/dist/api-clients.d.ts +71 -0
  4. package/dist/api-clients.js +186 -0
  5. package/dist/crypto.d.ts +31 -0
  6. package/dist/crypto.js +76 -0
  7. package/dist/email-verification.d.ts +45 -0
  8. package/dist/email-verification.js +72 -0
  9. package/dist/email.d.ts +7 -0
  10. package/dist/email.js +9 -0
  11. package/dist/index.d.ts +12 -0
  12. package/dist/index.js +12 -0
  13. package/dist/password.d.ts +7 -0
  14. package/dist/password.js +54 -0
  15. package/dist/roles.d.ts +40 -0
  16. package/dist/roles.js +46 -0
  17. package/dist/seed.d.ts +28 -0
  18. package/dist/seed.js +115 -0
  19. package/dist/session.d.ts +66 -0
  20. package/dist/session.js +161 -0
  21. package/dist/sso/contracts.d.ts +52 -0
  22. package/dist/sso/contracts.js +8 -0
  23. package/dist/sso/errors.d.ts +22 -0
  24. package/dist/sso/errors.js +45 -0
  25. package/dist/sso/identity.d.ts +41 -0
  26. package/dist/sso/identity.js +162 -0
  27. package/dist/sso/index.d.ts +27 -0
  28. package/dist/sso/index.js +16 -0
  29. package/dist/sso/login.d.ts +60 -0
  30. package/dist/sso/login.js +209 -0
  31. package/dist/sso/oauth2.d.ts +52 -0
  32. package/dist/sso/oauth2.js +180 -0
  33. package/dist/sso/oidc.d.ts +60 -0
  34. package/dist/sso/oidc.js +201 -0
  35. package/dist/sso/paths.d.ts +14 -0
  36. package/dist/sso/paths.js +17 -0
  37. package/dist/sso/pkce.d.ts +6 -0
  38. package/dist/sso/pkce.js +21 -0
  39. package/dist/sso/providers.d.ts +100 -0
  40. package/dist/sso/providers.js +70 -0
  41. package/dist/sso/saml.d.ts +44 -0
  42. package/dist/sso/saml.js +159 -0
  43. package/dist/sso/state.d.ts +34 -0
  44. package/dist/sso/state.js +91 -0
  45. package/dist/sso/tables.d.ts +306 -0
  46. package/dist/sso/tables.js +59 -0
  47. package/dist/tables.d.ts +769 -0
  48. package/dist/tables.js +148 -0
  49. package/package.json +45 -4
  50. package/src/api-clients.ts +261 -0
  51. package/src/crypto.ts +101 -0
  52. package/src/email-verification.ts +107 -0
  53. package/src/email.ts +9 -0
  54. package/src/index.ts +63 -0
  55. package/src/password.ts +74 -0
  56. package/src/roles.ts +77 -0
  57. package/src/seed.ts +146 -0
  58. package/src/session.ts +209 -0
  59. package/src/sso/contracts.ts +71 -0
  60. package/src/sso/errors.ts +53 -0
  61. package/src/sso/identity.ts +220 -0
  62. package/src/sso/index.ts +105 -0
  63. package/src/sso/login.ts +296 -0
  64. package/src/sso/oauth2.ts +235 -0
  65. package/src/sso/oidc.ts +285 -0
  66. package/src/sso/paths.ts +21 -0
  67. package/src/sso/pkce.ts +30 -0
  68. package/src/sso/providers.ts +176 -0
  69. package/src/sso/saml.ts +222 -0
  70. package/src/sso/state.ts +114 -0
  71. package/src/sso/tables.ts +77 -0
  72. package/src/tables.ts +214 -0
  73. package/src/test-support.ts +149 -0
@@ -0,0 +1,59 @@
1
+ import { sql } from "drizzle-orm";
2
+ import { pgPolicy, pgTable, primaryKey, text, timestamp, uuid } from "drizzle-orm/pg-core";
3
+ import { rlsForTable, tenantColumn } from "@facilis.dev/db";
4
+ import { users } from "../tables.js";
5
+ const identitiesRls = rlsForTable({ tenantColumn: "tenant_id" });
6
+ const statesRls = rlsForTable({ tenantColumn: "tenant_id" });
7
+ /**
8
+ * SSO identity links (D-120, SPEC §5.3): one row per `(provider, subject)` pair.
9
+ *
10
+ * The identity key is the IdP's stable subject, never the email: a user who changes their email
11
+ * at the IdP keeps the link. `email` is the address reported at the last sign-in, for operators.
12
+ *
13
+ * RLS matches `users`: restrictive tenant isolation AND-ed with a permissive "tenant scope
14
+ * present" policy, because Postgres denies by default when no permissive policy applies.
15
+ */
16
+ export const authIdentities = pgTable("auth_identities", {
17
+ provider: text("provider").notNull(),
18
+ subject: text("subject").notNull(),
19
+ userId: uuid("user_id")
20
+ .notNull()
21
+ .references(() => users.id, { onDelete: "cascade" }),
22
+ email: text("email").notNull(),
23
+ tenantId: tenantColumn(),
24
+ createdAt: timestamp("created_at").notNull().defaultNow(),
25
+ lastLoginAt: timestamp("last_login_at").notNull().defaultNow(),
26
+ }, (table) => [
27
+ primaryKey({ columns: [table.provider, table.subject] }),
28
+ ...identitiesRls.policies,
29
+ pgPolicy("auth_identities_tenant_access", {
30
+ for: "all",
31
+ using: sql `nullif(current_setting('app.tenant_id', true), '') IS NOT NULL`,
32
+ withCheck: sql `nullif(current_setting('app.tenant_id', true), '') IS NOT NULL`,
33
+ }),
34
+ ]).enableRLS();
35
+ /**
36
+ * One SSO login attempt (D-120): single-use state plus whatever the protocol needs to finish
37
+ * (`nonce`/`code_verifier` for OIDC, `request_id` for SAML, `redirect_to` for the browser).
38
+ *
39
+ * The row is written and consumed inside the audited `ctx.system` elevation, so RLS is not the
40
+ * load-bearing check here, but every scoped table ships the standard policies (SPEC §8.3).
41
+ */
42
+ export const authSsoStates = pgTable("auth_sso_states", {
43
+ state: text("state").primaryKey(),
44
+ provider: text("provider").notNull(),
45
+ nonce: text("nonce"),
46
+ codeVerifier: text("code_verifier"),
47
+ requestId: text("request_id"),
48
+ redirectTo: text("redirect_to"),
49
+ createdAt: timestamp("created_at").notNull().defaultNow(),
50
+ expiresAt: timestamp("expires_at").notNull(),
51
+ tenantId: tenantColumn(),
52
+ }, () => [
53
+ ...statesRls.policies,
54
+ pgPolicy("auth_sso_states_tenant_access", {
55
+ for: "all",
56
+ using: sql `nullif(current_setting('app.tenant_id', true), '') IS NOT NULL`,
57
+ withCheck: sql `nullif(current_setting('app.tenant_id', true), '') IS NOT NULL`,
58
+ }),
59
+ ]).enableRLS();